Fix some places where "Ethereal" wasn't capitalized and boldfaced.
[obnox/wireshark/wip.git] / packet-wsp.c
1 /* packet-wsp.c
2  *
3  * Routines to dissect WSP component of WAP traffic.
4  *
5  * $Id: packet-wsp.c,v 1.69 2003/05/25 19:36:51 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * WAP dissector based on original work by Ben Fowler
12  * Updated by Neil Hunter <neil.hunter@energis-squared.com>
13  * WTLS support by Alexandre P. Ferreira (Splice IP)
14  * Openwave header support by Dermot Bradley <dermot.bradley@openwave.com>
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <stdio.h>
36 #include <stdlib.h>
37
38 #ifdef NEED_SNPRINTF_H
39 # include "snprintf.h"
40 #endif
41
42 #include <string.h>
43 #include <glib.h>
44 #include <epan/packet.h>
45 #include <epan/ipv6-utils.h>
46 #include <epan/conversation.h>
47 #include "packet-wap.h"
48 #include "packet-wsp.h"
49
50 /* File scoped variables for the protocol and registered fields */
51 static int proto_wsp                                    = HF_EMPTY;
52
53 /* These fields used by fixed part of header */
54 static int hf_wsp_header_tid                            = HF_EMPTY;
55 static int hf_wsp_header_pdu_type                       = HF_EMPTY;
56 static int hf_wsp_version_major                         = HF_EMPTY;
57 static int hf_wsp_version_minor                         = HF_EMPTY;
58 static int hf_wsp_capability_length                     = HF_EMPTY;
59 static int hf_wsp_capabilities_section                  = HF_EMPTY;
60 static int hf_wsp_capabilities_client_SDU               = HF_EMPTY;
61 static int hf_wsp_capabilities_server_SDU               = HF_EMPTY;
62 static int hf_wsp_capabilities_protocol_opt             = HF_EMPTY;
63 static int hf_wsp_capabilities_method_MOR               = HF_EMPTY;
64 static int hf_wsp_capabilities_push_MOR                 = HF_EMPTY;
65 static int hf_wsp_capabilities_extended_methods         = HF_EMPTY;
66 static int hf_wsp_capabilities_header_code_pages        = HF_EMPTY;
67 static int hf_wsp_capabilities_aliases                  = HF_EMPTY;
68 static int hf_wsp_header_uri_len                        = HF_EMPTY;
69 static int hf_wsp_header_uri                            = HF_EMPTY;
70 static int hf_wsp_server_session_id                     = HF_EMPTY;
71 static int hf_wsp_header_status                         = HF_EMPTY;
72 static int hf_wsp_header_length                         = HF_EMPTY;
73 static int hf_wsp_headers_section                       = HF_EMPTY;
74 static int hf_wsp_header                                = HF_EMPTY;
75 static int hf_wsp_content_type                          = HF_EMPTY;
76 static int hf_wsp_content_type_str                      = HF_EMPTY;
77 static int hf_wsp_parameter_well_known_charset          = HF_EMPTY;
78 static int hf_wsp_parameter_type                        = HF_EMPTY;
79 static int hf_wsp_parameter_name                        = HF_EMPTY;
80 static int hf_wsp_parameter_filename                    = HF_EMPTY;
81 static int hf_wsp_parameter_start                       = HF_EMPTY;
82 static int hf_wsp_parameter_start_info                  = HF_EMPTY;
83 static int hf_wsp_parameter_comment                     = HF_EMPTY;
84 static int hf_wsp_parameter_domain                      = HF_EMPTY;
85 static int hf_wsp_parameter_path                        = HF_EMPTY;
86 static int hf_wsp_parameter_sec                 = HF_EMPTY;
87 static int hf_wsp_parameter_mac                 = HF_EMPTY;
88 static int hf_wsp_parameter_upart_type                  = HF_EMPTY;
89 static int hf_wsp_parameter_upart_type_value            = HF_EMPTY;
90 static int hf_wsp_reply_data                            = HF_EMPTY;
91 static int hf_wsp_post_data                             = HF_EMPTY;
92 static int hf_wsp_push_data                             = HF_EMPTY;
93 static int hf_wsp_multipart_data                        = HF_EMPTY;
94 static int hf_wsp_mpart                                 = HF_EMPTY;
95
96 static int hf_wsp_header_shift_code                     = HF_EMPTY;
97 static int hf_wsp_header_accept                         = HF_EMPTY;
98 static int hf_wsp_header_accept_str                     = HF_EMPTY;
99 static int hf_wsp_header_accept_application             = HF_EMPTY;
100 static int hf_wsp_header_accept_application_str         = HF_EMPTY;
101 static int hf_wsp_header_accept_charset                 = HF_EMPTY;
102 static int hf_wsp_header_accept_charset_str             = HF_EMPTY;
103 static int hf_wsp_header_accept_language                = HF_EMPTY;
104 static int hf_wsp_header_accept_language_str            = HF_EMPTY;
105 static int hf_wsp_header_accept_ranges                  = HF_EMPTY;
106 static int hf_wsp_header_accept_ranges_str              = HF_EMPTY;
107 static int hf_wsp_header_cache_control                  = HF_EMPTY;
108 static int hf_wsp_header_cache_control_str              = HF_EMPTY;
109 static int hf_wsp_header_cache_control_field_name       = HF_EMPTY;
110 static int hf_wsp_header_connection                     = HF_EMPTY;
111 static int hf_wsp_header_connection_str                 = HF_EMPTY;
112 static int hf_wsp_header_cache_control_field_name_str   = HF_EMPTY;
113 static int hf_wsp_header_content_length                 = HF_EMPTY;
114 static int hf_wsp_header_age                            = HF_EMPTY;
115 static int hf_wsp_header_bearer_indication              = HF_EMPTY;
116 static int hf_wsp_header_date                           = HF_EMPTY;
117 static int hf_wsp_header_etag                           = HF_EMPTY;
118 static int hf_wsp_header_expires                        = HF_EMPTY;
119 static int hf_wsp_header_last_modified                  = HF_EMPTY;
120 static int hf_wsp_header_location                       = HF_EMPTY;
121 static int hf_wsp_header_if_modified_since              = HF_EMPTY;
122 static int hf_wsp_header_profile                        = HF_EMPTY;
123 static int hf_wsp_header_pragma                         = HF_EMPTY;
124 static int hf_wsp_header_proxy_authenticate                             = HF_EMPTY;
125 static int hf_wsp_header_www_authenticate                               = HF_EMPTY;
126 static int hf_wsp_header_proxy_authorization                    = HF_EMPTY;
127 static int hf_wsp_header_proxy_authorization_scheme             = HF_EMPTY;
128 static int hf_wsp_header_proxy_authorization_user_id    = HF_EMPTY;
129 static int hf_wsp_header_proxy_authorization_password   = HF_EMPTY;
130 static int hf_wsp_header_authorization                                  = HF_EMPTY;
131 static int hf_wsp_header_authorization_scheme                   = HF_EMPTY;
132 static int hf_wsp_header_authorization_user_id                  = HF_EMPTY;
133 static int hf_wsp_header_authorization_password                 = HF_EMPTY;
134 static int hf_wsp_header_server                         = HF_EMPTY;
135 static int hf_wsp_header_user_agent                     = HF_EMPTY;
136 static int hf_wsp_header_warning                        = HF_EMPTY;
137 static int hf_wsp_header_warning_code                   = HF_EMPTY;
138 static int hf_wsp_header_warning_agent                  = HF_EMPTY;
139 static int hf_wsp_header_warning_text                   = HF_EMPTY;
140 static int hf_wsp_header_application_header             = HF_EMPTY;
141 static int hf_wsp_header_application_value              = HF_EMPTY;
142 static int hf_wsp_header_x_wap_tod                      = HF_EMPTY;
143 static int hf_wsp_header_content_ID                     = HF_EMPTY;
144 static int hf_wsp_header_transfer_encoding              = HF_EMPTY;
145 static int hf_wsp_header_transfer_encoding_str          = HF_EMPTY;
146 static int hf_wsp_header_via                            = HF_EMPTY;
147 static int hf_wsp_header_wap_application_id             = HF_EMPTY;
148 static int hf_wsp_header_wap_application_id_str         = HF_EMPTY;
149
150
151 /* Openwave-specific WSP headers */
152 static int hf_wsp_header_openwave_proxy_push_addr       = HF_EMPTY;
153 static int hf_wsp_header_openwave_proxy_push_accept     = HF_EMPTY;
154 static int hf_wsp_header_openwave_proxy_push_seq        = HF_EMPTY;
155 static int hf_wsp_header_openwave_proxy_notify          = HF_EMPTY;
156 static int hf_wsp_header_openwave_proxy_operator_domain = HF_EMPTY;
157 static int hf_wsp_header_openwave_proxy_home_page       = HF_EMPTY;
158 static int hf_wsp_header_openwave_devcap_has_color      = HF_EMPTY;
159 static int hf_wsp_header_openwave_devcap_num_softkeys   = HF_EMPTY;
160 static int hf_wsp_header_openwave_devcap_softkey_size   = HF_EMPTY;
161 static int hf_wsp_header_openwave_devcap_screen_chars   = HF_EMPTY;
162 static int hf_wsp_header_openwave_devcap_screen_pixels  = HF_EMPTY;
163 static int hf_wsp_header_openwave_devcap_em_size        = HF_EMPTY;
164 static int hf_wsp_header_openwave_devcap_screen_depth   = HF_EMPTY;
165 static int hf_wsp_header_openwave_devcap_immed_alert    = HF_EMPTY;
166 static int hf_wsp_header_openwave_proxy_net_ask         = HF_EMPTY;
167 static int hf_wsp_header_openwave_proxy_uplink_version  = HF_EMPTY;
168 static int hf_wsp_header_openwave_proxy_tod             = HF_EMPTY;
169 static int hf_wsp_header_openwave_proxy_ba_enable       = HF_EMPTY;
170 static int hf_wsp_header_openwave_proxy_ba_realm        = HF_EMPTY;
171 static int hf_wsp_header_openwave_proxy_redirect_enable = HF_EMPTY;
172 static int hf_wsp_header_openwave_proxy_request_uri     = HF_EMPTY;
173 static int hf_wsp_header_openwave_proxy_redirect_status = HF_EMPTY;
174 static int hf_wsp_header_openwave_proxy_trans_charset   = HF_EMPTY;
175 static int hf_wsp_header_openwave_proxy_trans_charset_str       = HF_EMPTY;
176 static int hf_wsp_header_openwave_proxy_linger          = HF_EMPTY;
177 static int hf_wsp_header_openwave_proxy_client_id       = HF_EMPTY;
178 static int hf_wsp_header_openwave_proxy_enable_trust    = HF_EMPTY;
179 static int hf_wsp_header_openwave_proxy_trust_old       = HF_EMPTY;
180 static int hf_wsp_header_openwave_proxy_trust           = HF_EMPTY;
181 static int hf_wsp_header_openwave_proxy_bookmark        = HF_EMPTY;
182 static int hf_wsp_header_openwave_devcap_gui            = HF_EMPTY;
183
184
185 static int hf_wsp_redirect_flags                        = HF_EMPTY;
186 static int hf_wsp_redirect_permanent                    = HF_EMPTY;
187 static int hf_wsp_redirect_reuse_security_session       = HF_EMPTY;
188 static int hf_wsp_redirect_afl                          = HF_EMPTY;
189 static int hf_wsp_redirect_afl_bearer_type_included     = HF_EMPTY;
190 static int hf_wsp_redirect_afl_port_number_included     = HF_EMPTY;
191 static int hf_wsp_redirect_afl_address_len              = HF_EMPTY;
192 static int hf_wsp_redirect_bearer_type                  = HF_EMPTY;
193 static int hf_wsp_redirect_port_num                     = HF_EMPTY;
194 static int hf_wsp_redirect_ipv4_addr                    = HF_EMPTY;
195 static int hf_wsp_redirect_ipv6_addr                    = HF_EMPTY;
196 static int hf_wsp_redirect_addr                         = HF_EMPTY;
197
198 /* Initialize the subtree pointers */
199 static gint ett_wsp                                     = ETT_EMPTY;
200 static gint ett_content_type_parameters                 = ETT_EMPTY;
201 static gint ett_header                                  = ETT_EMPTY;
202 static gint ett_headers                                 = ETT_EMPTY;
203 static gint ett_header_warning                          = ETT_EMPTY;
204 static gint ett_header_cache_control_parameters         = ETT_EMPTY;
205 static gint ett_header_cache_control_field_names        = ETT_EMPTY;
206 static gint ett_capabilities                            = ETT_EMPTY;
207 static gint ett_post                                    = ETT_EMPTY;
208 static gint ett_content_type                            = ETT_EMPTY;
209 static gint ett_redirect_flags                          = ETT_EMPTY;
210 static gint ett_redirect_afl                            = ETT_EMPTY;
211 static gint ett_multiparts                              = ETT_EMPTY;
212 static gint ett_mpartlist                               = ETT_EMPTY;
213 static gint ett_header_credentials                      = ETT_EMPTY;
214
215 /* Handle for WSP-over-UDP dissector */
216 static dissector_handle_t wsp_fromudp_handle;
217
218 /* Handle for WTP-over-UDP dissector */
219 static dissector_handle_t wtp_fromudp_handle;
220
221 /* Handle for WBXML dissector */
222 static dissector_handle_t wbxml_handle;
223
224 static const value_string vals_pdu_type[] = {
225         { 0x00, "Reserved" },
226         { 0x01, "Connect" },
227         { 0x02, "ConnectReply" },
228         { 0x03, "Redirect" },
229         { 0x04, "Reply" },
230         { 0x05, "Disconnect" },
231         { 0x06, "Push" },
232         { 0x07, "ConfirmedPush" },
233         { 0x08, "Suspend" },
234         { 0x09, "Resume" },
235
236         /* 0x10 - 0x3F Unassigned */
237
238         { 0x40, "Get" },
239         { 0x41, "Options" },
240         { 0x42, "Head" },
241         { 0x43, "Delete" },
242         { 0x44, "Trace" },
243
244         /* 0x45 - 0x4F Unassigned (Get PDU) */
245         /* 0x50 - 0x5F Extended method (Get PDU) */
246         { 0x50, "Extended Get Method 0"},
247         { 0x51, "Extended Get Method 1"},
248         { 0x52, "Extended Get Method 2"},
249         { 0x53, "Extended Get Method 3"},
250         { 0x54, "Extended Get Method 4"},
251         { 0x55, "Extended Get Method 5"},
252         { 0x56, "Extended Get Method 6"},
253         { 0x57, "Extended Get Method 7"},
254         { 0x58, "Extended Get Method 8"},
255         { 0x59, "Extended Get Method 9"},
256         { 0x5A, "Extended Get Method 10"},
257         { 0x5B, "Extended Get Method 11"},
258         { 0x5C, "Extended Get Method 12"},
259         { 0x5D, "Extended Get Method 13"},
260         { 0x5E, "Extended Get Method 14"},
261         { 0x5F, "Extended Get Method 15"},
262
263         { 0x60, "Post" },
264         { 0x61, "Put" },
265
266         /* 0x62 - 0x6F Unassigned (Post PDU) */
267         /* 0x70 - 0x7F Extended method (Post PDU) */
268         { 0x70, "Extended Post Method 0"},
269         { 0x71, "Extended Post Method 1"},
270         { 0x72, "Extended Post Method 2"},
271         { 0x73, "Extended Post Method 3"},
272         { 0x74, "Extended Post Method 4"},
273         { 0x75, "Extended Post Method 5"},
274         { 0x76, "Extended Post Method 6"},
275         { 0x77, "Extended Post Method 7"},
276         { 0x78, "Extended Post Method 8"},
277         { 0x79, "Extended Post Method 9"},
278         { 0x7A, "Extended Post Method 10"},
279         { 0x7B, "Extended Post Method 11"},
280         { 0x7C, "Extended Post Method 12"},
281         { 0x7D, "Extended Post Method 13"},
282         { 0x7E, "Extended Post Method 14"},
283         { 0x7F, "Extended Post Method 15"},
284
285         /* 0x80 - 0xFF Reserved */
286
287         { 0x00, NULL }
288
289 };
290
291 static const value_string vals_status[] = {
292         /* 0x00 - 0x0F Reserved */
293
294         { 0x10, "Continue" },
295         { 0x11, "Switching Protocols" },
296
297         { 0x20, "OK" },
298         { 0x21, "Created" },
299         { 0x22, "Accepted" },
300         { 0x23, "Non-Authoritative Information" },
301         { 0x24, "No Content" },
302         { 0x25, "Reset Content" },
303         { 0x26, "Partial Content" },
304
305         { 0x30, "Multiple Choices" },
306         { 0x31, "Moved Permanently" },
307         { 0x32, "Moved Temporarily" },
308         { 0x33, "See Other" },
309         { 0x34, "Not Modified" },
310         { 0x35, "Use Proxy" },
311         { 0x37, "Temporary Redirect" },
312
313         { 0x40, "Bad Request" },
314         { 0x41, "Unauthorised" },
315         { 0x42, "Payment Required" },
316         { 0x43, "Forbidden" },
317         { 0x44, "Not Found" },
318         { 0x45, "Method Not Allowed" },
319         { 0x46, "Not Acceptable" },
320         { 0x47, "Proxy Authentication Required" },
321         { 0x48, "Request Timeout" },
322         { 0x49, "Conflict" },
323         { 0x4A, "Gone" },
324         { 0x4B, "Length Required" },
325         { 0x4C, "Precondition Failed" },
326         { 0x4D, "Request Entity Too Large" },
327         { 0x4E, "Request-URI Too Large" },
328         { 0x4F, "Unsupported Media Type" },
329         { 0x50, "Requested Range Not Satisfiable" },
330         { 0x51, "Expectation Failed" },
331
332         { 0x60, "Internal Server Error" },
333         { 0x61, "Not Implemented" },
334         { 0x62, "Bad Gateway" },
335         { 0x63, "Service Unavailable" },
336         { 0x64, "Gateway Timeout" },
337         { 0x65, "HTTP Version Not Supported" },
338         { 0x00, NULL }
339 };
340
341 /*
342  * Field names.
343  */
344 #define FN_ACCEPT               0x00
345 #define FN_ACCEPT_CHARSET_DEP   0x01    /* encoding version 1.1, deprecated */
346 #define FN_ACCEPT_ENCODING_DEP  0x02    /* encoding version 1.1, deprecated */
347 #define FN_ACCEPT_LANGUAGE      0x03
348 #define FN_ACCEPT_RANGES        0x04
349 #define FN_AGE                  0x05
350 #define FN_ALLOW                0x06
351 #define FN_AUTHORIZATION        0x07
352 #define FN_CACHE_CONTROL_DEP    0x08    /* encoding version 1.1, deprecated */
353 #define FN_CONNECTION           0x09
354 #define FN_CONTENT_BASE         0x0A
355 #define FN_CONTENT_ENCODING     0x0B
356 #define FN_CONTENT_LANGUAGE     0x0C
357 #define FN_CONTENT_LENGTH       0x0D
358 #define FN_CONTENT_LOCATION     0x0E
359 #define FN_CONTENT_MD5          0x0F
360 #define FN_CONTENT_RANGE_DEP    0x10    /* encoding version 1.1, deprecated */
361 #define FN_CONTENT_TYPE         0x11
362 #define FN_DATE                 0x12
363 #define FN_ETAG                 0x13
364 #define FN_EXPIRES              0x14
365 #define FN_FROM                 0x15
366 #define FN_HOST                 0x16
367 #define FN_IF_MODIFIED_SINCE    0x17
368 #define FN_IF_MATCH             0x18
369 #define FN_IF_NONE_MATCH        0x19
370 #define FN_IF_RANGE             0x1A
371 #define FN_IF_UNMODIFIED_SINCE  0x1B
372 #define FN_LOCATION             0x1C
373 #define FN_LAST_MODIFIED        0x1D
374 #define FN_MAX_FORWARDS         0x1E
375 #define FN_PRAGMA               0x1F
376 #define FN_PROXY_AUTHENTICATE   0x20
377 #define FN_PROXY_AUTHORIZATION  0x21
378 #define FN_PUBLIC               0x22
379 #define FN_RANGE                0x23
380 #define FN_REFERER              0x24
381 #define FN_RETRY_AFTER          0x25
382 #define FN_SERVER               0x26
383 #define FN_TRANSFER_ENCODING    0x27
384 #define FN_UPGRADE              0x28
385 #define FN_USER_AGENT           0x29
386 #define FN_VARY                 0x2A
387 #define FN_VIA                  0x2B
388 #define FN_WARNING              0x2C
389 #define FN_WWW_AUTHENTICATE     0x2D
390 #define FN_CONTENT_DISPOSITION  0x2E
391 #define FN_X_WAP_APPLICATION_ID 0x2F
392 #define FN_X_WAP_CONTENT_URI    0x30
393 #define FN_X_WAP_INITIATOR_URI  0x31
394 #define FN_ACCEPT_APPLICATION   0x32
395 #define FN_BEARER_INDICATION    0x33
396 #define FN_PUSH_FLAG            0x34
397 #define FN_PROFILE              0x35
398 #define FN_PROFILE_DIFF         0x36
399 #define FN_PROFILE_WARNING      0x37
400 #define FN_EXPECT               0x38
401 #define FN_TE                   0x39
402 #define FN_TRAILER              0x3A
403 #define FN_ACCEPT_CHARSET       0x3B    /* encoding version 1.3 */
404 #define FN_ACCEPT_ENCODING      0x3C    /* encoding version 1.3 */
405 #define FN_CACHE_CONTROL        0x3D    /* encoding version 1.3 */
406 #define FN_CONTENT_RANGE        0x3E    /* encoding version 1.3 */
407 #define FN_X_WAP_TOD            0x3F
408 #define FN_CONTENT_ID           0x40
409 #define FN_SET_COOKIE           0x41
410 #define FN_COOKIE               0x42
411 #define FN_ENCODING_VERSION     0x43
412 #define FN_PROFILE_WARNING14    0x44    /* encoding version 1.4 */
413 #define FN_CONTENT_DISPOSITION14        0x45    /* encoding version 1.4 */
414 #define FN_X_WAP_SECURITY       0x46
415 #define FN_CACHE_CONTROL14      0x47    /* encoding version 1.4 */
416
417
418 /*
419  * Openwave field names.
420  */
421 #define FN_OPENWAVE_PROXY_PUSH_ADDR             0x00
422 #define FN_OPENWAVE_PROXY_PUSH_ACCEPT           0x01
423 #define FN_OPENWAVE_PROXY_PUSH_SEQ              0x02
424 #define FN_OPENWAVE_PROXY_NOTIFY                0x03
425 #define FN_OPENWAVE_PROXY_OPERATOR_DOMAIN       0x04
426 #define FN_OPENWAVE_PROXY_HOME_PAGE             0x05
427 #define FN_OPENWAVE_DEVCAP_HAS_COLOR            0x06
428 #define FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS         0x07
429 #define FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE         0x08
430 #define FN_OPENWAVE_DEVCAP_SCREEN_CHARS         0x09
431 #define FN_OPENWAVE_DEVCAP_SCREEN_PIXELS        0x0A
432 #define FN_OPENWAVE_DEVCAP_EM_SIZE              0x0B
433 #define FN_OPENWAVE_DEVCAP_SCREEN_DEPTH         0x0C
434 #define FN_OPENWAVE_DEVCAP_IMMED_ALERT          0x0D
435 #define FN_OPENWAVE_PROXY_NET_ASK               0x0E
436 #define FN_OPENWAVE_PROXY_UPLINK_VERSION        0x0F
437 #define FN_OPENWAVE_PROXY_TOD                   0x10
438 #define FN_OPENWAVE_PROXY_BA_ENABLE             0x11
439 #define FN_OPENWAVE_PROXY_BA_REALM              0x12
440 #define FN_OPENWAVE_PROXY_REDIRECT_ENABLE       0x13
441 #define FN_OPENWAVE_PROXY_REQUEST_URI           0x14
442 #define FN_OPENWAVE_PROXY_REDIRECT_STATUS       0x15
443 #define FN_OPENWAVE_PROXY_TRANS_CHARSET         0x16
444 #define FN_OPENWAVE_PROXY_LINGER                0x17
445 #define FN_OPENWAVE_PROXY_CLIENT_ID             0x18
446 #define FN_OPENWAVE_PROXY_ENABLE_TRUST          0x19
447 #define FN_OPENWAVE_PROXY_TRUST_OLD             0x1A
448 #define FN_OPENWAVE_PROXY_TRUST                 0x20
449 #define FN_OPENWAVE_PROXY_BOOKMARK              0x21
450 #define FN_OPENWAVE_DEVCAP_GUI                  0x22
451
452 static const value_string vals_openwave_field_names[] = {
453         { FN_OPENWAVE_PROXY_PUSH_ADDR,         "x-up-proxy-push-addr" },
454         { FN_OPENWAVE_PROXY_PUSH_ACCEPT,       "x-up-proxy-push-accept" },
455         { FN_OPENWAVE_PROXY_PUSH_SEQ,          "x-up-proxy-seq" },
456         { FN_OPENWAVE_PROXY_NOTIFY,            "x-up-proxy-notify" },
457         { FN_OPENWAVE_PROXY_OPERATOR_DOMAIN,   "x-up-proxy-operator-domain" },
458         { FN_OPENWAVE_PROXY_HOME_PAGE,         "x-up-proxy-home-page" },
459         { FN_OPENWAVE_DEVCAP_HAS_COLOR,        "x-up-devcap-has-color" },
460         { FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS,     "x-up-devcap-num-softkeys" },
461         { FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE,     "x-up-devcap-softkey-size" },
462         { FN_OPENWAVE_DEVCAP_SCREEN_CHARS,     "x-up-devcap-screen-chars" },
463         { FN_OPENWAVE_DEVCAP_SCREEN_PIXELS,    "x-up-devcap-screen-pixels" },
464         { FN_OPENWAVE_DEVCAP_EM_SIZE,          "x-up-devcap-em-size" },
465         { FN_OPENWAVE_DEVCAP_SCREEN_DEPTH,     "x-up-devcap-screen-depth" },
466         { FN_OPENWAVE_DEVCAP_IMMED_ALERT,      "x-up-devcap-immed-alert" },
467         { FN_OPENWAVE_PROXY_NET_ASK,           "x-up-proxy-net-ask" },
468         { FN_OPENWAVE_PROXY_UPLINK_VERSION,    "x-up-proxy-uplink-version" },
469         { FN_OPENWAVE_PROXY_TOD,               "x-up-proxy-tod" },
470         { FN_OPENWAVE_PROXY_BA_ENABLE,         "x-up-proxy-ba-enable" },
471         { FN_OPENWAVE_PROXY_BA_REALM,          "x-up-proxy-ba-realm" },
472         { FN_OPENWAVE_PROXY_REDIRECT_ENABLE,   "x-up-proxy-redirect-enable" },
473         { FN_OPENWAVE_PROXY_REQUEST_URI,       "x-up-proxy-request-uri" },
474         { FN_OPENWAVE_PROXY_REDIRECT_STATUS,   "x-up-proxy-redirect-status" },
475         { FN_OPENWAVE_PROXY_TRANS_CHARSET,     "x-up-proxy-trans-charset" },
476         { FN_OPENWAVE_PROXY_LINGER,            "x-up-proxy-linger" },
477         { FN_OPENWAVE_PROXY_CLIENT_ID,         "x-up-proxy-client-id" },
478         { FN_OPENWAVE_PROXY_ENABLE_TRUST,      "x-up-proxy-enable-trust" },
479         { FN_OPENWAVE_PROXY_TRUST_OLD,         "x-up-proxy-trust-old" },
480         { FN_OPENWAVE_PROXY_TRUST,             "x-up-proxy-trust" },
481         { FN_OPENWAVE_PROXY_BOOKMARK,          "x-up-proxy-bookmark" },
482         { FN_OPENWAVE_DEVCAP_GUI,              "x-up-devcap-gui" },
483         { 0,                                   NULL }
484 };
485
486
487 static const value_string vals_field_names[] = {
488         { FN_ACCEPT,               "Accept" },
489         { FN_ACCEPT_CHARSET_DEP,   "Accept-Charset (encoding 1.1)" },
490         { FN_ACCEPT_ENCODING_DEP,  "Accept-Encoding (encoding 1.1)" },
491         { FN_ACCEPT_LANGUAGE,      "Accept-Language" },
492         { FN_ACCEPT_RANGES,        "Accept-Ranges" },
493         { FN_AGE,                  "Age" },
494         { FN_ALLOW,                "Allow" },
495         { FN_AUTHORIZATION,        "Authorization" },
496         { FN_CACHE_CONTROL_DEP,    "Cache-Control (encoding 1.1)" },
497         { FN_CONNECTION,           "Connection" },
498         { FN_CONTENT_BASE,         "Content-Base" },
499         { FN_CONTENT_ENCODING,     "Content-Encoding" },
500         { FN_CONTENT_LANGUAGE,     "Content-Language" },
501         { FN_CONTENT_LENGTH,       "Content-Length" },
502         { FN_CONTENT_LOCATION,     "Content-Location" },
503         { FN_CONTENT_MD5,          "Content-MD5" },
504         { FN_CONTENT_RANGE_DEP,    "Content-Range (encoding 1.1)" },
505         { FN_CONTENT_TYPE,         "Content-Type" },
506         { FN_DATE,                 "Date" },
507         { FN_ETAG,                 "Etag" },
508         { FN_EXPIRES,              "Expires" },
509         { FN_FROM,                 "From" },
510         { FN_HOST,                 "Host" },
511         { FN_IF_MODIFIED_SINCE,    "If-Modified-Since" },
512         { FN_IF_MATCH,             "If-Match" },
513         { FN_IF_NONE_MATCH,        "If-None-Match" },
514         { FN_IF_RANGE,             "If-Range" },
515         { FN_IF_UNMODIFIED_SINCE,  "If-Unmodified-Since" },
516         { FN_LOCATION,             "Location" },
517         { FN_LAST_MODIFIED,        "Last-Modified" },
518         { FN_MAX_FORWARDS,         "Max-Forwards" },
519         { FN_PRAGMA,               "Pragma" },
520         { FN_PROXY_AUTHENTICATE,   "Proxy-Authenticate" },
521         { FN_PROXY_AUTHORIZATION,  "Proxy-Authorization" },
522         { FN_PUBLIC,               "Public" },
523         { FN_RANGE,                "Range" },
524         { FN_REFERER,              "Referer" },
525         { FN_RETRY_AFTER,          "Retry-After" },
526         { FN_SERVER,               "Server" },
527         { FN_TRANSFER_ENCODING,    "Transfer-Encoding" },
528         { FN_UPGRADE,              "Upgrade" },
529         { FN_USER_AGENT,           "User-Agent" },
530         { FN_VARY,                 "Vary" },
531         { FN_VIA,                  "Via" },
532         { FN_WARNING,              "Warning" },
533         { FN_WWW_AUTHENTICATE,     "WWW-Authenticate" },
534         { FN_CONTENT_DISPOSITION,  "Content-Disposition" },
535         { FN_X_WAP_APPLICATION_ID, "X-Wap-Application-ID" },
536         { FN_X_WAP_CONTENT_URI,    "X-Wap-Content-URI" },
537         { FN_X_WAP_INITIATOR_URI,  "X-Wap-Initiator-URI" },
538         { FN_ACCEPT_APPLICATION,   "Accept-Application" },
539         { FN_BEARER_INDICATION,    "Bearer-Indication" },
540         { FN_PUSH_FLAG,            "Push-Flag" },
541         { FN_PROFILE,              "Profile" },
542         { FN_PROFILE_DIFF,         "Profile-Diff" },
543         { FN_PROFILE_WARNING,      "Profile-Warning" },
544         { FN_EXPECT,               "Expect" },
545         { FN_TE,                   "TE" },
546         { FN_TRAILER,              "Trailer" },
547         { FN_ACCEPT_CHARSET,       "Accept-Charset" },
548         { FN_ACCEPT_ENCODING,      "Accept-Encoding" },
549         { FN_CACHE_CONTROL,        "Cache-Control" },
550         { FN_CONTENT_RANGE,        "Content-Range" },
551         { FN_X_WAP_TOD,            "X-Wap-Tod" },
552         { FN_CONTENT_ID,           "Content-ID" },
553         { FN_SET_COOKIE,           "Set-Cookie" },
554         { FN_COOKIE,               "Cookie" },
555         { FN_ENCODING_VERSION,     "Encoding-Version" },
556         { FN_PROFILE_WARNING14,    "Profile-Warning (encoding 1.4)" },
557         { FN_CONTENT_DISPOSITION14,"Content-Disposition (encoding 1.4)" },
558         { FN_X_WAP_SECURITY,       "X-WAP-Security" },
559         { FN_CACHE_CONTROL14,      "Cache-Control (encoding 1.4)" },
560         { 0,                       NULL }
561 };
562
563 /*
564  * Bearer types (from the WDP specification).
565  */
566 #define BT_IPv4                 0x00
567 #define BT_IPv6                 0x01
568 #define BT_GSM_USSD             0x02
569 #define BT_GSM_SMS              0x03
570 #define BT_ANSI_136_GUTS        0x04
571 #define BT_IS_95_SMS            0x05
572 #define BT_IS_95_CSD            0x06
573 #define BT_IS_95_PACKET_DATA    0x07
574 #define BT_ANSI_136_CSD         0x08
575 #define BT_ANSI_136_PACKET_DATA 0x09
576 #define BT_GSM_CSD              0x0A
577 #define BT_GSM_GPRS             0x0B
578 #define BT_GSM_USSD_IPv4        0x0C
579 #define BT_AMPS_CDPD            0x0D
580 #define BT_PDC_CSD              0x0E
581 #define BT_PDC_PACKET_DATA      0x0F
582 #define BT_IDEN_SMS             0x10
583 #define BT_IDEN_CSD             0x11
584 #define BT_IDEN_PACKET_DATA     0x12
585 #define BT_PAGING_FLEX          0x13
586 #define BT_PHS_SMS              0x14
587 #define BT_PHS_CSD              0x15
588 #define BT_GSM_USSD_GSM_SC      0x16
589 #define BT_TETRA_SDS_ITSI       0x17
590 #define BT_TETRA_SDS_MSISDN     0x18
591 #define BT_TETRA_PACKET_DATA    0x19
592 #define BT_PAGING_REFLEX        0x1A
593 #define BT_GSM_USSD_MSISDN      0x1B
594 #define BT_MOBITEX_MPAK         0x1C
595 #define BT_ANSI_136_GHOST       0x1D
596
597 static const value_string vals_bearer_types[] = {
598         { BT_IPv4,                 "IPv4" },
599         { BT_IPv6,                 "IPv6" },
600         { BT_GSM_USSD,             "GSM USSD" },
601         { BT_GSM_SMS,              "GSM SMS" },
602         { BT_ANSI_136_GUTS,        "ANSI-136 GUTS/R-Data" },
603         { BT_IS_95_SMS,            "IS-95 CDMA SMS" },
604         { BT_IS_95_CSD,            "IS-95 CDMA CSD" },
605         { BT_IS_95_PACKET_DATA,    "IS-95 CDMA Packet data" },
606         { BT_ANSI_136_CSD,         "ANSI-136 CSD" },
607         { BT_ANSI_136_PACKET_DATA, "ANSI-136 Packet data" },
608         { BT_GSM_CSD,              "GSM CSD" },
609         { BT_GSM_GPRS,             "GSM GPRS" },
610         { BT_GSM_USSD_IPv4,        "GSM USSD (IPv4 addresses)" },
611         { BT_AMPS_CDPD,            "AMPS CDPD" },
612         { BT_PDC_CSD,              "PDC CSD" },
613         { BT_PDC_PACKET_DATA,      "PDC Packet data" },
614         { BT_IDEN_SMS,             "IDEN SMS" },
615         { BT_IDEN_CSD,             "IDEN CSD" },
616         { BT_IDEN_PACKET_DATA,     "IDEN Packet data" },
617         { BT_PAGING_FLEX,          "Paging network FLEX(TM)" },
618         { BT_PHS_SMS,              "PHS SMS" },
619         { BT_PHS_CSD,              "PHS CSD" },
620         { BT_GSM_USSD_GSM_SC,      "GSM USSD (GSM Service Code addresses)" },
621         { BT_TETRA_SDS_ITSI,       "TETRA SDS (ITSI addresses)" },
622         { BT_TETRA_SDS_MSISDN,     "TETRA SDS (MSISDN addresses)" },
623         { BT_TETRA_PACKET_DATA,    "TETRA Packet data" },
624         { BT_PAGING_REFLEX,        "Paging network ReFLEX(TM)" },
625         { BT_GSM_USSD_MSISDN,      "GSM USSD (MSISDN addresses)" },
626         { BT_MOBITEX_MPAK,         "Mobitex MPAK" },
627         { BT_ANSI_136_GHOST,       "ANSI-136 GHOST/R-Data" },
628         { 0,                       NULL }
629 };
630
631 static const value_string vals_content_types[] = {
632         { 0x00, "*/*" },
633         { 0x01, "text/*" },
634         { 0x02, "text/html" },
635         { 0x03, "text/plain" },
636         { 0x04, "text/x-hdml" },
637         { 0x05, "text/x-ttml" },
638         { 0x06, "text/x-vCalendar" },
639         { 0x07, "text/x-vCard" },
640         { 0x08, "text/vnd.wap.wml" },
641         { 0x09, "text/vnd.wap.wmlscript" },
642         { 0x0A, "text/vnd.wap.channel" },
643         { 0x0B, "Multipart/*" },
644         { 0x0C, "Multipart/mixed" },
645         { 0x0D, "Multipart/form-data" },
646         { 0x0E, "Multipart/byteranges" },
647         { 0x0F, "Multipart/alternative" },
648         { 0x10, "application/*" },
649         { 0x11, "application/java-vm" },
650         { 0x12, "application/x-www-form-urlencoded" },
651         { 0x13, "application/x-hdmlc" },
652         { 0x14, "application/vnd.wap.wmlc" },
653         { 0x15, "application/vnd.wap.wmlscriptc" },
654         { 0x16, "application/vnd.wap.channelc" },
655         { 0x17, "application/vnd.wap.uaprof" },
656         { 0x18, "application/vnd.wap.wtls-ca-certificate" },
657         { 0x19, "application/vnd.wap.wtls-user-certificate" },
658         { 0x1A, "application/x-x509-ca-cert" },
659         { 0x1B, "application/x-x509-user-cert" },
660         { 0x1C, "image/*" },
661         { 0x1D, "image/gif" },
662         { 0x1E, "image/jpeg" },
663         { 0x1F, "image/tiff" },
664         { 0x20, "image/png" },
665         { 0x21, "image/vnd.wap.wbmp" },
666         { 0x22, "application/vnd.wap.multipart.*" },
667         { 0x23, "application/vnd.wap.multipart.mixed" },
668         { 0x24, "application/vnd.wap.multipart.form-data" },
669         { 0x25, "application/vnd.wap.multipart.byteranges" },
670         { 0x26, "application/vnd.wap.multipart.alternative" },
671         { 0x27, "application/xml" },
672         { 0x28, "text/xml" },
673         { 0x29, "application/vnd.wap.wbxml" },
674         { 0x2A, "application/x-x968-cross-cert" },
675         { 0x2B, "application/x-x968-ca-cert" },
676         { 0x2C, "application/x-x968-user-cert" },
677         { 0x2D, "text/vnd.wap.si" },
678         { 0x2E, "application/vnd.wap.sic" },
679         { 0x2F, "text/vnd.wap.sl" },
680         { 0x30, "application/vnd.wap.slc" },
681         { 0x31, "text/vnd.wap.co" },
682         { 0x32, "application/vnd.wap.coc" },
683         { 0x33, "application/vnd.wap.multipart.related" },
684         { 0x34, "application/vnd.wap.sia" },
685         { 0x35, "text/vnd.wap.connectivity-xml" },
686         { 0x36, "application/vnd.wap.connectivity-wbxml" },
687         { 0x37, "application/pkcs7-mime" },
688         { 0x38, "application/vnd.wap.hashed-certificate" },
689         { 0x39, "application/vnd.wap.signed-certificate" },
690         { 0x3A, "application/vnd.wap.cert-response" },
691         { 0x3B, "application/xhtml+xml" },
692         { 0x3C, "application/wml+xml" },
693         { 0x3D, "text/css" },
694         { 0x3E, "application/vnd.wap.mms-message" },
695         { 0x3F, "application/vnd.wap.rollover-certificate" },
696         { 0x201, "application/vnd.uplanet.cachop-wbxml" },
697         { 0x202, "application/vnd.uplanet.signal" },
698         { 0x203, "application/vnd.uplanet.alert-wbxml" },
699         { 0x204, "application/vnd.uplanet.list-wbxml" },
700         { 0x205, "application/vnd.uplanet.listcmd-wbxml" },
701         { 0x206, "application/vnd.uplanet.channel-wbxml" },
702         { 0x207, "application/vnd.uplanet.provisioning-status-uri" },
703         { 0x208, "x-wap.multipart/vnd.uplanet.header-set" },
704         { 0x209, "application/vnd.uplanet.bearer-choice-wbxml" },
705         { 0x20A, "application/vnd.phonecom.mmc-wbxml" },
706         { 0x20B, "application/vnd.nokia.syncset+wbxml" },
707         { 0x00, NULL }
708 };
709
710 static const value_string vals_languages[] = {
711         { 0x01, "Afar (aa)" },
712         { 0x02, "Abkhazian (ab)" },
713         { 0x03, "Afrikaans (af)" },
714         { 0x04, "Amharic (am)" },
715         { 0x05, "Arabic (ar)" },
716         { 0x06, "Assamese (as)" },
717         { 0x07, "Aymara (ay)" },
718         { 0x08, "Azerbaijani (az)" },
719         { 0x09, "Bashkir (ba)" },
720         { 0x0A, "Byelorussian (be)" },
721         { 0x0B, "Bulgarian (bg)" },
722         { 0x0C, "Bihari (bh)" },
723         { 0x0D, "Bislama (bi)" },
724         { 0x0E, "Bengali; Bangla (bn)" },
725         { 0x0F, "Tibetan (bo)" },
726         { 0x10, "Breton (br)" },
727         { 0x11, "Catalan (ca)" },
728         { 0x12, "Corsican (co)" },
729         { 0x13, "Czech (cs)" },
730         { 0x14, "Welsh (cy)" },
731         { 0x15, "Danish (da)" },
732         { 0x16, "German (de)" },
733         { 0x17, "Bhutani (dz)" },
734         { 0x18, "Greek (el)" },
735         { 0x19, "English (en)" },
736         { 0x1A, "Esperanto (eo)" },
737         { 0x1B, "Spanish (es)" },
738         { 0x1C, "Estonian (et)" },
739         { 0x1D, "Basque (eu)" },
740         { 0x1E, "Persian (fa)" },
741         { 0x1F, "Finnish (fi)" },
742         { 0x20, "Fiji (fj)" },
743         { 0x21, "Urdu (ur)" },
744         { 0x22, "French (fr)" },
745         { 0x23, "Uzbek (uz)" },
746         { 0x24, "Irish (ga)" },
747         { 0x25, "Scots Gaelic (gd)" },
748         { 0x26, "Galician (gl)" },
749         { 0x27, "Guarani (gn)" },
750         { 0x28, "Gujarati (gu)" },
751         { 0x29, "Hausa (ha)" },
752         { 0x2A, "Hebrew (formerly iw) (he)" },
753         { 0x2B, "Hindi (hi)" },
754         { 0x2C, "Croatian (hr)" },
755         { 0x2D, "Hungarian (hu)" },
756         { 0x2E, "Armenian (hy)" },
757         { 0x2F, "Vietnamese (vi)" },
758         { 0x30, "Indonesian (formerly in) (id)" },
759         { 0x31, "Wolof (wo)" },
760         { 0x32, "Xhosa (xh)" },
761         { 0x33, "Icelandic (is)" },
762         { 0x34, "Italian (it)" },
763         { 0x35, "Yoruba (yo)" },
764         { 0x36, "Japanese (ja)" },
765         { 0x37, "Javanese (jw)" },
766         { 0x38, "Georgian (ka)" },
767         { 0x39, "Kazakh (kk)" },
768         { 0x3A, "Zhuang (za)" },
769         { 0x3B, "Cambodian (km)" },
770         { 0x3C, "Kannada (kn)" },
771         { 0x3D, "Korean (ko)" },
772         { 0x3E, "Kashmiri (ks)" },
773         { 0x3F, "Kurdish (ku)" },
774         { 0x40, "Kirghiz (ky)" },
775         { 0x41, "Chinese (zh)" },
776         { 0x42, "Lingala (ln)" },
777         { 0x43, "Laothian (lo)" },
778         { 0x44, "Lithuanian (lt)" },
779         { 0x45, "Latvian, Lettish (lv)" },
780         { 0x46, "Malagasy (mg)" },
781         { 0x47, "Maori (mi)" },
782         { 0x48, "Macedonian (mk)" },
783         { 0x49, "Malayalam (ml)" },
784         { 0x4A, "Mongolian (mn)" },
785         { 0x4B, "Moldavian (mo)" },
786         { 0x4C, "Marathi (mr)" },
787         { 0x4D, "Malay (ms)" },
788         { 0x4E, "Maltese (mt)" },
789         { 0x4F, "Burmese (my)" },
790         { 0x50, "Ukrainian (uk)" },
791         { 0x51, "Nepali (ne)" },
792         { 0x52, "Dutch (nl)" },
793         { 0x53, "Norwegian (no)" },
794         { 0x54, "Occitan (oc)" },
795         { 0x55, "(Afan) Oromo (om)" },
796         { 0x56, "Oriya (or)" },
797         { 0x57, "Punjabi (pa)" },
798         { 0x58, "Polish (po)" },
799         { 0x59, "Pashto, Pushto (ps)" },
800         { 0x5A, "Portuguese (pt)" },
801         { 0x5B, "Quechua (qu)" },
802         { 0x5C, "Zulu (zu)" },
803         { 0x5D, "Kirundi (rn)" },
804         { 0x5E, "Romanian (ro)" },
805         { 0x5F, "Russian (ru)" },
806         { 0x60, "Kinyarwanda (rw)" },
807         { 0x61, "Sanskrit (sa)" },
808         { 0x62, "Sindhi (sd)" },
809         { 0x63, "Sangho (sg)" },
810         { 0x64, "Serbo-Croatian (sh)" },
811         { 0x65, "Sinhalese (si)" },
812         { 0x66, "Slovak (sk)" },
813         { 0x67, "Slovenian (sl)" },
814         { 0x68, "Samoan (sm)" },
815         { 0x69, "Shona (sn)" },
816         { 0x6A, "Somali (so)" },
817         { 0x6B, "Albanian (sq)" },
818         { 0x6C, "Serbian (sr)" },
819         { 0x6D, "Siswati (ss)" },
820         { 0x6E, "Sesotho (st)" },
821         { 0x6F, "Sundanese (su)" },
822         { 0x70, "Swedish (sv)" },
823         { 0x71, "Swahili (sw)" },
824         { 0x72, "Tamil (ta)" },
825         { 0x73, "Telugu (te)" },
826         { 0x74, "Tajik (tg)" },
827         { 0x75, "Thai (th)" },
828         { 0x76, "Tigrinya (ti)" },
829         { 0x77, "Turkmen (tk)" },
830         { 0x78, "Tagalog (tl)" },
831         { 0x79, "Setswana (tn)" },
832         { 0x7A, "Tonga (to)" },
833         { 0x7B, "Turkish (tr)" },
834         { 0x7C, "Tsonga (ts)" },
835         { 0x7D, "Tatar (tt)" },
836         { 0x7E, "Twi (tw)" },
837         { 0x7F, "Uighur (ug)" },
838         { 0x81, "Nauru (na)" },
839         { 0x82, "Faeroese (fo)" },
840         { 0x83, "Frisian (fy)" },
841         { 0x84, "Interlingua (ia)" },
842         { 0x85, "Volapuk (vo)" },
843         { 0x86, "Interlingue (ie)" },
844         { 0x87, "Inupiak (ik)" },
845         { 0x88, "Yiddish (formerly ji) (yi)" },
846         { 0x89, "Inuktitut (iu)" },
847         { 0x8A, "Greenlandic (kl)" },
848         { 0x8B, "Latin (la)" },
849         { 0x8C, "Rhaeto-Romance (rm)" },
850         { 0x00, NULL }
851 };
852
853 static const value_string vals_accept_ranges[] = {
854         { 0x00, "None" },
855         { 0x01, "Bytes" },
856         { 0x00, NULL }
857 };
858
859 #define NO_CACHE                0x00
860 #define NO_STORE                0x01
861 #define MAX_AGE                 0x02
862 #define MAX_STALE               0x03
863 #define MIN_FRESH               0x04
864 #define ONLY_IF_CACHED          0x05
865 #define PUBLIC                  0x06
866 #define PRIVATE                 0x07
867 #define NO_TRANSFORM            0x08
868 #define MUST_REVALIDATE         0x09
869 #define PROXY_REVALIDATE        0x0A
870 #define S_MAXAGE                0x0B
871
872 static const value_string vals_cache_control[] = {
873         { NO_CACHE,         "No-cache" },
874         { NO_STORE,         "No-store" },
875         { MAX_AGE,          "Max-age" },
876         { MAX_STALE,        "Max-stale" },
877         { MIN_FRESH,        "Min-fresh" },
878         { ONLY_IF_CACHED,   "Only-if-cached" },
879         { PUBLIC,           "Public" },
880         { PRIVATE,          "Private" },
881         { NO_TRANSFORM,     "No-transform" },
882         { MUST_REVALIDATE,  "Must-revalidate" },
883         { PROXY_REVALIDATE, "Proxy-revalidate" },
884         { S_MAXAGE,         "S-max-age" },
885         { 0x00,             NULL }
886 };
887
888 static const value_string vals_connection[] = {
889         { 0x00, "Close" },
890         { 0x00, NULL }
891 };
892
893 static const value_string vals_transfer_encoding[] = {
894         { 0x00, "Chunked" },
895         { 0x00, NULL }
896 };
897
898
899 /* Parameters and well-known encodings */
900 static const value_string vals_wsp_parameter_sec[] = {
901         { 0x00, "NETWPIN" },
902         { 0x01, "USERPIN" },
903         { 0x02, "USERNETWPIN" },
904         { 0x03, "USERPINMAC" },
905
906         { 0x00, NULL }
907 };
908
909 /* Warning codes and mappings */
910 static const value_string vals_wsp_warning_code[] = {
911         { 10, "110 Response is stale" },
912         { 11, "111 Revalidation failed" },
913         { 12, "112 Disconnected operation" },
914         { 13, "113 Heuristic expiration" },
915         { 14, "214 Transformation applied" },
916         { 99, "199/299 Miscellaneous warning" },
917
918         { 0, NULL }
919 };
920
921 static const value_string vals_wsp_warning_code_short[] = {
922         { 10, "110" },
923         { 11, "111" },
924         { 12, "112" },
925         { 13, "113" },
926         { 14, "214" },
927         { 99, "199/299" },
928
929         { 0, NULL }
930 };
931
932
933 /*
934  * Redirect flags.
935  */
936 #define PERMANENT_REDIRECT      0x80
937 #define REUSE_SECURITY_SESSION  0x40
938
939 /*
940  * Redirect address flags and length.
941  */
942 #define BEARER_TYPE_INCLUDED    0x80
943 #define PORT_NUMBER_INCLUDED    0x40
944 #define ADDRESS_LEN             0x3f
945
946 static const true_false_string yes_no_truth = {
947         "Yes" ,
948         "No"
949 };
950
951 /*
952  * Windows appears to define DELETE.
953  */
954 #ifdef DELETE
955 #undef DELETE
956 #endif
957
958 enum {
959         RESERVED                = 0x00,
960         CONNECT                 = 0x01,
961         CONNECTREPLY            = 0x02,
962         REDIRECT                = 0x03,                 /* No sample data */
963         REPLY                   = 0x04,
964         DISCONNECT              = 0x05,
965         PUSH                    = 0x06,                 /* No sample data */
966         CONFIRMEDPUSH           = 0x07,                 /* No sample data */
967         SUSPEND                 = 0x08,                 /* No sample data */
968         RESUME                  = 0x09,                 /* No sample data */
969
970         GET                     = 0x40,
971         OPTIONS                 = 0x41,                 /* No sample data */
972         HEAD                    = 0x42,                 /* No sample data */
973         DELETE                  = 0x43,                 /* No sample data */
974         TRACE                   = 0x44,                 /* No sample data */
975
976         POST                    = 0x60,
977         PUT                     = 0x61,                 /* No sample data */
978 };
979
980 #define VAL_STRING_SIZE 200
981
982 typedef enum {
983         VALUE_LEN_SUPPLIED,
984         VALUE_IS_TEXT_STRING,
985         VALUE_IN_LEN,
986 } value_type_t;
987
988 static dissector_table_t wsp_dissector_table;
989 static heur_dissector_list_t heur_subdissector_list;
990
991 static void add_uri (proto_tree *, packet_info *, tvbuff_t *, guint, guint);
992 static void add_headers (proto_tree *, tvbuff_t *);
993 static int add_well_known_header (proto_tree *, tvbuff_t *, int, guint8);
994 static int add_unknown_header (proto_tree *, tvbuff_t *, int, guint8);
995 static int add_application_header (proto_tree *, tvbuff_t *, int);
996 static void add_accept_header (proto_tree *, tvbuff_t *, int,
997     tvbuff_t *, value_type_t, int);
998 static void add_accept_xxx_header (proto_tree *, tvbuff_t *, int,
999     tvbuff_t *, value_type_t, int, int, int, const value_string *,
1000     const char *);
1001 static void add_accept_ranges_header (proto_tree *, tvbuff_t *, int,
1002     tvbuff_t *, value_type_t, int);
1003 static void add_cache_control_header (proto_tree *, tvbuff_t *, int,
1004     tvbuff_t *, value_type_t, int);
1005 static int add_cache_control_field_name (proto_tree *, tvbuff_t *, int, guint);
1006 static void add_connection_header (proto_tree *, tvbuff_t *, int,
1007     tvbuff_t *, value_type_t, int);
1008 static void add_content_type_value (proto_tree *, tvbuff_t *, int, int,
1009     tvbuff_t *, value_type_t, int, int, int, guint *, const char **);
1010 static void add_wap_application_id_header (proto_tree *, tvbuff_t *, int,
1011     tvbuff_t *, value_type_t, int);
1012 static void add_integer_value_header_common (proto_tree *, tvbuff_t *, int,
1013     tvbuff_t *, value_type_t, int, int, guint8, const value_string *);
1014 static void add_integer_value_header (proto_tree *, tvbuff_t *, int,
1015     tvbuff_t *, value_type_t, int, int, guint8);
1016 static void add_string_value_header_common (proto_tree *, tvbuff_t *, int,
1017     tvbuff_t *, value_type_t, int, int, guint8, const value_string *);
1018 static void add_string_value_header (proto_tree *, tvbuff_t *, int,
1019     tvbuff_t *, value_type_t, int, int, guint8);
1020 static void add_quoted_string_value_header (proto_tree *, tvbuff_t *, int,
1021     tvbuff_t *, value_type_t, int, int, guint8);
1022 static void add_date_value_header (proto_tree *, tvbuff_t *, int,
1023     tvbuff_t *, value_type_t, int, int, guint8);
1024 static int add_parameter (proto_tree *, tvbuff_t *, int);
1025 static int add_untyped_parameter (proto_tree *, tvbuff_t *, int, int);
1026 static int add_parameter_charset (proto_tree *, tvbuff_t *, int, int);
1027 static int add_constrained_encoding (proto_tree *, tvbuff_t *, int, int);
1028 static int add_parameter_type (proto_tree *, tvbuff_t *, int, int);
1029 static int add_parameter_text (proto_tree *, tvbuff_t *, int, int, int, const char *);
1030 static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
1031 static void add_multipart_data (proto_tree *, tvbuff_t *);
1032 static void add_pragma_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
1033     value_type_t, int);
1034 static void add_transfer_encoding_header (proto_tree *, tvbuff_t *, int,
1035     tvbuff_t *, value_type_t, int);
1036 static void add_warning_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
1037     value_type_t, int);
1038 static void add_accept_application_header (proto_tree *, tvbuff_t *, int,
1039     tvbuff_t *, value_type_t, int);
1040 static void add_credentials_value_header (proto_tree *tree,
1041                 tvbuff_t *header_buff, int headerLen, tvbuff_t *value_buff,
1042                 value_type_t valueType, int valueLen,
1043                 int hf_main, int hf_scheme, int hf_basic_user_id, int hf_basic_password);
1044 static void add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type);
1045 static void add_capability_vals(tvbuff_t *, gboolean, int, guint, guint, char *, size_t);
1046 static value_type_t get_value_type_len (tvbuff_t *, int, guint *, int *, int *);
1047 static guint get_uintvar (tvbuff_t *, guint, guint);
1048 static gint get_integer (tvbuff_t *, guint, guint, value_type_t, guint *);
1049
1050 static int add_well_known_openwave_header (proto_tree *, tvbuff_t *, int, guint8);
1051 static void add_openwave_integer_value_header (proto_tree *, tvbuff_t *, int,
1052     tvbuff_t *, value_type_t, int, int, guint8);
1053 static void add_openwave_string_value_header (proto_tree *, tvbuff_t *, int,
1054     tvbuff_t *, value_type_t, int, int, guint8);
1055
1056
1057 /* Code to actually dissect the packets */
1058 static void
1059 dissect_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
1060     proto_tree *tree, dissector_handle_t dissector_handle)
1061 {
1062         guint8 flags;
1063         proto_item *ti;
1064         proto_tree *flags_tree;
1065         guint8 bearer_type;
1066         guint8 address_flags_len;
1067         int address_len;
1068         proto_tree *atf_tree;
1069         guint16 port_num;
1070         guint32 address_ipv4;
1071         struct e_in6_addr address_ipv6;
1072         address redir_address;
1073         conversation_t *conv;
1074
1075         flags = tvb_get_guint8 (tvb, offset);
1076         if (tree) {
1077                 ti = proto_tree_add_uint (tree, hf_wsp_redirect_flags,
1078                     tvb, offset, 1, flags);
1079                 flags_tree = proto_item_add_subtree (ti, ett_redirect_flags);
1080                 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_permanent,
1081                     tvb, offset, 1, flags);
1082                 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_reuse_security_session,
1083                     tvb, offset, 1, flags);
1084         }
1085         offset++;
1086         while (tvb_reported_length_remaining (tvb, offset) > 0) {
1087                 address_flags_len = tvb_get_guint8 (tvb, offset);
1088                 if (tree) {
1089                         ti = proto_tree_add_uint (tree, hf_wsp_redirect_afl,
1090                             tvb, offset, 1, address_flags_len);
1091                         atf_tree = proto_item_add_subtree (ti, ett_redirect_afl);
1092                         proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_bearer_type_included,
1093                             tvb, offset, 1, address_flags_len);
1094                         proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_port_number_included,
1095                             tvb, offset, 1, address_flags_len);
1096                         proto_tree_add_uint (atf_tree, hf_wsp_redirect_afl_address_len,
1097                             tvb, offset, 1, address_flags_len);
1098                 }
1099                 offset++;
1100                 if (address_flags_len & BEARER_TYPE_INCLUDED) {
1101                         bearer_type = tvb_get_guint8 (tvb, offset);
1102                         if (tree) {
1103                                 proto_tree_add_uint (tree, hf_wsp_redirect_bearer_type,
1104                                     tvb, offset, 1, bearer_type);
1105                         }
1106                         offset++;
1107                 } else
1108                         bearer_type = 0x00;     /* XXX */
1109                 if (address_flags_len & PORT_NUMBER_INCLUDED) {
1110                         port_num = tvb_get_ntohs (tvb, offset);
1111                         if (tree) {
1112                                 proto_tree_add_uint (tree, hf_wsp_redirect_port_num,
1113                                     tvb, offset, 2, port_num);
1114                         }
1115                         offset += 2;
1116                 } else {
1117                         /*
1118                          * Redirecting to the same server port number as was
1119                          * being used, i.e. the source port number of this
1120                          * redirect.
1121                          */
1122                         port_num = pinfo->srcport;
1123                 }
1124                 address_len = address_flags_len & ADDRESS_LEN;
1125                 if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
1126                         /*
1127                          * We don't have the bearer type in the message,
1128                          * so we don't know the address type.
1129                          * (It's the same bearer type as the original
1130                          * connection.)
1131                          */
1132                         goto unknown_address_type;
1133                 }
1134
1135                 /*
1136                  * We know the bearer type, so we know the address type.
1137                  */
1138                 switch (bearer_type) {
1139
1140                 case BT_IPv4:
1141                 case BT_IS_95_CSD:
1142                 case BT_IS_95_PACKET_DATA:
1143                 case BT_ANSI_136_CSD:
1144                 case BT_ANSI_136_PACKET_DATA:
1145                 case BT_GSM_CSD:
1146                 case BT_GSM_GPRS:
1147                 case BT_GSM_USSD_IPv4:
1148                 case BT_AMPS_CDPD:
1149                 case BT_PDC_CSD:
1150                 case BT_PDC_PACKET_DATA:
1151                 case BT_IDEN_CSD:
1152                 case BT_IDEN_PACKET_DATA:
1153                 case BT_PHS_CSD:
1154                 case BT_TETRA_PACKET_DATA:
1155                         /*
1156                          * IPv4.
1157                          */
1158                         if (address_len != 4) {
1159                                 /*
1160                                  * Say what?
1161                                  */
1162                                 goto unknown_address_type;
1163                         }
1164                         tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
1165                         if (tree) {
1166                                 proto_tree_add_ipv4 (tree,
1167                                     hf_wsp_redirect_ipv4_addr,
1168                                     tvb, offset, 4, address_ipv4);
1169                         }
1170
1171                         /*
1172                          * Create a conversation so that the
1173                          * redirected session will be dissected
1174                          * as WAP.
1175                          */
1176                         redir_address.type = AT_IPv4;
1177                         redir_address.len = 4;
1178                         redir_address.data = (const guint8 *)&address_ipv4;
1179                         conv = find_conversation(&redir_address, &pinfo->dst,
1180                             PT_UDP, port_num, 0, NO_PORT_B);
1181                         if (conv == NULL) {
1182                                 conv = conversation_new(&redir_address,
1183                                     &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
1184                         }
1185                         conversation_set_dissector(conv, dissector_handle);
1186                         break;
1187
1188                 case BT_IPv6:
1189                         /*
1190                          * IPv6.
1191                          */
1192                         if (address_len != 16) {
1193                                 /*
1194                                  * Say what?
1195                                  */
1196                                 goto unknown_address_type;
1197                         }
1198                         tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
1199                         if (tree) {
1200                                 proto_tree_add_ipv6 (tree,
1201                                     hf_wsp_redirect_ipv6_addr,
1202                                     tvb, offset, 16, (guint8 *)&address_ipv6);
1203                         }
1204
1205                         /*
1206                          * Create a conversation so that the
1207                          * redirected session will be dissected
1208                          * as WAP.
1209                          */
1210                         redir_address.type = AT_IPv6;
1211                         redir_address.len = 16;
1212                         redir_address.data = (const guint8 *)&address_ipv4;
1213                         conv = find_conversation(&redir_address, &pinfo->dst,
1214                             PT_UDP, port_num, 0, NO_PORT_B);
1215                         if (conv == NULL) {
1216                                 conv = conversation_new(&redir_address,
1217                                     &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
1218                         }
1219                         conversation_set_dissector(conv, dissector_handle);
1220                         break;
1221
1222                 unknown_address_type:
1223                 default:
1224                         if (address_len != 0) {
1225                                 if (tree) {
1226                                         proto_tree_add_item (tree,
1227                                             hf_wsp_redirect_addr,
1228                                             tvb, offset, address_len,
1229                                             bo_little_endian);
1230                                 }
1231                         }
1232                         break;
1233                 }
1234                 offset += address_len;
1235         }
1236 }
1237
1238 static void
1239 dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1240     dissector_handle_t dissector_handle, gboolean is_connectionless)
1241 {
1242         int offset = 0;
1243
1244         guint8 pdut;
1245         guint count = 0;
1246         guint value = 0;
1247         guint uriLength = 0;
1248         guint uriStart = 0;
1249         guint capabilityLength = 0;
1250         guint capabilityStart = 0;
1251         guint headersLength = 0;
1252         guint headerLength = 0;
1253         guint headerStart = 0;
1254         guint nextOffset = 0;
1255         guint contentTypeStart = 0;
1256         guint contentType = 0;
1257         const char *contentTypeStr;
1258         tvbuff_t *tmp_tvb;
1259
1260 /* Set up structures we will need to add the protocol subtree and manage it */
1261         proto_item *ti;
1262         proto_tree *wsp_tree = NULL;
1263 /*      proto_tree *wsp_header_fixed; */
1264
1265 /* This field shows up as the "Info" column in the display; you should make
1266    it, if possible, summarize what's in the packet, so that a user looking
1267    at the list of packets can tell what type of packet it is. */
1268
1269         /* Connection-less mode has a TID first */
1270         if (is_connectionless)
1271         {
1272                 offset++;
1273         };
1274
1275         /* Find the PDU type */
1276         pdut = tvb_get_guint8 (tvb, offset);
1277
1278         /* Develop the string to put in the Info column */
1279         if (check_col(pinfo->cinfo, COL_INFO))
1280         {
1281                 col_append_fstr(pinfo->cinfo, COL_INFO, "WSP %s",
1282                         val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"));
1283         };
1284
1285 /* In the interest of speed, if "tree" is NULL, don't do any work not
1286    necessary to generate protocol tree items. */
1287         if (tree) {
1288                 ti = proto_tree_add_item(tree, proto_wsp, tvb, 0, -1,
1289                     bo_little_endian);
1290                 wsp_tree = proto_item_add_subtree(ti, ett_wsp);
1291
1292 /* Code to process the packet goes here */
1293 /*
1294                 wsp_header_fixed = proto_item_add_subtree(ti, ett_header );
1295 */
1296
1297                 /* Add common items: only TID and PDU Type */
1298
1299                 /* If this is connectionless, then the TID Field is always first */
1300                 if (is_connectionless)
1301                 {
1302                         ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,tvb,
1303                                 0,1,bo_little_endian);
1304                 }
1305
1306                 ti = proto_tree_add_item(
1307                                 wsp_tree,               /* tree */
1308                                 hf_wsp_header_pdu_type, /* id */
1309                                 tvb,
1310                                 offset,                 /* start of high light */
1311                                 1,                      /* length of high light */
1312                                 bo_little_endian        /* value */
1313                      );
1314         }
1315         offset++;
1316
1317         /* Map extended methods to the main method now the Column info has been written;
1318          * this way we can dissect the extended method PDUs. */
1319         if ((pdut >= 0x50) && (pdut <= 0x5F))
1320                 pdut = GET;
1321         else if ((pdut >= 0x70) && (pdut <= 0x7F))
1322                 pdut = POST;
1323
1324         switch (pdut)
1325         {
1326                 case CONNECT:
1327                 case CONNECTREPLY:
1328                 case RESUME:
1329                         if (tree) {
1330                                 if (pdut == CONNECT)
1331                                 {
1332                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,tvb,offset,1,bo_little_endian);
1333                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,tvb,offset,1,bo_little_endian);
1334                                         offset++;
1335                                 } else {
1336                                         count = 0;      /* Initialise count */
1337                                         value = tvb_get_guintvar (tvb, offset, &count);
1338                                         ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1339                                         offset += count;
1340                                 }
1341                                 capabilityStart = offset;
1342                                 count = 0;      /* Initialise count */
1343                                 capabilityLength = tvb_get_guintvar (tvb, offset, &count);
1344                                 offset += count;
1345                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,tvb,capabilityStart,count,capabilityLength);
1346
1347                                 if (pdut != RESUME)
1348                                 {
1349                                         count = 0;      /* Initialise count */
1350                                         headerLength = tvb_get_guintvar (tvb, offset, &count);
1351                                         ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headerLength);
1352                                         offset += count;
1353                                         capabilityStart = offset;
1354                                         headerStart = capabilityStart + capabilityLength;
1355                                 } else {
1356                                                 /* Resume computes the headerlength by remaining bytes */
1357                                         capabilityStart = offset;
1358                                         headerStart = capabilityStart + capabilityLength;
1359                                         headerLength = tvb_reported_length_remaining (tvb, headerStart);
1360                                 }
1361                                 if (capabilityLength > 0)
1362                                 {
1363                                         tmp_tvb = tvb_new_subset (tvb, offset, capabilityLength, capabilityLength);
1364                                         add_capabilities (wsp_tree, tmp_tvb, pdut);
1365                                         offset += capabilityLength;
1366                                 }
1367
1368                                 if (headerLength > 0)
1369                                 {
1370                                         tmp_tvb = tvb_new_subset (tvb, offset, headerLength, headerLength);
1371                                         add_headers (wsp_tree, tmp_tvb);
1372                                 }
1373                         }
1374
1375                         break;
1376
1377                 case REDIRECT:
1378                         dissect_redirect(tvb, offset, pinfo, wsp_tree,
1379                           dissector_handle);
1380                         break;
1381
1382                 case DISCONNECT:
1383                 case SUSPEND:
1384                         if (tree) {
1385                                 count = 0;      /* Initialise count */
1386                                 value = tvb_get_guintvar (tvb, offset, &count);
1387                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1388                         }
1389                         break;
1390
1391                 case GET:
1392                         count = 0;      /* Initialise count */
1393                                 /* Length of URI and size of URILen field */
1394                         value = tvb_get_guintvar (tvb, offset, &count);
1395                         nextOffset = offset + count;
1396                         add_uri (wsp_tree, pinfo, tvb, offset, nextOffset);
1397                         if (tree) {
1398                                 offset += (value+count); /* VERIFY */
1399                                 tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
1400                                 add_headers (wsp_tree, tmp_tvb);
1401                         }
1402                         break;
1403
1404                 case POST:
1405                         uriStart = offset;
1406                         count = 0;      /* Initialise count */
1407                         uriLength = tvb_get_guintvar (tvb, offset, &count);
1408                         headerStart = uriStart+count;
1409                         count = 0;      /* Initialise count */
1410                         headersLength = tvb_get_guintvar (tvb, headerStart, &count);
1411                         offset = headerStart + count;
1412
1413                         add_uri (wsp_tree, pinfo, tvb, uriStart, offset);
1414                         if (tree) {
1415                                 offset += uriLength;
1416
1417                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,headersLength);
1418
1419                                 if (headersLength == 0)
1420                                         break;
1421
1422                                 contentTypeStart = offset;
1423                                 nextOffset = add_content_type (wsp_tree,
1424                                     tvb, offset, &contentType,
1425                                     &contentTypeStr);
1426
1427                                 /* Add headers subtree that will hold the headers fields */
1428                                 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1429                                 headerLength = headersLength-(nextOffset-contentTypeStart);
1430                                 if (headerLength > 0)
1431                                 {
1432                                         tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1433                                         add_headers (wsp_tree, tmp_tvb);
1434                                 }
1435                                 offset = nextOffset+headerLength;
1436                         }
1437                         /* POST data - First check whether a subdissector exists for the content type */
1438                         if (tvb_reported_length_remaining(tvb, headerStart + count + uriLength + headersLength) > 0)
1439                         {
1440                                 tmp_tvb = tvb_new_subset (tvb, headerStart + count + uriLength + headersLength, -1, -1);
1441                                 /* Try finding a dissector for the content first, then fallback */
1442                                 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1443                                         if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree))
1444                                                 if (tree) /* Only display if needed */
1445                                                         add_post_data (wsp_tree, tmp_tvb, contentType, contentTypeStr);
1446                         }
1447                         break;
1448
1449                 case REPLY:
1450                         count = 0;      /* Initialise count */
1451                         headersLength = tvb_get_guintvar (tvb, offset+1, &count);
1452                         headerStart = offset + count + 1;
1453                         if (tree) {
1454                                 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
1455                                 nextOffset = offset + 1 + count;
1456                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset+1,count,headersLength);
1457
1458                                 if (headersLength == 0)
1459                                         break;
1460
1461                                 contentTypeStart = nextOffset;
1462                                 nextOffset = add_content_type (wsp_tree,
1463                                     tvb, nextOffset, &contentType,
1464                                     &contentTypeStr);
1465
1466                                 /* Add headers subtree that will hold the headers fields */
1467                                 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1468                                 headerLength = headersLength-(nextOffset-contentTypeStart);
1469                                 if (headerLength > 0)
1470                                 {
1471                                         tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1472                                         add_headers (wsp_tree, tmp_tvb);
1473                                 }
1474                                 offset += count+headersLength+1;
1475                         }
1476                         /* REPLY data - First check whether a subdissector exists for the content type */
1477                         if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1478                         {
1479                                 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1480                                 /* Try finding a dissector for the content first, then fallback */
1481                                 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1482                                         if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree))
1483                                                 if (tree) /* Only display if needed */
1484                                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_reply_data,
1485                                                                         tmp_tvb, 0, -1, bo_little_endian);
1486                         }
1487                         break;
1488
1489                 case PUSH:
1490                 case CONFIRMEDPUSH:
1491                         count = 0;      /* Initialise count */
1492                         headersLength = tvb_get_guintvar (tvb, offset, &count);
1493                         headerStart = offset + count;
1494
1495                         if (tree) {
1496                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headersLength);
1497
1498                                 if (headersLength == 0)
1499                                         break;
1500
1501                                 offset += count;
1502                                 contentTypeStart = offset;
1503                                 nextOffset = add_content_type (wsp_tree,
1504                                     tvb, offset, &contentType,
1505                                     &contentTypeStr);
1506
1507                                 /* Add headers subtree that will hold the headers fields */
1508                                 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1509                                 headerLength = headersLength-(nextOffset-contentTypeStart);
1510                                 if (headerLength > 0)
1511                                 {
1512                                         tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1513                                         add_headers (wsp_tree, tmp_tvb);
1514                                 }
1515                                 offset += headersLength;
1516                         }
1517                         /* PUSH data - First check whether a subdissector exists for the content type */
1518                         if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1519                         {
1520                                 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1521                                 /* Try finding a dissector for the content first, then fallback */
1522                                 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1523                                         if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree))
1524                                                 if (tree) /* Only display if needed */
1525                                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_push_data,
1526                                                                         tmp_tvb, 0, -1, bo_little_endian);
1527                         }
1528                         break;
1529
1530         }
1531 }
1532
1533 /*
1534  * Called directly from UDP.
1535  * Put "WSP" into the "Protocol" column.
1536  */
1537 static void
1538 dissect_wsp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1539 {
1540         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1541                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSP" );
1542         if (check_col(pinfo->cinfo, COL_INFO))
1543                 col_clear(pinfo->cinfo, COL_INFO);
1544
1545         dissect_wsp_common(tvb, pinfo, tree, wsp_fromudp_handle, TRUE);
1546 }
1547
1548 /*
1549  * Called from a higher-level WAP dissector, in connection-oriented mode.
1550  * Leave the "Protocol" column alone - the dissector calling us should
1551  * have set it.
1552  */
1553 static void
1554 dissect_wsp_fromwap_co(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1555 {
1556         /*
1557          * XXX - what about WTLS->WTP->WSP?
1558          */
1559         dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, FALSE);
1560 }
1561
1562 /*
1563  * Called from a higher-level WAP dissector, in connectionless mode.
1564  * Leave the "Protocol" column alone - the dissector calling us should
1565  * have set it.
1566  */
1567 static void
1568 dissect_wsp_fromwap_cl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1569 {
1570         /*
1571          * XXX - what about WTLS->WSP?
1572          */
1573         if (check_col(pinfo->cinfo, COL_INFO))
1574         {
1575                 col_clear(pinfo->cinfo, COL_INFO);
1576         }
1577         dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, TRUE);
1578 }
1579
1580 static void
1581 add_uri (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint URILenOffset, guint URIOffset)
1582 {
1583         proto_item *ti;
1584
1585         guint count = 0;
1586         guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
1587
1588         if (tree)
1589                 ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,tvb,URILenOffset,count,uriLen);
1590
1591         if (tree)
1592                 ti = proto_tree_add_item (tree, hf_wsp_header_uri,tvb,URIOffset,uriLen,bo_little_endian);
1593         if (check_col(pinfo->cinfo, COL_INFO)) {
1594                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1595                     tvb_format_text (tvb, URIOffset, uriLen));
1596         }
1597 }
1598
1599 static void
1600 add_headers (proto_tree *tree, tvbuff_t *tvb)
1601 {
1602         proto_item *ti;
1603         proto_tree *wsp_headers;
1604         guint offset = 0;
1605         guint headersLen = tvb_reported_length (tvb);
1606         guint headerStart = 0;
1607         guint peek = 0;
1608         guint pageCode = 1;
1609
1610 #ifdef DEBUG
1611         fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, headersLen);
1612 #endif
1613
1614         /* End of buffer */
1615         if (headersLen <= 0)
1616         {
1617                 return;
1618         }
1619
1620 #ifdef DEBUG
1621         fprintf (stderr, "dissect_wsp: Headers to process\n");
1622 #endif
1623
1624         ti = proto_tree_add_item (tree, hf_wsp_headers_section,tvb,offset,headersLen,bo_little_endian);
1625         wsp_headers = proto_item_add_subtree( ti, ett_headers );
1626
1627         /* Parse Headers */
1628
1629         while (offset < headersLen)
1630         {
1631                 /* Loop round each header */
1632                 headerStart = offset;
1633                 peek = tvb_get_guint8 (tvb, headerStart);
1634
1635                 if (peek < 32)          /* Short-cut shift delimiter */
1636                 {
1637                         pageCode = peek;
1638                         proto_tree_add_uint (wsp_headers,
1639                             hf_wsp_header_shift_code, tvb, offset, 1,
1640                             pageCode);
1641                         offset += 1;
1642                         continue;
1643                 }
1644                 else if (peek == 0x7F)  /* Shift delimiter */
1645                 {
1646                         pageCode = tvb_get_guint8(tvb, offset+1);
1647                         proto_tree_add_uint (wsp_headers,
1648                             hf_wsp_header_shift_code, tvb, offset, 2,
1649                             pageCode);
1650                         offset += 2;
1651                         continue;
1652                 }
1653                 else if (peek < 127)
1654                 {
1655 #ifdef DEBUG
1656                         fprintf (stderr, "dissect_wsp: header: application-header start %d (0x%02X)\n", peek, peek);
1657 #endif
1658                         /*
1659                          * Token-text, followed by Application-specific-value.
1660                          */
1661                         offset = add_application_header (wsp_headers, tvb,
1662                             headerStart);
1663                 }
1664                 else if (peek & 0x80)
1665                 {
1666 #ifdef DEBUG
1667                         fprintf (stderr, "dissect_wsp: header: well-known %d (0x%02X)\n", peek, peek);
1668 #endif
1669                         /*
1670                          * Well-known-header; the lower 7 bits of "peek"
1671                          * are the header code.
1672                          */
1673                         switch (pageCode) {
1674                         case 1:
1675                                 offset = add_well_known_header (wsp_headers,
1676                                     tvb, headerStart, peek & 0x7F);
1677                                 break;
1678
1679                         case 2:
1680                         case 16:
1681                                 offset = add_well_known_openwave_header (wsp_headers,
1682                                     tvb, headerStart, peek & 0x7F);
1683                                 break;
1684
1685                         default:
1686                                 offset = add_unknown_header (wsp_headers,
1687                                     tvb, headerStart, peek & 0x7F);
1688                                 break;
1689                         }
1690                 }
1691         }
1692 }
1693
1694 static int
1695 add_well_known_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1696     guint8 headerType)
1697 {
1698         int headerStart;
1699         value_type_t valueType;
1700         int headerLen;
1701         guint valueLen;
1702         int valueStart;
1703         tvbuff_t *header_buff;
1704         tvbuff_t *value_buff;
1705
1706 #ifdef DEBUG
1707         fprintf (stderr, "dissect_wsp: Got header 0x%02x\n", headerType);
1708 #endif
1709         headerStart = offset;
1710
1711         /*
1712          * Skip the Short-Integer header type.
1713          */
1714         offset++;
1715
1716         /*
1717          * Get the value type and length (or, if the type is VALUE_IN_LEN,
1718          * meaning the value is a Short-integer, get the value type
1719          * and the value itself).
1720          */
1721         valueType = get_value_type_len (tvb, offset, &valueLen,
1722             &valueStart, &offset);
1723         headerLen = offset - headerStart;
1724
1725         /*
1726          * Get a tvbuff for the entire header.
1727          * XXX - cut the actual length short so that it doesn't run
1728          * past the actual length of tvb.
1729          */
1730         header_buff = tvb_new_subset (tvb, headerStart, headerLen,
1731             headerLen);
1732
1733         /*
1734          * If the value wasn't in the length, get a tvbuff for the value.
1735          * XXX - can valueLen be 0?
1736          * XXX - cut the actual length short so that it doesn't run
1737          * past the actual length of tvb.
1738          */
1739         if (valueType != VALUE_IN_LEN) {
1740                 value_buff = tvb_new_subset (tvb, valueStart, valueLen,
1741                     valueLen);
1742         } else {
1743                 /*
1744                  * XXX - when the last dissector is tvbuffified,
1745                  * so that NULL is no longer a valid tvb pointer
1746                  * value in "proto_tree_add" calls, just
1747                  * set "value_buff" to NULL.
1748                  *
1749                  * XXX - can we already do that?  I.e., will that
1750                  * cause us always to crash if we mistakenly try
1751                  * to fetch the value of a VALUE_IN_LEN item?
1752                  */
1753                 value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
1754         }
1755
1756         switch (headerType) {
1757
1758         case FN_ACCEPT:                 /* Accept */
1759                 add_accept_header (tree, header_buff, headerLen,
1760                     value_buff, valueType, valueLen);
1761                 break;
1762
1763         case FN_ACCEPT_CHARSET_DEP:     /* Accept-Charset */
1764                 /*
1765                  * XXX - should both encoding versions 1.1 and
1766                  * 1.3 be handled this way?
1767                  */
1768                 add_accept_xxx_header (tree, header_buff, headerLen,
1769                     value_buff, valueType, valueLen,
1770                     hf_wsp_header_accept_charset,
1771                     hf_wsp_header_accept_charset_str,
1772                     vals_character_sets, "Unknown charset (0x%04x)");
1773                 break;
1774
1775         case FN_ACCEPT_LANGUAGE:        /* Accept-Language */
1776                 add_accept_xxx_header (tree, header_buff, headerLen,
1777                     value_buff, valueType, valueLen,
1778                     hf_wsp_header_accept_language,
1779                     hf_wsp_header_accept_language_str,
1780                     vals_languages, "Unknown language (0x%04x)");
1781                 break;
1782
1783         case FN_ACCEPT_RANGES:          /* Accept-Ranges */
1784                 add_accept_ranges_header (tree, header_buff, headerLen,
1785                     value_buff, valueType, valueLen);
1786                 break;
1787
1788         case FN_AGE:                    /* Age */
1789                 add_integer_value_header (tree, header_buff, headerLen,
1790                     value_buff, valueType, valueLen, hf_wsp_header_age,
1791                     headerType);
1792                 break;
1793
1794         case FN_CACHE_CONTROL_DEP:      /* Cache-Control */
1795         case FN_CACHE_CONTROL:
1796         case FN_CACHE_CONTROL14:
1797                 /*
1798                  * XXX - is the only difference in the three different
1799                  * versions (1.1, 1.3, 1.4) really only S_MAXAGE?
1800                  */
1801                 add_cache_control_header (tree, header_buff, headerLen,
1802                     value_buff, valueType, valueLen);
1803                 break;
1804
1805         case FN_CONNECTION:     /* Connection */
1806                 add_connection_header (tree, header_buff, headerLen,
1807                     value_buff, valueType, valueLen);
1808                 break;
1809
1810         case FN_CONTENT_LENGTH:         /* Content-Length */
1811                 add_integer_value_header (tree, header_buff, headerLen,
1812                     value_buff, valueType, valueLen,
1813                     hf_wsp_header_content_length,
1814                     headerType);
1815                 break;
1816
1817         case FN_DATE:                   /* Date */
1818                 add_date_value_header (tree, header_buff, headerLen,
1819                     value_buff, valueType, valueLen,
1820                     hf_wsp_header_date, headerType);
1821                 break;
1822
1823         case FN_ETAG:                   /* Etag */
1824                 add_string_value_header (tree, header_buff, headerLen,
1825                     value_buff, valueType, valueLen,
1826                     hf_wsp_header_etag, headerType);
1827                 break;
1828
1829         case FN_EXPIRES:                /* Expires */
1830                 add_date_value_header (tree, header_buff, headerLen,
1831                     value_buff, valueType, valueLen,
1832                     hf_wsp_header_expires, headerType);
1833                 break;
1834
1835         case FN_IF_MODIFIED_SINCE:      /* If-Modified-Since */
1836                 add_date_value_header (tree, header_buff, headerLen,
1837                     value_buff, valueType, valueLen,
1838                     hf_wsp_header_if_modified_since, headerType);
1839                 break;
1840
1841         case FN_LOCATION:               /* Location */
1842                 add_string_value_header (tree, header_buff, headerLen,
1843                     value_buff, valueType, valueLen,
1844                     hf_wsp_header_location, headerType);
1845                 break;
1846
1847         case FN_LAST_MODIFIED:          /* Last-Modified */
1848                 add_date_value_header (tree, header_buff, headerLen,
1849                     value_buff, valueType, valueLen,
1850                     hf_wsp_header_last_modified, headerType);
1851                 break;
1852
1853         case FN_PRAGMA:                 /* Pragma */
1854                 add_pragma_header (tree, header_buff, headerLen,
1855                     value_buff, valueType, valueLen);
1856                 break;
1857
1858         case FN_SERVER:                 /* Server */
1859                 add_string_value_header (tree, header_buff, headerLen,
1860                     value_buff, valueType, valueLen,
1861                     hf_wsp_header_server, headerType);
1862                 break;
1863
1864         case FN_TRANSFER_ENCODING:      /* Transfer-Encoding */
1865                 add_transfer_encoding_header (tree, header_buff, headerLen,
1866                     value_buff, valueType, valueLen);
1867                 break;
1868
1869         case FN_USER_AGENT:             /* User-Agent */
1870                 add_string_value_header (tree, header_buff, headerLen,
1871                     value_buff, valueType, valueLen,
1872                     hf_wsp_header_user_agent, headerType);
1873                 break;
1874
1875         case FN_VIA:                    /* Via */
1876                 add_string_value_header (tree, header_buff, headerLen,
1877                     value_buff, valueType, valueLen,
1878                     hf_wsp_header_via, headerType);
1879                 break;
1880
1881         case FN_WARNING:                /* Warning */
1882                 add_warning_header (tree, header_buff, headerLen,
1883                     value_buff, valueType, valueLen);
1884                 break;
1885
1886         case FN_ACCEPT_APPLICATION:     /* Accept-Application */
1887                 add_accept_application_header (tree, header_buff, headerLen,
1888                     value_buff, valueType, valueLen);
1889                 break;
1890
1891         case FN_BEARER_INDICATION:      /* Bearer-Indication */
1892                 add_integer_value_header (tree, header_buff, headerLen,
1893                     value_buff, valueType, valueLen,
1894                     hf_wsp_header_bearer_indication, headerType);
1895                 break;
1896
1897         case FN_PROFILE:                /* Profile */
1898                 add_string_value_header (tree, header_buff, headerLen,
1899                     value_buff, valueType, valueLen,
1900                     hf_wsp_header_profile, headerType);
1901                 break;
1902
1903         case FN_X_WAP_APPLICATION_ID:   /* X-Wap-Application-Id */
1904                 add_wap_application_id_header (tree, header_buff, headerLen,
1905                     value_buff, valueType, valueLen);
1906                 break;
1907
1908         case FN_CONTENT_ID:             /* Content-ID   */
1909                 add_quoted_string_value_header (tree, header_buff, headerLen,
1910                     value_buff, valueType, valueLen,
1911                     hf_wsp_header_content_ID, headerType);
1912                 break;
1913         
1914         case FN_AUTHORIZATION: /* Authorization */
1915                 add_credentials_value_header (tree, header_buff, headerLen,
1916                                 value_buff, valueType, valueLen,
1917                                 hf_wsp_header_authorization,
1918                                 hf_wsp_header_authorization_scheme,
1919                                 hf_wsp_header_authorization_user_id,
1920                                 hf_wsp_header_authorization_password);
1921                 break;
1922
1923         case FN_PROXY_AUTHORIZATION: /* Proxy-Authorization */
1924                 add_credentials_value_header (tree, header_buff, headerLen,
1925                                 value_buff, valueType, valueLen,
1926                                 hf_wsp_header_proxy_authorization,
1927                                 hf_wsp_header_proxy_authorization_scheme,
1928                                 hf_wsp_header_proxy_authorization_user_id,
1929                                 hf_wsp_header_proxy_authorization_password);
1930                 break;
1931
1932         case FN_WWW_AUTHENTICATE: /* WWW-Authenticate */
1933         case FN_PROXY_AUTHENTICATE: /* Proxy-Authenticate */
1934
1935
1936         default:
1937                 proto_tree_add_text (tree, header_buff, 0, headerLen,
1938                     "Undecoded Header: %s",
1939                     val_to_str (headerType, vals_field_names, "Unknown (0x%02X)"));
1940                 break;
1941         }
1942         return offset;
1943 }
1944
1945
1946 static int
1947 add_well_known_openwave_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1948     guint8 headerType)
1949 {
1950         int headerStart;
1951         value_type_t valueType;
1952         int headerLen;
1953         guint valueLen;
1954         int valueStart;
1955         tvbuff_t *header_buff;
1956         tvbuff_t *value_buff;
1957
1958 #ifdef DEBUG
1959         fprintf (stderr, "dissect_wsp: Got Openwave header 0x%02x\n", headerType);
1960 #endif
1961         headerStart = offset;
1962
1963         /*
1964          * Skip the Short-Integer header type.
1965          */
1966         offset++;
1967
1968         /*
1969          * Get the value type and length (or, if the type is VALUE_IN_LEN,
1970          * meaning the value is a Short-integer, get the value type
1971          * and the value itself).
1972          */
1973         valueType = get_value_type_len (tvb, offset, &valueLen,
1974             &valueStart, &offset);
1975         headerLen = offset - headerStart;
1976
1977         /*
1978          * Get a tvbuff for the entire header.
1979          * XXX - cut the actual length short so that it doesn't run
1980          * past the actual length of tvb.
1981          */
1982         header_buff = tvb_new_subset (tvb, headerStart, headerLen,
1983             headerLen);
1984
1985         /*
1986          * If the value wasn't in the length, get a tvbuff for the value.
1987          * XXX - can valueLen be 0?
1988          * XXX - cut the actual length short so that it doesn't run
1989          * past the actual length of tvb.
1990          */
1991         if (valueType != VALUE_IN_LEN) {
1992                 value_buff = tvb_new_subset (tvb, valueStart, valueLen,
1993                     valueLen);
1994         } else {
1995                 /*
1996                  * XXX - when the last dissector is tvbuffified,
1997                  * so that NULL is no longer a valid tvb pointer
1998                  * value in "proto_tree_add" calls, just
1999                  * set "value_buff" to NULL.
2000                  *
2001                  * XXX - can we already do that?  I.e., will that
2002                  * cause us always to crash if we mistakenly try
2003                  * to fetch the value of a VALUE_IN_LEN item?
2004                  */
2005                 value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
2006         }
2007
2008         switch (headerType) {
2009
2010 /*      case FN_OPENWAVE_PROXY_PUSH_ADDR:       / x-up-proxy-push-addr */
2011 /*              add_openwave_push_address_header (tree, header_buff, headerLen, */
2012 /*                  value_buff, valueType, valueLen); */
2013 /*              break; */
2014
2015         case FN_OPENWAVE_PROXY_PUSH_ACCEPT:     /* x-up-proxy-push-accept */
2016                 add_accept_header (tree, header_buff, headerLen,
2017                     value_buff, valueType, valueLen);
2018                 break;
2019
2020         case FN_OPENWAVE_PROXY_PUSH_SEQ:        /* x-up-proxy-push-seq */
2021                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2022                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_push_seq,
2023                     headerType);
2024                 break;
2025
2026         case FN_OPENWAVE_PROXY_NOTIFY:          /* x-up-proxy-notify */
2027                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2028                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_notify,
2029                     headerType);
2030                 break;
2031
2032         case FN_OPENWAVE_PROXY_OPERATOR_DOMAIN: /* x-up-proxy-operator-domain */
2033                 add_openwave_string_value_header (tree, header_buff, headerLen,
2034                     value_buff, valueType, valueLen,
2035                     hf_wsp_header_openwave_proxy_operator_domain, headerType);
2036                 break;
2037
2038         case FN_OPENWAVE_PROXY_HOME_PAGE:       /* x-up-proxy-home-page */
2039                 add_openwave_string_value_header (tree, header_buff, headerLen,
2040                     value_buff, valueType, valueLen,
2041                     hf_wsp_header_openwave_proxy_home_page, headerType);
2042                 break;
2043
2044         case FN_OPENWAVE_DEVCAP_HAS_COLOR:      /* x-up-devcap-has-color */
2045                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2046                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_has_color,
2047                     headerType);
2048                 break;
2049
2050         case FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS:   /* x-up-devcap-num-softkeys */
2051                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2052                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_num_softkeys,
2053                     headerType);
2054                 break;
2055
2056         case FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE:   /* x-up-devcap-softkey-size */
2057                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2058                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_softkey_size,
2059                     headerType);
2060                 break;
2061
2062 /*      case FN_OPENWAVE_DEVCAP_SCREEN_CHARS:   / x-up-devcap-screen-chars */
2063 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2064 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_chars, */
2065 /*                  headerType); */
2066 /*              break; */
2067
2068 /*      case FN_OPENWAVE_DEVCAP_SCREEN_PIXELS:  / x-up-devcap-screen-pixels */
2069 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2070 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_pixels, */
2071 /*                  headerType); */
2072 /*              break; */
2073
2074 /*      case FN_OPENWAVE_DEVCAP_EM_SIZE:        / x-up-devcap-em-size */
2075 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2076 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_em_size, */
2077 /*                  headerType); */
2078 /*              break; */
2079
2080         case FN_OPENWAVE_DEVCAP_SCREEN_DEPTH:   /* x-up-devcap-screen-depth */
2081                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2082                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_depth,
2083                     headerType);
2084                 break;
2085
2086         case FN_OPENWAVE_DEVCAP_IMMED_ALERT:    /* x-up-devcap-immed-alert */
2087                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2088                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_immed_alert,
2089                     headerType);
2090                 break;
2091
2092         case FN_OPENWAVE_PROXY_NET_ASK:         /* x-up-proxy-net-ask */
2093                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2094                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_net_ask,
2095                     headerType);
2096                 break;
2097
2098         case FN_OPENWAVE_PROXY_UPLINK_VERSION:          /* x-up-proxy-uplink-version */
2099                 add_openwave_string_value_header (tree, header_buff, headerLen,
2100                     value_buff, valueType, valueLen,
2101                     hf_wsp_header_openwave_proxy_uplink_version, headerType);
2102                 break;
2103
2104         case FN_OPENWAVE_PROXY_TOD:             /* x-up-proxy-tod */
2105                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2106                     value_buff, valueType, valueLen,
2107                     hf_wsp_header_openwave_proxy_tod, headerType);
2108                 break;
2109
2110         case FN_OPENWAVE_PROXY_BA_ENABLE:               /* x-up-proxy-ba-enable */
2111                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2112                     value_buff, valueType, valueLen,
2113                     hf_wsp_header_openwave_proxy_ba_enable, headerType);
2114                 break;
2115
2116         case FN_OPENWAVE_PROXY_BA_REALM:                /* x-up-proxy-ba-realm */
2117                 add_openwave_string_value_header (tree, header_buff, headerLen,
2118                     value_buff, valueType, valueLen,
2119                     hf_wsp_header_openwave_proxy_ba_realm, headerType);
2120                 break;
2121
2122         case FN_OPENWAVE_PROXY_REDIRECT_ENABLE:         /* x-up-proxy-redirect-enable */
2123                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2124                     value_buff, valueType, valueLen,
2125                     hf_wsp_header_openwave_proxy_redirect_enable, headerType);
2126                 break;
2127
2128         case FN_OPENWAVE_PROXY_REQUEST_URI:             /* x-up-proxy-request-uri */
2129                 add_openwave_string_value_header (tree, header_buff, headerLen,
2130                     value_buff, valueType, valueLen,
2131                     hf_wsp_header_openwave_proxy_request_uri, headerType);
2132                 break;
2133
2134 /*      case FN_OPENWAVE_PROXY_REDIRECT_STATUS:         / x-up-proxy-redirect-status */
2135 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2136 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_redirect_status, */
2137 /*                  headerType); */
2138 /*              break; */
2139
2140         case FN_OPENWAVE_PROXY_TRANS_CHARSET:           /* x-up-proxy-trans-charset */
2141                 add_accept_xxx_header (tree, header_buff, headerLen,
2142                     value_buff, valueType, valueLen,
2143                     hf_wsp_header_openwave_proxy_trans_charset,
2144                     hf_wsp_header_openwave_proxy_trans_charset_str,
2145                     vals_character_sets, "Unknown charset (%u)");
2146                 break;
2147
2148         case FN_OPENWAVE_PROXY_LINGER:                  /* x-up-proxy-linger */
2149                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2150                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_linger,
2151                     headerType);
2152                 break;
2153
2154 /*      case FN_OPENWAVE_PROXY_CLIENT_ID:               / x-up-proxy-client-id */
2155 /*              add_openwave_string_value_header (tree, header_buff, headerLen, */
2156 /*                  value_buff, valueType, valueLen, */
2157 /*                  hf_wsp_header_openwave_proxy_client_id, headerType); */
2158 /*              break; */
2159
2160         case FN_OPENWAVE_PROXY_ENABLE_TRUST:            /* x-up-proxy-enable-trust */
2161                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2162                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_enable_trust,
2163                     headerType);
2164                 break;
2165
2166         case FN_OPENWAVE_PROXY_TRUST_OLD:               /* x-up-proxy-trust old value */
2167                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2168                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_trust_old,
2169                     headerType);
2170                 break;
2171
2172         case FN_OPENWAVE_PROXY_TRUST:                   /* x-up-proxy-trust */
2173                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2174                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_trust,
2175                     headerType);
2176                 break;
2177
2178         case FN_OPENWAVE_PROXY_BOOKMARK:                /* x-up-proxy-bookmark */
2179                 add_openwave_string_value_header (tree, header_buff, headerLen,
2180                     value_buff, valueType, valueLen,
2181                     hf_wsp_header_openwave_proxy_bookmark, headerType);
2182                 break;
2183
2184         case FN_OPENWAVE_DEVCAP_GUI:                    /* x-up-devcap-gui */
2185                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2186                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_gui,
2187                     headerType);
2188                 break;
2189
2190         default:
2191                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2192                     "Undecoded Openwave Header: %s",
2193                     val_to_str (headerType, vals_openwave_field_names, "Unknown (0x%02X)"));
2194                 break;
2195         }
2196         return offset;
2197 }
2198
2199 /* *********
2200 static void
2201 add_openwave_push_address_header (proto_tree *tree, tvbuff_t *header_buff,
2202     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2203     int valueLen)
2204 {
2205
2206         ???
2207
2208 }
2209 ********* */
2210
2211 static int
2212 add_unknown_header (proto_tree *tree, tvbuff_t *tvb, int offset,
2213     guint8 headerType)
2214 {
2215         int headerStart;
2216         int valueStart;
2217         value_type_t valueType;
2218         int headerLen;
2219         guint valueLen;
2220         int valueOffset;
2221
2222         headerStart = offset;
2223
2224         /*
2225          * Skip the Short-Integer header type.
2226          */
2227         offset++;
2228
2229         valueStart = offset;
2230
2231         /*
2232          * Get the value type and length (or, if the type is VALUE_IN_LEN,
2233          * meaning the value is a Short-integer, get the value type
2234          * and the value itself).
2235          */
2236         valueType = get_value_type_len (tvb, valueStart, &valueLen,
2237             &valueOffset, &offset);
2238         headerLen = offset - headerStart;
2239
2240         proto_tree_add_text (tree, tvb, headerStart, headerLen,
2241                        "Undecoded Header (0x%02X)", headerType);
2242         return offset;
2243 }
2244
2245 static int
2246 add_application_header (proto_tree *tree, tvbuff_t *tvb, int offset)
2247 {
2248         int startOffset;
2249         guint tokenSize;
2250         const guint8 *token;
2251         value_type_t valueType;
2252         int subvalueLen;
2253         int subvalueOffset;
2254         guint secs;
2255         nstime_t timeValue;
2256         int asvOffset;
2257         guint stringSize;
2258
2259         startOffset = offset;
2260         tokenSize = tvb_strsize (tvb, startOffset);
2261         token = tvb_get_ptr (tvb, startOffset, tokenSize);
2262         offset += tokenSize;
2263
2264         /*
2265          * Special case header "X-WAP.TOD" that is sometimes followed
2266          * by a 4-byte date value.
2267          *
2268          * XXX - according to the 4-May-2000 WSP spec, X-Wap-Tod is
2269          * encoded as a well known header, with a code of 0x3F.
2270          */
2271         if (tokenSize == 10 && strncasecmp ("x-wap.tod", token, 9) == 0)
2272         {
2273                 valueType = get_value_type_len (tvb, offset,
2274                     &subvalueLen, &subvalueOffset, &offset);
2275                 if (get_integer (tvb, subvalueOffset, subvalueLen,
2276                     valueType, &secs) == 0)
2277                 {
2278                         /*
2279                          * Fill in the "struct timeval", and add it to the
2280                          * protocol tree.
2281                          * Note: this will succeed even if it's a Short-integer.
2282                          * A Short-integer would work, but, as the time values
2283                          * are UNIX seconds-since-the-Epoch value, and as
2284                          * there weren't WAP phones or Web servers back in
2285                          * late 1969/early 1970, they're unlikely to be used.
2286                          */
2287                         timeValue.secs = secs;
2288                         timeValue.nsecs = 0;
2289                         proto_tree_add_time (tree, hf_wsp_header_x_wap_tod,
2290                             tvb, startOffset, offset - startOffset, &timeValue);
2291                 }
2292                 else
2293                 {
2294                         proto_tree_add_text (tree, tvb, startOffset,
2295                             offset - startOffset,
2296                             "%s: invalid date value", token);
2297                 }
2298         }
2299         else
2300         {
2301                 asvOffset = offset;
2302                 stringSize = tvb_strsize (tvb, asvOffset);
2303                 offset += stringSize;
2304                 proto_tree_add_text (tree, tvb, startOffset,
2305                     offset - startOffset,
2306                     "%s: %s", token,
2307                     tvb_get_ptr (tvb, asvOffset, stringSize));
2308         }
2309         return offset;
2310 }
2311
2312 static void
2313 add_accept_header (proto_tree *tree, tvbuff_t *header_buff,
2314     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2315     int valueLen)
2316 {
2317         guint contentType;
2318         const char *contentTypeStr;
2319
2320         add_content_type_value (tree, header_buff, 0, headerLen, value_buff,
2321             valueType, valueLen, hf_wsp_header_accept,
2322             hf_wsp_header_accept_str, &contentType, &contentTypeStr);
2323 }
2324
2325 static void
2326 add_accept_xxx_header (proto_tree *tree, tvbuff_t *header_buff,
2327     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2328     int valueLen, int hf_numeric, int hf_string,
2329     const value_string *vals, const char *unknown_tag)
2330 {
2331         int offset = 0;
2332         int subvalueLen;
2333         int subvalueOffset;
2334         guint value = 0;
2335         char valString[VAL_STRING_SIZE];
2336         const char *valMatch;
2337         guint peek;
2338         double q_value = 1.0;
2339
2340         if (valueType == VALUE_IN_LEN)
2341         {
2342                 /*
2343                  * Constrained-{charset,language} (Short-Integer).
2344                  */
2345                 proto_tree_add_uint (tree, hf_numeric,
2346                     header_buff, 0, headerLen,
2347                     valueLen);  /* valueLen is the value */
2348                 return;
2349         }
2350         if (valueType == VALUE_IS_TEXT_STRING)
2351         {
2352                 /*
2353                  * Constrained-{charset,language} (text, i.e.
2354                  * Extension-Media).
2355                  */
2356                 proto_tree_add_string (tree, hf_string,
2357                     header_buff, 0, headerLen,
2358                     tvb_get_ptr (value_buff, 0, valueLen));
2359                 return;
2360         }
2361
2362         /*
2363          * First byte had the 8th bit set.
2364          */
2365         if (valueLen == 0) {
2366                 /*
2367                  * Any-{charset,language}.
2368                  */
2369                 proto_tree_add_string (tree, hf_string,
2370                         header_buff, 0, headerLen,
2371                         "*");
2372                 return;
2373         }
2374
2375         /*
2376          * Accept-{charset,language}-general-form; Value-length, followed
2377          * by Well-known-{charset,language} or {Token-text,Text-string},
2378          * possibly followed by a Q-value.
2379          *
2380          * Get Value-length.
2381          */
2382         valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2383             &subvalueOffset, &offset);
2384         if (valueType == VALUE_IS_TEXT_STRING)
2385         {
2386                 /*
2387                  * {Token-text,Text-string}.
2388                  */
2389                 valMatch =
2390                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
2391                 proto_tree_add_string (tree, hf_string,
2392                         value_buff, 0, valueLen, valMatch);
2393         } else {
2394                 /*
2395                  * Well-known-{charset,langugage}; starts with an
2396                  * Integer-value.
2397                  */
2398                 if (get_integer (value_buff, subvalueOffset, subvalueLen,
2399                     valueType, &value) < 0)
2400                 {
2401                         valMatch = "Invalid integer";
2402                 }
2403                 else
2404                 {
2405                         valMatch = val_to_str(value, vals, unknown_tag);
2406                 }
2407         }
2408
2409         /* Any remaining data relates to Q-value */
2410         if (offset < valueLen)
2411         {
2412                 peek = tvb_get_guintvar (value_buff, offset, NULL);
2413                 if (peek <= 100) {
2414                         peek = (peek - 1) * 10;
2415                 }
2416                 else {
2417                         peek -= 100;
2418                 }
2419                 q_value = peek/1000.0;
2420         }
2421
2422         /* Build string including Q-value if present */
2423         if (q_value == 1.0)                     /* Default */
2424         {
2425                 snprintf (valString, VAL_STRING_SIZE, "%s", valMatch);
2426         }
2427         else
2428         {
2429                 snprintf (valString, VAL_STRING_SIZE, "%s; Q=%5.3f", valMatch, q_value);
2430         }
2431         /* Add string to tree */
2432         
2433         proto_tree_add_string (tree, hf_string,
2434             header_buff, 0, headerLen, valString);
2435 }
2436
2437 static void
2438 add_accept_ranges_header (proto_tree *tree, tvbuff_t *header_buff,
2439     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2440     int valueLen)
2441 {
2442         if (valueType == VALUE_IN_LEN)
2443         {
2444                 /*
2445                  * Must be 0 (None) or 1 (Bytes) (the 8th bit was stripped
2446                  * off).
2447                  */
2448                 proto_tree_add_uint (tree, hf_wsp_header_accept_ranges,
2449                     header_buff, 0, headerLen,
2450                     valueLen);  /* valueLen is the value */
2451                 return;
2452         }
2453         if (valueType == VALUE_IS_TEXT_STRING)
2454         {
2455                 /*
2456                  * Token-text.
2457                  */
2458                 proto_tree_add_string (tree, hf_wsp_header_accept_ranges_str,
2459                     header_buff, 0, headerLen,
2460                     tvb_get_ptr (value_buff, 0, valueLen));
2461                 return;
2462         }
2463
2464         /*
2465          * Not valid.
2466          */
2467         fprintf(stderr, "dissect_wsp: Accept-Ranges is neither None, Bytes, nor Token-text\n");
2468         return;
2469 }
2470
2471 static void
2472 add_cache_control_header (proto_tree *tree, tvbuff_t *header_buff,
2473     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2474     int valueLen)
2475 {
2476         int offset = 0;
2477         int subvalueLen;
2478         int subvalueOffset;
2479         guint value;
2480         proto_item *ti;
2481         proto_tree *parameter_tree;
2482         proto_tree *field_names_tree;
2483         guint delta_secs;
2484
2485         if (valueType == VALUE_IN_LEN)
2486         {
2487                 /*
2488                  * No-cache, No-store, Max-age, Max-stale, Min-fresh,
2489                  * Only-if-cached, Public, Private, No-transform,
2490                  * Must-revalidate, Proxy-revalidate, or S-maxage.
2491                  */
2492                 proto_tree_add_uint (tree, hf_wsp_header_cache_control,
2493                     header_buff, 0, headerLen,
2494                     valueLen);  /* valueLen is the value */
2495                 return;
2496         }
2497         if (valueType == VALUE_IS_TEXT_STRING)
2498         {
2499                 /*
2500                  * Cache-extension.
2501                  */
2502                 proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
2503                     header_buff, 0, headerLen,
2504                     tvb_get_ptr (value_buff, 0, valueLen));
2505                 return;
2506         }
2507
2508         /*
2509          * Value-length Cache-directive.
2510          * Get first field of Cache-directive.
2511          */
2512         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2513             &subvalueOffset, &offset);
2514         if (valueType == VALUE_IS_TEXT_STRING)
2515         {
2516                 /*
2517                  * Cache-extension Parameter.
2518                  */
2519                 ti = proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
2520                     header_buff, 0, headerLen,
2521                     tvb_get_ptr (value_buff, 0, valueLen));
2522                 parameter_tree = proto_item_add_subtree (ti,
2523                     ett_header_cache_control_parameters);
2524
2525                 /*
2526                  * Process the rest of the value as parameters.
2527                  */
2528                 while (tvb_reported_length_remaining (value_buff, offset) > 0) {
2529                         offset = add_parameter (parameter_tree, value_buff,
2530                             offset);
2531                 }
2532                 return;
2533         }
2534         if (get_integer (value_buff, subvalueOffset, subvalueLen, valueType,
2535             &value) < 0)
2536         {
2537                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2538                     "Invalid Cache-Control Cache-directive value");
2539         }
2540         else
2541         {
2542                 switch (value) {
2543
2544                 case NO_CACHE:
2545                 case PRIVATE:
2546                         /*
2547                          * Loop, processing Field-names.
2548                          */
2549                         ti = proto_tree_add_uint (tree,
2550                             hf_wsp_header_cache_control,
2551                             header_buff, 0, headerLen,
2552                             value);
2553                         field_names_tree = proto_item_add_subtree (ti,
2554                             ett_header_cache_control_field_names);
2555                         while (tvb_reported_length_remaining (value_buff, offset)
2556                             > 0) {
2557                                 offset = add_cache_control_field_name (tree,
2558                                     value_buff, offset, value);
2559                         }
2560                         break;
2561
2562                 case MAX_AGE:
2563                 case MAX_STALE:
2564                 case MIN_FRESH:
2565                 case S_MAXAGE:
2566                         /*
2567                          * Get Delta-second-value.
2568                          */
2569                         valueType = get_value_type_len (value_buff, offset,
2570                             &subvalueLen, &subvalueOffset, &offset);
2571                         if (get_integer (value_buff, subvalueOffset,
2572                             subvalueLen, valueType, &delta_secs) < 0)
2573                         {
2574                                 proto_tree_add_text (tree,
2575                                     header_buff, 0, headerLen,
2576                                     "Invalid Cache-Control %s Delta-second-value",
2577                                     match_strval (value, vals_cache_control));
2578                         }
2579                         else
2580                         {
2581                                 proto_tree_add_uint_format (tree,
2582                                     hf_wsp_header_cache_control,
2583                                     header_buff, 0, headerLen,
2584                                     value,
2585                                     "Cache-Control: %s %u secs",
2586                                     match_strval (value, vals_cache_control),
2587                                     delta_secs);
2588                         }
2589                         break;
2590
2591                 default:
2592                         /*
2593                          * This should not happen, but handle it anyway.
2594                          */
2595                         proto_tree_add_uint (tree,
2596                             hf_wsp_header_cache_control,
2597                             header_buff, 0, headerLen,
2598                             value);
2599                         break;
2600                 }
2601         }
2602 }
2603
2604 static int
2605 add_cache_control_field_name (proto_tree *tree, tvbuff_t *value_buff,
2606     int offset, guint cache_control_value)
2607 {
2608         value_type_t valueType;
2609         int startOffset;
2610         int subvalueLen;
2611         int subvalueOffset;
2612
2613         startOffset = offset;
2614         valueType = get_value_type_len (value_buff, offset,
2615             &subvalueLen, &subvalueOffset, &offset);
2616         if (valueType == VALUE_IS_TEXT_STRING)
2617         {
2618                 /*
2619                  * Token-text.
2620                  */
2621                 proto_tree_add_item (tree,
2622                     hf_wsp_header_cache_control_field_name_str,
2623                     value_buff, startOffset, offset - startOffset,
2624                     bo_little_endian);
2625         }
2626         else if (valueType == VALUE_IN_LEN)
2627         {
2628                 /*
2629                  * Short-integer Field-name.
2630                  */
2631                 proto_tree_add_uint (tree,
2632                     hf_wsp_header_cache_control_field_name,
2633                     value_buff, startOffset, offset - startOffset,
2634                     subvalueLen);
2635         }
2636         else
2637         {
2638                 /*
2639                  * Long-integer - illegal.
2640                  */
2641                 proto_tree_add_text (tree,
2642                     value_buff, startOffset, offset - startOffset,
2643                     "Invalid Cache-Control %s Field-name",
2644                     match_strval (cache_control_value, vals_cache_control));
2645         }
2646         return offset;
2647 }
2648
2649 static void
2650 add_connection_header (proto_tree *tree, tvbuff_t *header_buff,
2651     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2652     int valueLen)
2653 {
2654         int offset = 0;
2655
2656         if (valueType == VALUE_LEN_SUPPLIED)
2657         {
2658                 /*
2659                  * Invalid.
2660                  */
2661                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2662                     "Invalid Connection value");
2663                 return;
2664         }
2665         if (valueType == VALUE_IS_TEXT_STRING)
2666         {
2667                 /*
2668                  * Token-text.
2669                  */
2670                 proto_tree_add_string (tree,
2671                     hf_wsp_header_connection_str,
2672                     header_buff, 0, headerLen,
2673                     tvb_get_ptr (value_buff, 0, valueLen));
2674                 return;
2675         }
2676
2677         /*
2678          * First byte had the 8th bit set.
2679          */
2680         if (valueLen == 0) {
2681                 /*
2682                  * Close.
2683                  */
2684                 proto_tree_add_uint (tree, hf_wsp_header_connection,
2685                     header_buff, offset, headerLen, valueLen);
2686                 return;
2687         }
2688
2689         /*
2690          * Invalid.
2691          */
2692         proto_tree_add_text (tree, header_buff, 0, headerLen,
2693             "Invalid Connection value");
2694 }
2695
2696 static void
2697 add_pragma_header (proto_tree *tree, tvbuff_t *header_buff,
2698     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2699     int valueLen)
2700 {
2701         int offset = 0;
2702         int subvalueLen;
2703         int subvalueOffset;
2704
2705         if (valueType == VALUE_IN_LEN)
2706         {
2707                 /*
2708                  * Invalid.
2709                  */
2710                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2711                     "Invalid Pragma");
2712                 return;
2713         }
2714         if (valueType == VALUE_IS_TEXT_STRING)
2715         {
2716                 /*
2717                  * Invalid?
2718                  */
2719                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2720                     "Invalid Pragma");
2721                 return;
2722         }
2723
2724         /*
2725          * First byte had the 8th bit set.
2726          */
2727         if (valueLen == 0) {
2728                 /*
2729                  * No-cache.
2730                  */
2731                 proto_tree_add_string (tree, hf_wsp_header_pragma,
2732                     header_buff, 0, headerLen, "No-cache");
2733                 return;
2734         }
2735
2736         /*
2737          * Value-length, followed by Parameter.
2738          *
2739          * Get Value-length.
2740          */
2741         valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2742             &subvalueOffset, &offset);
2743         if (valueType == VALUE_IS_TEXT_STRING)
2744         {
2745                 /*
2746                  * Parameter - a text string.
2747                  */
2748                 proto_tree_add_string (tree, hf_wsp_header_pragma,
2749                     header_buff, 0, headerLen,
2750                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
2751         } else {
2752                 /*
2753                  * Parameter - numeric; illegal?
2754                  */
2755                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2756                     "Invalid Pragma");
2757         }
2758 }
2759
2760 static void
2761 add_transfer_encoding_header (proto_tree *tree, tvbuff_t *header_buff,
2762     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2763     int valueLen)
2764 {
2765         int offset = 0;
2766
2767         if (valueType == VALUE_LEN_SUPPLIED)
2768         {
2769                 /*
2770                  * Invalid.
2771                  */
2772                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2773                     "Invalid Transfer-Encoding value");
2774                 return;
2775         }
2776         if (valueType == VALUE_IS_TEXT_STRING)
2777         {
2778                 /*
2779                  * Token-text.
2780                  */
2781                 proto_tree_add_string (tree,
2782                     hf_wsp_header_transfer_encoding_str,
2783                     header_buff, 0, headerLen,
2784                     tvb_get_ptr (value_buff, 0, valueLen));
2785                 return;
2786         }
2787
2788         /*
2789          * First byte had the 8th bit set.
2790          */
2791         if (valueLen == 0) {
2792                 /*
2793                  * Chunked.
2794                  */
2795                 proto_tree_add_uint (tree, hf_wsp_header_transfer_encoding,
2796                     header_buff, offset, headerLen, valueLen);
2797                 return;
2798         }
2799
2800         /*
2801          * Invalid.
2802          */
2803         proto_tree_add_text (tree, header_buff, 0, headerLen,
2804             "Invalid Transfer Encoding value");
2805 }
2806
2807 static void
2808 add_warning_header (proto_tree *tree, tvbuff_t *header_buff,
2809     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2810     int valueLen)
2811 {
2812         int offset = 0;
2813         proto_item *ti;
2814         proto_tree *warning_tree;
2815         int subvalueLen;
2816         int subvalueOffset;
2817         guint8 code;
2818
2819         /*
2820          * Put the items under a header.
2821          * XXX - make the text of the item summarize the elements.
2822          */
2823         ti = proto_tree_add_item (tree, hf_wsp_header_warning,
2824             header_buff, 0, headerLen, bo_little_endian);
2825         warning_tree = proto_item_add_subtree(ti, ett_header_warning);
2826
2827         if (valueType == VALUE_IN_LEN)
2828         {
2829                 /*
2830                  * Warn-code (Short-integer).
2831                  */
2832                 proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2833                     header_buff, 0, headerLen,
2834                     valueLen);  /* valueLen is the value */
2835                 proto_item_append_text (ti, ": %s", match_strval(valueLen, vals_wsp_warning_code));
2836                 return;
2837         }
2838         if (valueType == VALUE_IS_TEXT_STRING)
2839         {
2840                 /*
2841                  * Invalid.
2842                  */
2843                 proto_tree_add_text (warning_tree, header_buff, 0, headerLen,
2844                     "Invalid Warning (all text)");
2845                 return;
2846         }
2847
2848         /*
2849          * Warning-value; Warn-code, followed by Warn-agent, followed by
2850          * Warn-text.
2851          */
2852         /*
2853          * Get Short-integer Warn-code.
2854          */
2855         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2856             &subvalueOffset, &offset);
2857         if (valueType != VALUE_IN_LEN)
2858         {
2859                 /*
2860                  * Not a Short-integer.
2861                  */
2862                 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2863                     subvalueLen, "Invalid Warn-code (not a Short-integer)");
2864                 return;
2865         }
2866         code = subvalueLen;
2867         proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2868             value_buff, subvalueOffset, 1,
2869             subvalueLen);       /* subvalueLen is the value */
2870
2871         /*
2872          * Warn-agent; must be text.
2873          */
2874         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2875             &subvalueOffset, &offset);
2876         if (valueType != VALUE_IS_TEXT_STRING)
2877         {
2878                 /*
2879                  * Not text.
2880                  */
2881                 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2882                     subvalueLen, "Invalid Warn-agent (not a text string)");
2883                 return;
2884         }
2885         proto_tree_add_item (warning_tree,
2886                 hf_wsp_header_warning_agent,
2887                 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2888
2889         /*
2890          * Warn-text; must be text.
2891          */
2892         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2893             &subvalueOffset, &offset);
2894         if (valueType != VALUE_IS_TEXT_STRING)
2895         {
2896                 /*
2897                  * Not text.
2898                  */
2899                 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2900                     subvalueLen, "Invalid Warn-text (not a text string)");
2901                 return;
2902         }
2903         proto_tree_add_item (warning_tree,
2904                 hf_wsp_header_warning_text,
2905                 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2906         /* Now create the summary warning header */
2907         proto_item_append_text (ti, ": %s %s",
2908                         val_to_str (code, vals_wsp_warning_code_short, "%u"),
2909                         tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
2910 }
2911
2912 static void
2913 add_accept_application_header (proto_tree *tree, tvbuff_t *header_buff,
2914     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2915     int valueLen)
2916 {
2917         guint value;
2918
2919         if (valueType == VALUE_IN_LEN)
2920         {
2921                 /*
2922                  * Application-id-value; numeric, so it's App-assigned-code.
2923                  */
2924                 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2925                     header_buff, 0, headerLen,
2926                     valueLen);  /* valueLen is the value */
2927                 return;
2928         }
2929         if (valueType == VALUE_IS_TEXT_STRING)
2930         {
2931                 /*
2932                  * Uri-value.
2933                  */
2934                 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2935                     header_buff, 0, headerLen,
2936                     tvb_get_ptr (value_buff, 0, valueLen));
2937                 return;
2938         }
2939
2940         /*
2941          * First byte had the 8th bit set.
2942          */
2943         if (valueLen == 0) {
2944                 /*
2945                  * Any-application.
2946                  */
2947                 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2948                         header_buff, 0, headerLen,
2949                         "*");
2950                 return;
2951         }
2952
2953         /*
2954          * Integer-value, hence App-assigned-code.
2955          */
2956         if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
2957         {
2958                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2959                         "Invalid Accept-Application App-assigned-code");
2960         }
2961         else
2962         {
2963                 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2964                     header_buff, 0, headerLen, value);
2965         }
2966 }
2967
2968 static void
2969 add_wap_application_id_header (proto_tree *tree, tvbuff_t *header_buff,
2970     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2971     int valueLen)
2972 {
2973         if (valueType == VALUE_IN_LEN)
2974         {
2975                 /*
2976                  * Must application-id (the 8th bit was stripped off).
2977                  */
2978                 proto_tree_add_uint (tree, hf_wsp_header_wap_application_id,
2979                     header_buff, 0, headerLen,
2980                     valueLen);  /* valueLen is the value */
2981                 return;
2982         }
2983         if (valueType == VALUE_IS_TEXT_STRING)
2984         {
2985                 /*
2986                  * Token-text.
2987                  */
2988                 proto_tree_add_string (tree, hf_wsp_header_wap_application_id_str,
2989                     header_buff, 0, headerLen,
2990                     tvb_get_ptr (value_buff, 0, valueLen));
2991                 return;
2992         }
2993
2994         /*
2995          * Not valid.
2996          */
2997         fprintf(stderr, "dissect_wsp: Suprising format of X-Wap-Application-Id\n");
2998         return;
2999 }
3000
3001 static void
3002 add_credentials_value_header (proto_tree *tree, tvbuff_t *header_buff,
3003                 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3004                 int valueLen _U_ ,
3005                 int hf_main, int hf_scheme,
3006                 int hf_basic_user_id, int hf_basic_password)
3007 {
3008         char *s;
3009         guint32 i, sLen;
3010         proto_item *ti;
3011         proto_tree *basic_tree;
3012
3013         ti = proto_tree_add_item (tree, hf_main, header_buff, 0, headerLen,
3014                         bo_little_endian);
3015         if (valueType == VALUE_LEN_SUPPLIED)
3016         {
3017                 if (tvb_get_guint8 (value_buff, 0) == 0x80)
3018                 { /* Basic */
3019                         basic_tree = proto_item_add_subtree(ti, ett_header_credentials);
3020                         proto_tree_add_string (basic_tree, hf_scheme,
3021                                         value_buff, 0, 1, "Basic" );
3022                         proto_item_append_text (ti, ": Basic");
3023                         /* Now process the Basic Cookie consisting of User-Id and Password */
3024                         i = 1;
3025                         while (tvb_get_guint8(value_buff, i))
3026                                 i++; /* Count length of 1st string */
3027                         /* We reached End of String at offset = i.
3028                          * Get the user id including trailing '\0' (end - start + 1) */
3029                         s = (char *) tvb_get_ptr(value_buff, 1, i - 1 + 1);
3030                         proto_tree_add_string (basic_tree, hf_basic_user_id,
3031                                         value_buff, 1, i - 1 + 1, s );
3032                         proto_item_append_text (ti, "; user-id='%s'", s);
3033                         sLen = ++i; /* Move to 1st byte of password string */
3034
3035                         while (tvb_get_guint8(value_buff, i))
3036                                 i++; /* Count length of 2nd string */
3037                         /* We reached End of String at offset = i.
3038                          * Get the password including trailing '\0' (end - start + 1) */
3039                         s = (char *) tvb_get_ptr(value_buff, sLen, i - sLen + 1);
3040                         proto_tree_add_string (basic_tree, hf_basic_password,
3041                                         value_buff, sLen, i - sLen + 1, s );
3042                         proto_item_append_text (ti, "; password='%s'", s);
3043                 }
3044                 else
3045                 { /* TODO: Authentication-scheme *Auth-param */
3046                         proto_item_append_text (ti, ": (General format not yet decoded)");
3047                 }
3048         }
3049         else
3050         {
3051                 proto_item_append_text (ti, ": (Invalid header value format)");
3052         }
3053         return;
3054 }
3055
3056 static void
3057 add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type)
3058 {
3059         proto_item *ti;
3060         proto_tree *wsp_capabilities;
3061         guint offset = 0;
3062         guint offsetStr = 0;
3063         guint capabilitiesLen = tvb_reported_length (tvb);
3064         guint capabilitiesStart = 0;
3065         guint peek = 0;
3066         guint length = 0;
3067         guint value = 0;
3068         guint i;
3069         int ret;
3070         char valString[VAL_STRING_SIZE];
3071
3072 #ifdef DEBUG
3073         fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, capabilitiesLen);
3074 #endif
3075
3076         /* End of buffer */
3077         if (capabilitiesLen <= 0)
3078         {
3079                 fprintf (stderr, "dissect_wsp: Capabilities = 0\n");
3080                 return;
3081         }
3082
3083 #ifdef DEBUG
3084         fprintf (stderr, "dissect_wsp: capabilities to process\n");
3085 #endif
3086
3087         ti = proto_tree_add_item (tree, hf_wsp_capabilities_section,tvb,offset,capabilitiesLen,bo_little_endian);
3088         wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
3089
3090         /* Parse Headers */
3091
3092         while (offset < capabilitiesLen)
3093         {
3094                 /* Loop round each header */
3095                 capabilitiesStart = offset;
3096                 length = tvb_get_guint8 (tvb, capabilitiesStart);
3097
3098                 if (length >= 127)              /* length */
3099                 {
3100 #ifdef DEBUG
3101                         fprintf (stderr, "dissect_wsp: capabilities length invalid %d\n",length);
3102 #endif
3103                         offset+=length;
3104                         continue;
3105                 }
3106                 offset++;
3107                 peek = tvb_get_guint8 (tvb, offset);
3108                 offset++;
3109                 switch (peek & 0x7f)
3110                 {
3111                         case 0x00 : /* Client-SDU-Size */
3112                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
3113                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_client_SDU, tvb, capabilitiesStart, length+1, value);
3114                                 break;
3115                         case 0x01 : /* Server-SDU-Size */
3116                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
3117                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_server_SDU, tvb, capabilitiesStart, length+1, value);
3118                                 break;
3119                         case 0x02 : /* Protocol Options */
3120                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
3121                                 i = 0;
3122                                 valString[0]=0;
3123                                 if (value & 0x80)
3124                                 {
3125                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Confirmed push facility) ");
3126                                         if (ret == -1 || ret >= VAL_STRING_SIZE-i) {
3127                                                 /*
3128                                                  * We've been truncated
3129                                                  */
3130                                                 goto add_string;
3131                                         }
3132                                         i += ret;
3133                                 }
3134                                 if (value & 0x40)
3135                                 {
3136                                         if (i >= 200) {
3137                                                 /* No more room. */
3138                                                 goto add_string;
3139                                         }
3140                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Push facility) ");
3141                                         if (ret == -1 || ret >= VAL_STRING_SIZE-i) {
3142                                                 /*
3143                                                  * We've been truncated
3144                                                  */
3145                                                 goto add_string;
3146                                         }
3147                                         i += ret;
3148                                 }
3149                                 if (value & 0x20)
3150                                 {
3151                                         if (i >= 200) {
3152                                                 /* No more room. */
3153                                                 goto add_string;
3154                                         }
3155                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Session resume facility) ");
3156                                         if (ret == -1 || ret >= VAL_STRING_SIZE-i) {
3157                                                 /*
3158                                                  * We've been truncated
3159                                                  */
3160                                                 goto add_string;
3161                                         }
3162                                         i += ret;
3163                                 }
3164                                 if (value & 0x10)
3165                                 {
3166                                         if (i >= VAL_STRING_SIZE) {
3167                                                 /* No more room. */
3168                                                 goto add_string;
3169                                         }
3170                                         ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Acknowledgement headers) ");
3171                                         if (ret == -1 || ret >= VAL_STRING_SIZE-i) {
3172                                                 /*
3173                                                  * We've been truncated
3174                                                  */
3175                                                 goto add_string;
3176                                         }
3177                                         i += ret;
3178                                 }
3179                         add_string:
3180                                 valString[VAL_STRING_SIZE-1] = '\0';
3181                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_protocol_opt, tvb, capabilitiesStart, length+1, valString);
3182                                 break;
3183                         case 0x03 : /* Method-MOR */
3184                                 value = tvb_get_guint8(tvb, offset);
3185                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_method_MOR, tvb, capabilitiesStart, length+1, value);
3186                                 break;
3187                         case 0x04 : /* Push-MOR */
3188                                 value = tvb_get_guint8(tvb, offset);
3189                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_push_MOR, tvb, capabilitiesStart, length+1, value);
3190                                 break;
3191                                 break;
3192                         case 0x05 : /* Extended Methods */
3193                                 offsetStr = offset;
3194                                 offset++;
3195                                 add_capability_vals(tvb, (type == CONNECT),
3196                                     offsetStr, length, capabilitiesStart,
3197                                     valString, sizeof valString);
3198                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_extended_methods, tvb, capabilitiesStart, length+1, valString);
3199                                 break;
3200                         case 0x06 : /* Header Code Pages */
3201                                 offsetStr = offset;
3202                                 offset++;
3203                                 add_capability_vals(tvb, (type == CONNECT),
3204                                     offsetStr, length, capabilitiesStart,
3205                                     valString, sizeof valString);
3206                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_header_code_pages, tvb, capabilitiesStart, length+1, valString);
3207                                 break;
3208                         case 0x07 : /* Aliases */
3209                                 break;
3210                         default:
3211                                 proto_tree_add_text (wsp_capabilities, tvb , capabilitiesStart, length+1,
3212                                        "Undecoded Header (0x%02X)", peek & 0x7F);
3213                                 break;
3214                 }
3215                 offset=capabilitiesStart+length+1;
3216         }
3217 }
3218
3219 static void
3220 add_capability_vals(tvbuff_t *tvb, gboolean add_string, int offsetStr,
3221     guint length, guint capabilitiesStart, char *valString,
3222     size_t valStringSize)
3223 {
3224         guint i;
3225         int ret;
3226         guint value;
3227         guint8 c;
3228
3229         i = 0;
3230         while ((offsetStr-capabilitiesStart) <= length)
3231         {
3232                 value = tvb_get_guint8(tvb, offsetStr);
3233                 if (i >= valStringSize) {
3234                         /* No more room. */
3235                         break;
3236                 }
3237                 if (add_string)
3238                 {
3239                         ret = snprintf(valString+i,valStringSize-i,
3240                             "(0x%02x - ",value);
3241                 }
3242                 else
3243                 {
3244                         ret = snprintf(valString+i,valStringSize-i,"(0x%02x) ",
3245                             value);
3246                 }
3247                 if (ret == -1 || ret >= valStringSize-i) {
3248                         /*
3249                          * We've been truncated.
3250                          */
3251                         break;
3252                 }
3253                 i += ret;
3254                 offsetStr++;
3255                 if (add_string)
3256                 {
3257                         for (;(c = tvb_get_guint8(tvb, offsetStr))
3258                             && i < valStringSize - 1; i++,offsetStr++)
3259                                 valString[i] = c;
3260                         offsetStr++;
3261                         if (i < valStringSize - 2) {
3262                                 valString[i++] = ')';
3263                                 valString[i++] = ' ';
3264                         }
3265                 }
3266         }
3267         valString[i] = '\0';
3268 }
3269
3270 static value_type_t
3271 get_value_type_len (tvbuff_t *tvb, int offset, guint *valueLen,
3272     int *valueOffset, int *nextOffset)
3273 {
3274         guint8 peek;
3275         guint32 len;
3276         guint count;
3277
3278         /* Get value part of header */
3279         peek = tvb_get_guint8 (tvb, offset);
3280         if (peek <= 30)
3281         {
3282                 /*
3283                  * The value follows "peek", and is "peek" octets long.
3284                  */
3285 #ifdef DEBUG
3286                 fprintf (stderr, "dissect_wsp: Looking for %d octets\n", peek);
3287 #endif
3288                 len = peek;
3289                 *valueLen = len;        /* Length of value */
3290                 offset++;               /* Skip the length */
3291                 *valueOffset = offset;  /* Offset of value */
3292                 offset += len;          /* Skip the value */
3293                 *nextOffset = offset;   /* Offset after value */
3294                 return VALUE_LEN_SUPPLIED;
3295         }
3296         else if (peek == 31)
3297         {
3298                 /*
3299                  * A uintvar giving the length of the value follows
3300                  * "peek", and the value follows that.
3301                  */
3302 #ifdef DEBUG
3303                 fprintf (stderr, "dissect_wsp: Looking for uintvar octets\n");
3304 #endif
3305                 offset++;               /* Skip the uintvar indicator */
3306                 count = 0;              /* Initialise count */
3307                 len = tvb_get_guintvar (tvb, offset, &count);
3308                 *valueLen = len;        /* Length of value */
3309                 offset += count;        /* Skip the length */
3310                 *valueOffset = offset;  /* Offset of value */
3311                 offset += len;          /* Skip the value */
3312                 *nextOffset = offset;   /* Offset after value */
3313                 return VALUE_LEN_SUPPLIED;
3314         }
3315         else if (peek <= 127)
3316         {
3317                 /*
3318                  * The value is a NUL-terminated string, and "peek"
3319                  * is the first octet of the string.
3320                  */
3321 #ifdef DEBUG
3322                 fprintf (stderr, "dissect_wsp: Looking for NUL-terminated string\n");
3323 #endif
3324                 len = tvb_strsize (tvb, offset);
3325                 *valueLen = len;        /* Length of value */
3326                 *valueOffset = offset;  /* Offset of value */
3327                 offset += len;          /* Skip the value */
3328                 *nextOffset = offset;   /* Offset after value */
3329                 return VALUE_IS_TEXT_STRING;
3330         }
3331         else
3332         {
3333                 /*
3334                  * "peek", with the 8th bit stripped off, is the value.
3335                  */
3336 #ifdef DEBUG
3337                 fprintf (stderr, "dissect_wsp: Value is %d\n", (peek & 0x7F));
3338 #endif
3339                 *valueLen = peek & 0x7F; /* Return the value itself */
3340                 *valueOffset = offset;  /* Offset of value */
3341                 offset++;               /* Skip the value */
3342                 *nextOffset = offset;   /* Offset after value */
3343                 return VALUE_IN_LEN;
3344         }
3345 }
3346
3347 static guint
3348 get_uintvar (tvbuff_t *tvb, guint offset, guint offsetEnd)
3349 {
3350         guint value = 0;
3351         guint octet;
3352
3353         do
3354         {
3355                 octet = tvb_get_guint8 (tvb, offset);
3356                 offset++;
3357                 value <<= 7;
3358                 value += octet & 0x7f;
3359         }
3360         while ((offsetEnd > offset) && (octet & 0x80));
3361         return value;
3362 }
3363
3364 static void
3365 add_content_type_value (proto_tree *tree, tvbuff_t *header_buff,
3366     int headerOffset, int headerLen, tvbuff_t *value_buff,
3367     value_type_t valueType, int valueLen, int hf_numeric, int hf_string,
3368     guint *contentTypep, const char **contentTypeStrp)
3369 {
3370         proto_item *ti;
3371         proto_tree *parameter_tree;
3372         const char *contentTypeStr;
3373         int offset;
3374         int subvalueLen;
3375         int subvalueOffset;
3376         guint value;
3377
3378         if (valueType == VALUE_IN_LEN)
3379         {
3380                 /*
3381                  * Constrained-media (Short-Integer).
3382                  */
3383                 proto_tree_add_uint (tree, hf_numeric,
3384                     header_buff, headerOffset, headerLen,
3385                     valueLen);  /* valueLen is the value */
3386
3387                 /*
3388                  * Return the numerical value, and a null string value
3389                  * indicating that the value is numerical.
3390                  */
3391                 *contentTypep = valueLen;
3392                 *contentTypeStrp = NULL;
3393                 return;
3394         }
3395         if (valueType == VALUE_IS_TEXT_STRING)
3396         {
3397                 /*
3398                  * Constrained-media (text, i.e. Extension-Media).
3399                  */
3400                 contentTypeStr = tvb_get_ptr (value_buff, 0, valueLen);
3401                 proto_tree_add_string (tree, hf_string,
3402                     header_buff, headerOffset, headerLen,
3403                     contentTypeStr);
3404
3405                 /*
3406                  * Return the string value, and set the numerical value
3407                  * to 0 (as it shouldn't be used).
3408                  */
3409                 *contentTypep = 0;
3410                 *contentTypeStrp = contentTypeStr;
3411                 return;
3412         }
3413
3414         /*
3415          * Content-general-form; Value-length, followed by Media-range,
3416          * followed by optional Accept-parameters.
3417          *
3418          * Get Value-length.
3419          */
3420         valueType = get_value_type_len (value_buff, 0, &subvalueLen,
3421             &subvalueOffset, &offset);
3422         if (valueType == VALUE_IS_TEXT_STRING)
3423         {
3424                 /*
3425                  * Extension-Media; value is a string.
3426                  */
3427                 contentTypeStr =
3428                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
3429                 ti = proto_tree_add_string (tree, hf_string, header_buff,
3430                     headerOffset, headerLen, contentTypeStr);
3431
3432                 /*
3433                  * Return the string value, and set the numerical value
3434                  * to 0 (as it shouldn't be used).
3435                  */
3436                 *contentTypep = 0;
3437                 *contentTypeStrp = contentTypeStr;
3438         }
3439         else
3440         {
3441                 /*
3442                  * Well-known-media; value is an Integer.
3443                  */
3444                 if (get_integer (value_buff, subvalueOffset, subvalueLen,
3445                     valueType, &value) < 0)
3446                 {
3447                         proto_tree_add_text (tree, header_buff,
3448                             headerOffset, headerLen,
3449                             "Invalid integer for Well-known-media");
3450
3451                         /*
3452                          * Content type is invalid.
3453                          * Don't try to parse the rest of the value.
3454                          */
3455                         *contentTypep = 0;
3456                         *contentTypeStrp = NULL;
3457                         return;
3458                 }
3459                 ti = proto_tree_add_uint (tree, hf_numeric,
3460                     header_buff, headerOffset, headerLen, value);
3461
3462                 /*
3463                  * Return the numerical value, and a null string value
3464                  * indicating that the value is numerical.
3465                  */
3466                 *contentTypep = value;
3467                 *contentTypeStrp = NULL;
3468         }
3469
3470         /*
3471          * Process the rest of the value as parameters.
3472          */
3473         parameter_tree = proto_item_add_subtree(ti,
3474             ett_content_type_parameters);
3475         while (tvb_reported_length_remaining (value_buff, offset) > 0)
3476                 offset = add_parameter (parameter_tree, value_buff, offset);
3477 }
3478
3479 guint
3480 add_content_type (proto_tree *tree, tvbuff_t *tvb, guint offset,
3481     guint *contentTypep, const char **contentTypeStrp)
3482 {
3483         int valueStart;
3484         value_type_t valueType;
3485         int valueTypeLen;
3486         guint valueLen;
3487         int valueOffset;
3488         tvbuff_t *value_buff;
3489
3490         valueStart = offset;
3491
3492         /*
3493          * Get the value type and length (or, if the type is VALUE_IN_LEN,
3494          * meaning the value is a Short-integer, get the value type
3495          * and the value itself).
3496          */
3497         valueType = get_value_type_len (tvb, valueStart, &valueLen,
3498             &valueOffset, &offset);
3499         valueTypeLen = offset - valueStart;
3500
3501         /*
3502          * Get a tvbuff for the value.
3503          * XXX - can valueLen be 0?
3504          * XXX - cut the actual length short so that it doesn't run
3505          * past the actual length of tvb.
3506          */
3507         if (valueType != VALUE_IN_LEN) {
3508                 value_buff = tvb_new_subset (tvb, valueOffset, valueLen,
3509                     valueLen);
3510         } else {
3511                 /*
3512                  * XXX - when the last dissector is tvbuffified,
3513                  * so that NULL is no longer a valid tvb pointer
3514                  * value in "proto_tree_add" calls, just
3515                  * set "value_buff" to NULL.
3516                  *
3517                  * XXX - can we already do that?  I.e., will that
3518                  * cause us always to crash if we mistakenly try
3519                  * to fetch the value of a VALUE_IN_LEN item?
3520                  */
3521                 value_buff = tvb_new_subset (tvb, valueStart, 0, 0);
3522         }
3523
3524         add_content_type_value (tree, tvb, valueStart, valueTypeLen, value_buff,
3525             valueType, valueLen, hf_wsp_content_type,
3526             hf_wsp_content_type_str, contentTypep, contentTypeStrp);
3527
3528         return offset;
3529 }
3530
3531 static void
3532 add_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
3533     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3534     int valueLen, int hf_numeric, guint8 headerType)
3535 {
3536         add_integer_value_header_common (tree, header_buff, headerLen,
3537             value_buff, valueType, valueLen, hf_numeric, headerType,
3538             vals_field_names);
3539 }
3540
3541 static void
3542 add_openwave_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
3543     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3544     int valueLen, int hf_numeric, guint8 headerType)
3545 {
3546         add_integer_value_header_common (tree, header_buff, headerLen,
3547             value_buff, valueType, valueLen, hf_numeric, headerType,
3548             vals_openwave_field_names);
3549 }
3550
3551 static void
3552 add_integer_value_header_common (proto_tree *tree, tvbuff_t *header_buff,
3553     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3554     int valueLen, int hf_numeric, guint8 headerType,
3555     const value_string *vals)
3556 {
3557         guint value;
3558
3559         if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
3560         {
3561                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3562                     "Invalid %s integer value",
3563                     match_strval (headerType, vals));
3564         }
3565         else
3566         {
3567                 proto_tree_add_uint (tree, hf_numeric,
3568                     header_buff, 0, headerLen, value);
3569         }
3570 }
3571
3572 static void
3573 add_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
3574     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3575     int valueLen, int hf_string, guint8 headerType)
3576 {
3577         add_string_value_header_common (tree, header_buff, headerLen,
3578             value_buff, valueType, valueLen, hf_string, headerType,
3579             vals_field_names);
3580 }
3581
3582 static void
3583 add_openwave_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
3584     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3585     int valueLen, int hf_string, guint8 headerType)
3586 {
3587         add_string_value_header_common (tree, header_buff, headerLen,
3588             value_buff, valueType, valueLen, hf_string, headerType,
3589             vals_openwave_field_names);
3590 }
3591
3592 static void
3593 add_string_value_header_common (proto_tree *tree, tvbuff_t *header_buff,
3594     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3595     int valueLen, int hf_string, guint8 headerType,
3596     const value_string *vals)
3597 {
3598         if (valueType != VALUE_IS_TEXT_STRING)
3599         {
3600                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3601                     "Invalid %s string value",
3602                     match_strval (headerType, vals));
3603         }
3604         else
3605         {
3606                 proto_tree_add_string (tree, hf_string, header_buff,
3607                         0, headerLen, tvb_get_ptr (value_buff, 0, valueLen));
3608         }
3609 }
3610
3611 static void
3612 add_quoted_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
3613     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3614     int valueLen, int hf_string, guint8 headerType)
3615 {
3616         if (valueType != VALUE_IS_TEXT_STRING)
3617         {
3618                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3619                     "Invalid %s quoted string value",
3620                     match_strval (headerType, vals_field_names));
3621         }
3622         else
3623         {
3624                 proto_tree_add_string (tree, hf_string, header_buff,
3625                         0, headerLen, tvb_get_ptr (value_buff, 1, valueLen - 1));
3626         }
3627 }
3628
3629 /* Utility function to add a date value to the protocol tree */
3630 static void
3631 add_date_value_header (proto_tree *tree, tvbuff_t *header_buff,
3632     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3633     int valueLen, int hf_time, guint8 headerType)
3634 {
3635         guint secs;
3636         nstime_t timeValue;
3637
3638         /* Attempt to get the date value from the buffer */
3639         if (get_integer (value_buff, 0, valueLen, valueType, &secs) == 0)
3640         {
3641                 /*
3642                  * Fill in the "struct timeval", and add it to the
3643                  * protocol tree.
3644                  * Note: this will succeed even if it's a Short-integer.
3645                  * A Short-integer would work, but, as the time values
3646                  * are UNIX seconds-since-the-Epoch value, and as
3647                  * there weren't WAP phones or Web servers back in
3648                  * late 1969/early 1970, they're unlikely to be used.
3649                  */
3650                 timeValue.secs = secs;
3651                 timeValue.nsecs = 0;
3652                 proto_tree_add_time (tree, hf_time, header_buff, 0,
3653                         headerLen, &timeValue);
3654         }
3655         else
3656         {
3657                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3658                     "Invalid %s date value",
3659                     match_strval (headerType, vals_field_names));
3660         }
3661 }
3662
3663 static int
3664 add_parameter (proto_tree *tree, tvbuff_t *value_buff, int offset)
3665 {
3666         int startOffset;
3667         value_type_t valueType;
3668         int subvalueLen;
3669         int subvalueOffset;
3670         guint value;
3671
3672         startOffset = offset;
3673         valueType = get_value_type_len (value_buff, offset,
3674             &subvalueLen, &subvalueOffset, &offset);
3675         if (valueType == VALUE_IS_TEXT_STRING)
3676         {
3677                 /*
3678                  * Untyped-parameter.
3679                  */
3680                 offset = add_untyped_parameter (tree, value_buff, startOffset, offset);
3681                 return offset;
3682         }
3683
3684         /*
3685          * Well-known-parameter-token.
3686          */
3687         if (get_integer (value_buff, subvalueOffset,
3688             subvalueLen, valueType, &value) < 0)
3689         {
3690                 proto_tree_add_text (tree, value_buff, startOffset,
3691                     offset - startOffset,
3692                     "Invalid Well-known-parameter-token");
3693                 return offset;
3694         }
3695
3696         switch (value) {
3697
3698                 case 0x01:      /* WSP 1.1 encoding - Charset: Well-known-charset */
3699                         offset = add_parameter_charset (tree, value_buff, startOffset, offset);
3700                         break;
3701
3702                 case 0x03:      /* WSP 1.1 encoding - Type: Integer-value */
3703                         offset = add_parameter_type (tree, value_buff, startOffset, offset);
3704                         break;
3705
3706                 case 0x05:      /* WSP 1.1 encoding - Name: Text-string */
3707                 case 0x17:      /* WSP 1.4 encoding - Name: Text-value */
3708                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3709                                             hf_wsp_parameter_name, "Name");
3710                         break;
3711
3712                 case 0x06:      /* WSP 1.1 encoding - Filename: Text-string */
3713                 case 0x18:      /* WSP 1.4 encoding - Filename: Text-value */
3714                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3715                                             hf_wsp_parameter_filename, "Filename");
3716                         break;
3717
3718                 case 0x09:      /* WSP 1.2 encoding - Type (special): Constrained-encoding */
3719                         offset = add_constrained_encoding(tree, value_buff, startOffset, offset);
3720                         break;
3721
3722                 case 0x0A:      /* WSP 1.2 encoding - Start: Text-string */
3723                 case 0x19:      /* WSP 1.4 encoding - Start (with multipart/related): Text-value */
3724                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3725                                             hf_wsp_parameter_start, "Start");
3726                         break;
3727
3728                 case 0x0B:      /* WSP 1.2 encoding - Start-info: Text-string */
3729                 case 0x1A:      /* WSP 1.4 encoding - Start-info (with multipart/related): Text-value */
3730                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3731                                             hf_wsp_parameter_start_info, "Start-info");
3732                         break;
3733
3734                 case 0x0C:      /* WSP 1.3 encoding - Comment: Text-string */
3735                 case 0x1B:      /* WSP 1.4 encoding - Comment: Text-value */
3736                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3737                                             hf_wsp_parameter_comment, "Comment");
3738                         break;
3739
3740                 case 0x0D:      /* WSP 1.3 encoding - Domain: Text-string */
3741                 case 0x1C:      /* WSP 1.4 encoding - Domain: Text-value */
3742                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3743                                             hf_wsp_parameter_domain, "Domain");
3744                         break;
3745
3746                 case 0x0F:      /* WSP 1.3 encoding - Path: Text-string */
3747                 case 0x1D:      /* WSP 1.4 encoding - Path: Text-value */
3748                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3749                                             hf_wsp_parameter_path, "Path");
3750                         break;
3751
3752                 case 0x11:      /* WSP 1.4 encoding - SEC: Short-integer (OCTET) */
3753                         proto_tree_add_uint (tree, hf_wsp_parameter_sec, value_buff, startOffset, 2,
3754                                         tvb_get_guint8 (value_buff, startOffset+1) & 0x7F);
3755                         offset++;
3756                         break;
3757                 
3758                 case 0x12:      /* WSP 1.4 encoding - MAC: Text-value */
3759                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3760                                             hf_wsp_parameter_mac, "MAC");
3761                         break;
3762                 
3763                 case 0x00:      /* WSP 1.1 encoding - Q: Q-value */
3764                 case 0x02:      /* WSP 1.1 encoding - Level: Version-value */
3765                 case 0x07:      /* WSP 1.1 encoding - Differences: Field-name */
3766                 case 0x08:      /* WSP 1.1 encoding - Padding: Short-integer */
3767                 case 0x0E:      /* WSP 1.3 encoding - Max-Age: Delta-seconds-value */
3768                 case 0x10:      /* WSP 1.3 encoding - Secure: No-value */
3769                 case 0x13:      /* WSP 1.4 encoding - Creation-date: Date-value */
3770                 case 0x14:      /* WSP 1.4 encoding - Modification-date: Date-value */
3771                 case 0x15:      /* WSP 1.4 encoding - Read-date: Date-value */
3772                 case 0x16:      /* WSP 1.4 encoding - Size: Integer-value */
3773                 default:
3774                         break;
3775         }
3776
3777         return offset;
3778 }
3779
3780 static int
3781 add_untyped_parameter (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3782     int offset)
3783 {
3784         const guint8 *token;
3785         value_type_t valueType;
3786         int subvalueLen;
3787         int subvalueOffset;
3788         guint value;
3789         int vOffset = offset;
3790
3791         token = tvb_get_ptr (value_buff, startOffset, offset - startOffset);
3792         /*
3793          * Now an Untyped-value; either an Integer-value or a Text-value.
3794          */
3795         valueType = get_value_type_len (value_buff, offset,
3796             &subvalueLen, &subvalueOffset, &offset);
3797         if (valueType == VALUE_IS_TEXT_STRING)
3798         {
3799                 /*
3800                  * Text-value.
3801                  */
3802                 if ((offset - vOffset) == 1) {
3803                         /*
3804                          * No-value.  (stringSize includes the terminating
3805                          * null byte, so an empty string has a size of 1.)
3806                          */
3807                         proto_tree_add_text (tree, value_buff, startOffset,
3808                             offset - startOffset,
3809                             "%s", token);
3810                         return offset;
3811                 }
3812                 proto_tree_add_text (tree, value_buff, startOffset,
3813                     offset - startOffset,
3814                     "%s: %s", token,
3815                     tvb_get_ptr (value_buff, vOffset, offset - vOffset));
3816         }
3817         else
3818         {
3819                 /*
3820                  * Integer-value.
3821                  */
3822                 if (get_integer (value_buff, subvalueOffset, subvalueLen,
3823                     valueType, &value) == 0)
3824                 {
3825                         proto_tree_add_text (tree, value_buff, startOffset,
3826                             offset - startOffset,
3827                             "%s: %u", token, value);
3828                 }
3829                 else
3830                 {
3831                         proto_tree_add_text (tree, value_buff, startOffset,
3832                             offset - startOffset,
3833                             "%s: Invalid Integer-value", token);
3834                 }
3835         }
3836         return offset;
3837 }
3838
3839 static int
3840 add_parameter_charset (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3841     int offset)
3842 {
3843         value_type_t valueType;
3844         int subvalueLen;
3845         int subvalueOffset;
3846         guint value;
3847
3848         valueType = get_value_type_len (value_buff, offset,
3849             &subvalueLen, &subvalueOffset, &offset);
3850         if (valueType == VALUE_IN_LEN)
3851         {
3852                 /*
3853                  * Integer-value.
3854                  */
3855                 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3856                     value_buff, startOffset, offset - startOffset,
3857                     subvalueLen);       /* subvalueLen is the value */
3858                 return offset;
3859         }
3860         if (valueType == VALUE_IS_TEXT_STRING)
3861         {
3862                 /*
3863                  * Invalid.
3864                  */
3865                 proto_tree_add_text (tree, value_buff, startOffset,
3866                     offset - startOffset, "Invalid Well-known charset");
3867                 return offset;
3868         }
3869
3870         /*
3871          * First byte had the 8th bit set.
3872          */
3873         if (subvalueLen == 0) {
3874                 /*
3875                  * Any-charset.
3876                  * XXX - add this as a field?
3877                  */
3878                 proto_tree_add_text (tree, value_buff, startOffset,
3879                     offset- startOffset, "*");
3880                 return offset;
3881         }
3882
3883         if (get_integer(value_buff, subvalueOffset, subvalueLen,
3884             valueType, &value) == -1) {
3885                 proto_tree_add_text (tree, value_buff, startOffset,
3886                     offset - startOffset, "Length %u not handled in Well-known charset",
3887                         subvalueLen);
3888         } else {
3889                 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3890                     value_buff, startOffset, offset - startOffset, value);
3891         }
3892         return offset;
3893 }
3894
3895 static int
3896 add_constrained_encoding (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3897     int offset)
3898 {
3899         value_type_t valueType;
3900         int subvalueLen;
3901         int subvalueOffset;
3902         guint value;
3903
3904         valueType = get_value_type_len (value_buff, offset,
3905             &subvalueLen, &subvalueOffset, &offset);
3906         if (valueType == VALUE_IN_LEN)
3907         {
3908                 /*
3909                  * Integer-value, invalid
3910                  */
3911                 proto_tree_add_text (tree, value_buff, startOffset,
3912                     offset - startOffset, "Invalid multipart type parameter");
3913                 return offset;
3914         }
3915         if (valueType == VALUE_IS_TEXT_STRING)
3916         {
3917                 /*
3918                  * type-label.
3919                  */
3920                 proto_tree_add_string (tree, hf_wsp_parameter_upart_type,
3921                     value_buff, startOffset, offset - startOffset,
3922                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
3923                 return offset;
3924         }
3925         /*
3926          * First byte had the 8th bit set.
3927          */
3928         get_integer(value_buff, subvalueOffset, subvalueLen, valueType, &value);
3929         proto_tree_add_uint (tree, hf_wsp_parameter_upart_type_value,
3930             value_buff, startOffset, offset - startOffset, value);
3931         return offset;
3932 }
3933
3934 static int
3935 add_parameter_type (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3936     int offset)
3937 {
3938         value_type_t valueType;
3939         int subvalueLen;
3940         int subvalueOffset;
3941         guint value;
3942
3943         valueType = get_value_type_len (value_buff, offset,
3944             &subvalueLen, &subvalueOffset, &offset);
3945         if (get_integer(value_buff, subvalueOffset, subvalueLen,
3946             valueType, &value) == -1) {
3947                 proto_tree_add_text (tree, value_buff, startOffset,
3948                     offset - startOffset, "Invalid type");
3949         } else {
3950                 proto_tree_add_uint (tree, hf_wsp_parameter_type, value_buff,
3951                     startOffset, offset - startOffset, value);
3952         }
3953         return offset;
3954 }
3955
3956 static int
3957 add_parameter_text (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3958     int offset, int hf_string, const char *paramName)
3959 {
3960         value_type_t valueType;
3961         int subvalueLen;
3962         int subvalueOffset;
3963
3964         valueType = get_value_type_len (value_buff, offset,
3965             &subvalueLen, &subvalueOffset, &offset);
3966         if (valueType != VALUE_IS_TEXT_STRING) {
3967                 proto_tree_add_text (tree, value_buff, startOffset,
3968                     offset - startOffset, "Invalid %s", paramName);
3969         } else {
3970                 proto_tree_add_string (tree, hf_string, value_buff,
3971                             startOffset, offset - startOffset,
3972                             tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
3973         }
3974         return offset;
3975 }
3976
3977 void
3978 add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType,
3979     const char *contentTypeStr)
3980 {
3981         guint offset = 0;
3982         guint variableStart = 0;
3983         guint variableEnd = 0;
3984         guint valueStart = 0;
3985         guint valueEnd = 0;
3986         guint8 peek = 0;
3987         proto_item *ti;
3988         proto_tree *sub_tree;
3989
3990         /* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian); */
3991         ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian);
3992         sub_tree = proto_item_add_subtree(ti, ett_post);
3993
3994         if (contentTypeStr == NULL && contentType == 0x12)
3995         {
3996                 /*
3997                  * URL Encoded data.
3998                  * Iterate through post data.
3999                  */
4000                 for (offset = 0; offset < tvb_reported_length (tvb); offset++)
4001                 {
4002                         peek = tvb_get_guint8 (tvb, offset);
4003                         if (peek == '=')
4004                         {
4005                                 variableEnd = offset;
4006                                 valueStart = offset+1;
4007                         }
4008                         else if (peek == '&')
4009                         {
4010                                 if (variableEnd > 0)
4011                                 {
4012                                         add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
4013                                 }
4014                                 variableStart = offset+1;
4015                                 variableEnd = 0;
4016                                 valueStart = 0;
4017                                 valueEnd = 0;
4018                         }
4019                 }
4020
4021                 /* See if there's outstanding data */
4022                 if (variableEnd > 0)
4023                 {
4024                         add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
4025                 }
4026         }
4027         else if ((contentType == 0x22) || (contentType == 0x23) || (contentType == 0x23) || (contentType == 0x24) ||
4028                  (contentType == 0x25) || (contentType == 0x26) || (contentType == 0x33))
4029         {
4030                 add_multipart_data(sub_tree, tvb);
4031         }
4032 }
4033
4034 static void
4035 add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
4036 {
4037         int variableLength = variableEnd-variableStart;
4038         int valueLength = 0;
4039         char *variableBuffer;
4040         char *valueBuffer;
4041
4042         variableBuffer = g_malloc (variableLength+1);
4043         strncpy (variableBuffer, tvb_get_ptr (tvb, variableStart, variableLength), variableLength);
4044         variableBuffer[variableLength] = 0;
4045
4046         if (valueEnd < valueStart)
4047         {
4048                 valueBuffer = g_malloc (1);
4049                 valueBuffer[0] = 0;
4050                 valueEnd = valueStart;
4051         }
4052         else
4053         {
4054                 valueLength = valueEnd-valueStart;
4055                 valueBuffer = g_malloc (valueLength+1);
4056                 strncpy (valueBuffer, tvb_get_ptr (tvb, valueStart, valueLength), valueLength);
4057                 valueBuffer[valueLength] = 0;
4058         }
4059
4060         /* Check for variables with no value */
4061         if (valueStart >= tvb_reported_length (tvb))
4062         {
4063                 valueStart = tvb_reported_length (tvb);
4064                 valueEnd = valueStart;
4065         }
4066         valueLength = valueEnd-valueStart;
4067
4068         proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
4069
4070         g_free (variableBuffer);
4071         g_free (valueBuffer);
4072 }
4073
4074 static void
4075 add_multipart_data (proto_tree *tree, tvbuff_t *tvb)
4076 {
4077         int              offset = 0;
4078         guint            nextOffset;
4079         guint            nEntries = 0;
4080         guint            count;
4081         guint            HeadersLen;
4082         guint            DataLen;
4083         guint            contentType = 0;
4084         const char      *contentTypeStr;
4085         tvbuff_t        *tmp_tvb;
4086         int              partnr = 1;
4087         int              part_start;
4088
4089         proto_item      *sub_tree = NULL,
4090                         *ti;
4091         proto_tree      *mpart_tree;
4092
4093         nEntries = tvb_get_guintvar (tvb, offset, &count);
4094         offset += count;
4095         if (nEntries)
4096         {
4097                 sub_tree = proto_tree_add_text(tree, tvb, offset - count, 0,
4098                                         "Multipart body");
4099                 proto_item_add_subtree(sub_tree, ett_mpartlist);
4100         }
4101         while (nEntries--)
4102         {
4103                 part_start = offset;
4104                 HeadersLen = tvb_get_guintvar (tvb, offset, &count);
4105                 offset += count;
4106                 DataLen = tvb_get_guintvar (tvb, offset, &count);
4107                 offset += count;
4108                 ti = proto_tree_add_uint(sub_tree, hf_wsp_mpart, tvb, part_start,
4109                                         HeadersLen + DataLen + (offset - part_start), partnr);
4110                 mpart_tree = proto_item_add_subtree(ti, ett_multiparts);
4111                 nextOffset = add_content_type (mpart_tree, tvb, offset, &contentType, &contentTypeStr);
4112                 HeadersLen -= (nextOffset - offset);
4113                 if (HeadersLen > 0)
4114                 {
4115                         tmp_tvb = tvb_new_subset (tvb, nextOffset, HeadersLen, HeadersLen);
4116                         add_headers (mpart_tree, tmp_tvb);
4117                 }
4118                 offset = nextOffset + HeadersLen;
4119                 proto_tree_add_item (mpart_tree, hf_wsp_multipart_data, tvb, offset, DataLen, bo_little_endian);
4120                 offset += DataLen;
4121                 partnr++;
4122         }
4123 }
4124
4125 static gint
4126 get_integer (tvbuff_t *tvb, guint offset, guint valueLength,
4127     value_type_t valueType, guint *value)
4128 {
4129         if (valueType == VALUE_IS_TEXT_STRING) {
4130                 /*
4131                  * Not valid.
4132                  */
4133                 return -1;
4134         }
4135
4136         if (valueType == VALUE_IN_LEN) {
4137                 /*
4138                  * Short-integer.
4139                  */
4140                 *value = valueLength;
4141                 return 0;
4142         }
4143
4144         /*
4145          * Long-integer.
4146          */
4147         switch (valueLength)
4148         {
4149                 case 1:
4150                         *value = tvb_get_guint8(tvb, offset);
4151                         break;
4152                 case 2:
4153                         *value = tvb_get_ntohs(tvb, offset);
4154                         break;
4155                 case 3:
4156                         *value = tvb_get_ntoh24(tvb, offset);
4157                         break;
4158                 case 4:
4159                         *value = tvb_get_ntohl(tvb, offset);
4160                         break;
4161                 default:
4162                         /* TODO: Need to read peek octets */
4163                         *value = 0;
4164                         fprintf (stderr, "dissect_wsp: get_integer size %u NYI\n", valueLength);
4165                         break;
4166         }
4167         return 0;
4168 }
4169
4170 /* Register the protocol with Ethereal */
4171 void
4172 proto_register_wsp(void)
4173 {
4174
4175 /* Setup list of header fields */
4176         static hf_register_info hf[] = {
4177                 { &hf_wsp_header_tid,
4178                         {       "Transaction ID",
4179                                 "wsp.TID",
4180                                  FT_UINT8, BASE_HEX, NULL, 0x00,
4181                                 "Transaction ID", HFILL
4182                         }
4183                 },
4184                 { &hf_wsp_header_pdu_type,
4185                         {       "PDU Type",
4186                                 "wsp.pdu_type",
4187                                  FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
4188                                 "PDU Type", HFILL
4189                         }
4190                 },
4191                 { &hf_wsp_version_major,
4192                         {       "Version (Major)",
4193                                 "wsp.version.major",
4194                                  FT_UINT8, BASE_DEC, NULL, 0xF0,
4195                                 "Version (Major)", HFILL
4196                         }
4197                 },
4198                 { &hf_wsp_version_minor,
4199                         {       "Version (Minor)",
4200                                 "wsp.version.minor",
4201                                  FT_UINT8, BASE_DEC, NULL, 0x0F,
4202                                 "Version (Minor)", HFILL
4203                         }
4204                 },
4205                 { &hf_wsp_capability_length,
4206                         {       "Capability Length",
4207                                 "wsp.capability.length",
4208                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4209                                 "Capability Length", HFILL
4210                         }
4211                 },
4212                 { &hf_wsp_header_length,
4213                         {       "Headers Length",
4214                                 "wsp.headers_length",
4215                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4216                                 "Headers Length", HFILL
4217                         }
4218                 },
4219                 { &hf_wsp_capabilities_section,
4220                         {       "Capabilities",
4221                                 "wsp.capabilities",
4222                                  FT_NONE, BASE_DEC, NULL, 0x00,
4223                                 "Capabilities", HFILL
4224                         }
4225                 },
4226                 { &hf_wsp_headers_section,
4227                         {       "Headers",
4228                                 "wsp.headers",
4229                                  FT_NONE, BASE_DEC, NULL, 0x00,
4230                                 "Headers", HFILL
4231                         }
4232                 },
4233                 { &hf_wsp_header,
4234                         {       "Header",
4235                                 "wsp.headers.header",
4236                                  FT_NONE, BASE_DEC, NULL, 0x00,
4237                                 "Header", HFILL
4238                         }
4239                 },
4240                 { &hf_wsp_header_uri_len,
4241                         {       "URI Length",
4242                                 "wsp.uri_length",
4243                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4244                                 "URI Length", HFILL
4245                         }
4246                 },
4247                 { &hf_wsp_header_uri,
4248                         {       "URI",
4249                                 "wsp.uri",
4250                                  FT_STRING, BASE_NONE, NULL, 0x00,
4251                                 "URI", HFILL
4252                         }
4253                 },
4254                 { &hf_wsp_server_session_id,
4255                         {       "Server Session ID",
4256                                 "wsp.server.session_id",
4257                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4258                                 "Server Session ID", HFILL
4259                         }
4260                 },
4261                 { &hf_wsp_header_status,
4262                         {       "Status",
4263                                 "wsp.reply.status",
4264                                  FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
4265                                 "Status", HFILL
4266                         }
4267                 },
4268                 { &hf_wsp_content_type,
4269                         {       "Content Type",
4270                                 "wsp.content_type.type",
4271                                  FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
4272                                 "Content Type", HFILL
4273                         }
4274                 },
4275                 { &hf_wsp_content_type_str,
4276                         {       "Content Type",
4277                                 "wsp.content_type.type.string",
4278                                  FT_STRING, BASE_NONE, NULL, 0x00,
4279                                 "Content Type", HFILL
4280                         }
4281                 },
4282                 { &hf_wsp_parameter_well_known_charset,
4283                         {       "Charset",
4284                                 "wsp.content_type.parameter.charset",
4285                                  FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
4286                                 "Charset", HFILL
4287                         }
4288                 },
4289                 { &hf_wsp_parameter_type,
4290                         {       "Type",
4291                                 "wsp.content_type.parameter.type",
4292                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4293                                 "Type", HFILL
4294                         }
4295                 },
4296                 { &hf_wsp_parameter_name,
4297                         {       "Name",
4298                                 "wsp.content_type.parameter.name",
4299                                  FT_STRING, BASE_NONE, NULL, 0x00,
4300                                 "Name", HFILL
4301                         }
4302                 },
4303                 { &hf_wsp_parameter_filename,
4304                         {       "Filename",
4305                                 "wsp.content_type.parameter.filename",
4306                                  FT_STRING, BASE_NONE, NULL, 0x00,
4307                                 "Filename", HFILL
4308                         }
4309                 },
4310                 { &hf_wsp_parameter_start,
4311                         {       "Start",
4312                                 "wsp.content_type.parameter.start",
4313                                  FT_STRING, BASE_NONE, NULL, 0x00,
4314                                 "Start", HFILL
4315                         }
4316                 },
4317                 { &hf_wsp_parameter_start_info,
4318                         {       "Start-info",
4319                                 "wsp.content_type.parameter.start_info",
4320                                  FT_STRING, BASE_NONE, NULL, 0x00,
4321                                 "Start-info", HFILL
4322                         }
4323                 },
4324                 { &hf_wsp_parameter_comment,
4325                         {       "Comment",
4326                                 "wsp.content_type.parameter.comment",
4327                                  FT_STRING, BASE_NONE, NULL, 0x00,
4328                                 "Comment", HFILL
4329                         }
4330                 },
4331                 { &hf_wsp_parameter_domain,
4332                         {       "Domain",
4333                                 "wsp.content_type.parameter.domain",
4334                                  FT_STRING, BASE_NONE, NULL, 0x00,
4335                                 "Domain", HFILL
4336                         }
4337                 },
4338                 { &hf_wsp_parameter_path,
4339                         {       "Path",
4340                                 "wsp.content_type.parameter.path",
4341                                  FT_STRING, BASE_NONE, NULL, 0x00,
4342                                 "Path", HFILL
4343                         }
4344                 },
4345                 { &hf_wsp_parameter_sec,
4346                         {       "SEC",
4347                                 "wsp.content_type.parameter.sec",
4348                                  FT_UINT8, BASE_HEX, VALS (vals_wsp_parameter_sec), 0x00,
4349                                 "SEC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
4350                         }
4351                 },
4352                 { &hf_wsp_parameter_mac,
4353                         {       "MAC",
4354                                 "wsp.content_type.parameter.mac",
4355                                  FT_STRING, BASE_NONE, NULL, 0x00,
4356                                 "MAC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
4357                         }
4358                 },
4359                 { &hf_wsp_parameter_upart_type,
4360                         {       "Type",
4361                                 "wsp.content_type.parameter.upart.type",
4362                                  FT_STRING, BASE_NONE, NULL, 0x00,
4363                                 "Multipart type", HFILL
4364                         }
4365                 },
4366                 { &hf_wsp_parameter_upart_type_value,
4367                         {       "Type",
4368                                 "wsp.content_type.parameter.upart.type.int",
4369                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4370                                 "Multipart type (int value)", HFILL
4371                         }
4372                 },
4373                 { &hf_wsp_reply_data,
4374                         {       "Data",
4375                                 "wsp.reply.data",
4376                                  FT_NONE, BASE_NONE, NULL, 0x00,
4377                                 "Data", HFILL
4378                         }
4379                 },
4380                 { &hf_wsp_header_shift_code,
4381                         {       "Shift code",
4382                                 "wsp.header.shift",
4383                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4384                                  FT_UINT8, BASE_HEX, NULL, 0x00,
4385                                 "Header code page shift code", HFILL
4386                         }
4387                 },
4388                 { &hf_wsp_header_accept,
4389                         {       "Accept",
4390                                 "wsp.header.accept",
4391                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4392                                  FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
4393                                 "Accept", HFILL
4394                         }
4395                 },
4396                 { &hf_wsp_header_accept_str,
4397                         {       "Accept",
4398                                 "wsp.header.accept.string",
4399                                  FT_STRING, BASE_NONE, NULL, 0x00,
4400                                 "Accept", HFILL
4401                         }
4402                 },
4403                 { &hf_wsp_header_accept_application,
4404                         {       "Accept-Application",
4405                                 "wsp.header.accept_application",
4406                                  FT_UINT32, BASE_HEX, NULL, 0x00,
4407                                 "Accept-Application", HFILL
4408                         }
4409                 },
4410                 { &hf_wsp_header_accept_application_str,
4411                         {       "Accept-Application",
4412                                 "wsp.header.accept_application.string",
4413                                  FT_STRING, BASE_NONE, NULL, 0x00,
4414                                 "Accept-Application", HFILL
4415                         }
4416                 },
4417                 { &hf_wsp_header_accept_charset,
4418                         {       "Accept-Charset",
4419                                 "wsp.header.accept_charset",
4420                                  FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
4421                                 "Accept-Charset", HFILL
4422                         }
4423                 },
4424                 { &hf_wsp_header_accept_charset_str,
4425                         {       "Accept-Charset",
4426                                 "wsp.header.accept_charset.string",
4427                                  FT_STRING, BASE_NONE, NULL, 0x00,
4428                                 "Accept-Charset", HFILL
4429                         }
4430                 },
4431                 { &hf_wsp_header_accept_language,
4432                         {       "Accept-Language",
4433                                 "wsp.header.accept_language",
4434                                  FT_UINT8, BASE_HEX, VALS ( vals_languages ), 0x00,
4435                                 "Accept-Language", HFILL
4436                         }
4437                 },
4438                 { &hf_wsp_header_accept_language_str,
4439                         {       "Accept-Language",
4440                                 "wsp.header.accept_language.string",
4441                                  FT_STRING, BASE_NONE, NULL, 0x00,
4442                                 "Accept-Language", HFILL
4443                         }
4444                 },
4445                 { &hf_wsp_header_accept_ranges,
4446                         {       "Accept-Ranges",
4447                                 "wsp.header.accept_ranges",
4448                                  FT_UINT8, BASE_HEX, VALS ( vals_accept_ranges ), 0x00,
4449                                 "Accept-Ranges", HFILL
4450                         }
4451                 },
4452                 { &hf_wsp_header_accept_ranges_str,
4453                         {       "Accept-Ranges",
4454                                 "wsp.header.accept_ranges.string",
4455                                  FT_STRING, BASE_NONE, NULL, 0x00,
4456                                 "Accept-Ranges", HFILL
4457                         }
4458                 },
4459                 { &hf_wsp_header_age,
4460                         {       "Age",
4461                                 "wsp.header.age",
4462                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4463                                 "Age", HFILL
4464                         }
4465                 },
4466                 { &hf_wsp_header_openwave_proxy_push_addr,
4467                         {       "x-up-proxy-push-addr",
4468                                 "wsp.header.x-up-proxy-push-addr",
4469                                  FT_BYTES, BASE_HEX, NULL, 0x00,
4470                                 "The network address and port number that the handset can receive UPNOTIFY pushes on.", HFILL
4471                         }
4472                 },
4473                 { &hf_wsp_header_openwave_proxy_push_accept,
4474                         {       "x-up-proxy-push-accept",
4475                                 "wsp.header.x-up-proxy-push-accept",
4476                                  FT_STRING, BASE_NONE, NULL, 0x00,
4477                                 "The content types that the handset can handle when sent via UPNOTIFY pushes.", HFILL
4478                         }
4479                 },
4480                 { &hf_wsp_header_openwave_proxy_push_seq,
4481                         {       "x-up-proxy-push-seq",
4482                                 "wsp.header.x-up-proxy-push-seq",
4483                                  FT_UINT16, BASE_DEC, NULL, 0x00,
4484                                 "Specifies the sequence number of the last UPNOTIFY push sent.", HFILL
4485                         }
4486                 },
4487                 { &hf_wsp_header_openwave_proxy_notify,
4488                         {       "x-up-proxy-notify",
4489                                 "wsp.header.x-up-proxy-notify",
4490                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4491                                 "Indicates to the handset that there are pending UPNOTIFY pushes waiting.", HFILL
4492                         }
4493                 },
4494                 { &hf_wsp_header_openwave_proxy_operator_domain,
4495                         {       "x-up-proxy-operator-domain",
4496                                 "wsp.header.x-up-proxy-operator-domain",
4497                                  FT_STRING, BASE_NONE, NULL, 0x00,
4498                                 "Indicates the Trusted Provisioning Domain.", HFILL
4499                         }
4500                 },
4501                 { &hf_wsp_header_openwave_proxy_home_page,
4502                         {       "x-up-proxy-home-page",
4503                                 "wsp.header.x-up-proxy-home-page",
4504                                  FT_STRING, BASE_NONE, NULL, 0x00,
4505                                 "Specifies the server-assigned home page URL.", HFILL
4506                         }
4507                 },
4508                 { &hf_wsp_header_openwave_devcap_has_color,
4509                         {       "x-up-devcap-has-color",
4510                                 "wsp.header.x-up-devcap-has-color",
4511                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4512                                 "Indicates if the handset supports colour.", HFILL
4513                         }
4514                 },
4515                 { &hf_wsp_header_openwave_devcap_num_softkeys,
4516                         {       "x-up-devcap-num-softkeys",
4517                                 "wsp.header.x-up-devcap-num-softkeys",
4518                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4519                                 "The number of softkeys that can be displayed on the handset.", HFILL
4520                         }
4521                 },
4522                 { &hf_wsp_header_openwave_devcap_softkey_size,
4523                         {       "x-up-devcap-softkey-size",
4524                                 "wsp.header.x-up-devcap-softkey-size",
4525                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4526                                 "The number of chars that can be displayed on a softkey label.", HFILL
4527                         }
4528                 },
4529                 { &hf_wsp_header_openwave_devcap_screen_chars,
4530                         {       "x-up-devcap-screen-chars",
4531                                 "wsp.header.x-up-devcap-screen-chars",
4532                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4533                                 "The height and width of the handset's display in characters.", HFILL
4534                         }
4535                 },
4536                 { &hf_wsp_header_openwave_devcap_screen_pixels,
4537                         {       "x-up-devcap-screen-pixels",
4538                                 "wsp.header.x-up-devcap-screen-pixels",
4539                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4540                                 "The height and width of the handset's display in pixels.", HFILL
4541                         }
4542                 },
4543                 { &hf_wsp_header_openwave_devcap_em_size,
4544                         {       "x-up-devcap-em-size",
4545                                 "wsp.header.x-up-devcap-em-size",
4546                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4547                                 "The height and width of an uppercase M in pixels in a handset.", HFILL
4548                         }
4549                 },
4550                 { &hf_wsp_header_openwave_devcap_screen_depth,
4551                         {       "x-up-devcap-screen-depth",
4552                                 "wsp.header.x-up-devcap-screen-depth",
4553                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4554                                 "The colour/gray depth of the display in bits.", HFILL
4555                         }
4556                 },
4557                 { &hf_wsp_header_openwave_devcap_immed_alert,
4558                         {       "x-up-devcap-immed-alert",
4559                                 "wsp.header.x-up-devcap-immed-alert",
4560                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4561                                 "Indicates if the handset has support for immediate UPNOTIFY alerts.", HFILL
4562                         }
4563                 },
4564                 { &hf_wsp_header_openwave_proxy_net_ask,
4565                         {       "x-up-proxy-net-ask",
4566                                 "wsp.header.x-up-proxy-net-ask",
4567                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4568                                 "Indicates to browser if circuit switched call is allowed without user interaction", HFILL
4569                         }
4570                 },
4571                 { &hf_wsp_header_openwave_proxy_uplink_version,
4572                         {       "x-up-proxy-uplink-version",
4573                                 "wsp.header.x-up-proxy-uplink-version",
4574                                  FT_STRING, BASE_NONE, NULL, 0x00,
4575                                 "Version of the MAG WAP gateway", HFILL
4576                         }
4577                 },
4578                 { &hf_wsp_header_openwave_proxy_tod,
4579                         {       "x-up-proxy-tod",
4580                                 "wsp.header.x-up-proxy-tod",
4581                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4582                                 "Time of day", HFILL
4583                         }
4584                 },
4585                 { &hf_wsp_header_openwave_proxy_ba_enable,
4586                         {       "x-up-proxy-ba-enable",
4587                                 "wsp.header.x-up-proxy-ba-enable",
4588                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4589                                 "Indicates if the WAP gateway should cache basic authentication details on behalf of the handset", HFILL
4590                         }
4591                 },
4592                 { &hf_wsp_header_openwave_proxy_ba_realm,
4593                         {       "x-up-proxy-ba-realm",
4594                                 "wsp.header.x-up-proxy-ba-realm",
4595                                  FT_STRING, BASE_NONE, NULL, 0x00,
4596                                 "Indicates the realm within which basic authentication credentials apply", HFILL
4597                         }
4598                 },
4599                 { &hf_wsp_header_openwave_proxy_redirect_enable,
4600                         {       "x-up-proxy-redirect-enable",
4601                                 "wsp.header.x-up-proxy-redirect-enable",
4602                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4603                                 "Indicates if the handset wants the WAP gateway to handle HTTP redirects on its behalf", HFILL
4604                         }
4605                 },
4606                 { &hf_wsp_header_openwave_proxy_request_uri,
4607                         {       "x-up-proxy-request-uri",
4608                                 "wsp.header.x-up-proxy-request-uri",
4609                                  FT_STRING, BASE_NONE, NULL, 0x00,
4610                                 "Indicates to the handset that the previous request was redirected to the specified URI", HFILL
4611                         }
4612                 },
4613                 { &hf_wsp_header_openwave_proxy_redirect_status,
4614                         {       "x-up-proxy-redirect-status",
4615                                 "wsp.header.x-up-proxy-redirect-status",
4616                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4617                                 "Indicates the status of a redirect performed on behalf of a handset", HFILL
4618                         }
4619                 },
4620                 { &hf_wsp_header_openwave_proxy_trans_charset,
4621                         {       "x-up-proxy-trans-charset",
4622                                 "wsp.header.x-up-proxy-trans-charset",
4623                                  FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
4624                                 "For POSTs indicates the charset encoding of a document", HFILL
4625                         }
4626                 },
4627                 { &hf_wsp_header_openwave_proxy_trans_charset_str,
4628                         {       "x-up-proxy-trans-charset",
4629                                 "wsp.header.x-up-proxy-trans-charset.string",
4630                                  FT_STRING, BASE_NONE, NULL, 0x00,
4631                                 "For POSTs indicates the charset encoding of a document", HFILL
4632                         }
4633                 },
4634                 { &hf_wsp_header_openwave_proxy_linger,
4635                         {       "x-up-proxy-linger",
4636                                 "wsp.header.x-up-proxy-linger",
4637                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4638                                 "Indicates the circuit linger time in seconds", HFILL
4639                         }
4640                 },
4641                 { &hf_wsp_header_openwave_proxy_client_id,
4642                         {       "x-up-proxy-client-id",
4643                                 "wsp.header.x-up-proxy-client-id",
4644                                  FT_BYTES, BASE_DEC, NULL, 0x00,
4645                                 "The ClientId of the handset", HFILL
4646                         }
4647                 },
4648                 { &hf_wsp_header_openwave_proxy_enable_trust,
4649                         {       "x-up-proxy-enable-trust",
4650                                 "wsp.header.x-up-proxy-enable-trust",
4651                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4652                                 "Indicates whether to enable Trusted Provisioning Domain", HFILL
4653                         }
4654                 },
4655                 { &hf_wsp_header_openwave_proxy_trust_old,
4656                         {       "x-up-proxy-trust-old",
4657                                 "wsp.header.x-up-proxy-trust-old",
4658                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4659                                 "Indicates if the content being returned was received from within the Trusted Provisioning Domain", HFILL
4660                         }
4661                 },
4662                 { &hf_wsp_header_openwave_proxy_trust,
4663                         {       "x-up-proxy-trust",
4664                                 "wsp.header.x-up-proxy-trust",
4665                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4666                                 "Indicates if the content being returned was received from within the Trusted Provisioning Domain", HFILL
4667                         }
4668                 },
4669                 { &hf_wsp_header_openwave_proxy_bookmark,
4670                         {       "x-up-proxy-bookmark",
4671                                 "wsp.header.x-up-proxy-bookmark",
4672                                  FT_STRING, BASE_NONE, NULL, 0x00,
4673                                 "Specifies the URL to use for server-side bookmarks", HFILL
4674                         }
4675                 },
4676                 { &hf_wsp_header_openwave_devcap_gui,
4677                         {       "x-up-devcap-gui",
4678                                 "wsp.header.x-up-devcap-gui",
4679                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4680                                 "Indicates if the handset has a GUI", HFILL
4681                         }
4682                 },
4683                 { &hf_wsp_header_bearer_indication,
4684                         /*
4685                          * XXX - I'm assuming that the bearer indication is
4686                          * just a bearer type.
4687                          */
4688                         {       "Bearer-indication",
4689                                 "wsp.header.bearer_indication",
4690                                  FT_UINT32, BASE_HEX, VALS(vals_bearer_types), 0x00,
4691                                 "Bearer-indication", HFILL
4692                         }
4693                 },
4694                 { &hf_wsp_header_cache_control,
4695                         {       "Cache-Control",
4696                                 "wsp.header.cache_control",
4697                                  FT_UINT8, BASE_HEX, VALS ( vals_cache_control ), 0x00,
4698                                 "Cache-Control", HFILL
4699                         }
4700                 },
4701                 { &hf_wsp_header_cache_control_str,
4702                         {       "Cache-Control",
4703                                 "wsp.header.cache_control.string",
4704                                  FT_STRING, BASE_NONE, NULL, 0x00,
4705                                 "Cache-Control", HFILL
4706                         }
4707                 },
4708                 { &hf_wsp_header_cache_control_field_name,
4709                         {       "Field Name",
4710                                 "wsp.header.cache_control.field_name",
4711                                  FT_UINT8, BASE_HEX, VALS ( vals_field_names ), 0x00,
4712                                 "Cache-Control field name", HFILL
4713                         }
4714                 },
4715                 { &hf_wsp_header_cache_control_field_name_str,
4716                         {       "Field Name",
4717                                 "wsp.header.cache_control.field_name.str",
4718                                  FT_STRING, BASE_NONE, NULL, 0x00,
4719                                 "Cache-Control field name", HFILL
4720                         }
4721                 },
4722                 { &hf_wsp_header_connection,
4723                         {       "Connection",
4724                                 "wsp.header.connection",
4725                                  FT_UINT8, BASE_HEX, VALS ( vals_connection ), 0x00,
4726                                 "Connection", HFILL
4727                         }
4728                 },
4729                 { &hf_wsp_header_connection_str,
4730                         {       "Connection",
4731                                 "wsp.header.connection_str",
4732                                  FT_STRING, BASE_NONE, NULL, 0x00,
4733                                 "Connection", HFILL
4734                         }
4735                 },
4736                 { &hf_wsp_header_content_length,
4737                         {       "Content-Length",
4738                                 "wsp.header.content_length",
4739                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4740                                 "Content-Length", HFILL
4741                         }
4742                 },
4743                 { &hf_wsp_header_date,
4744                         {       "Date",
4745                                 "wsp.header.date",
4746                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4747                                 "Date", HFILL
4748                         }
4749                 },
4750                 { &hf_wsp_header_etag,
4751                         {       "Etag",
4752                                 "wsp.header.etag",
4753                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4754                                  FT_STRING, BASE_NONE, NULL, 0x00,
4755                                 "Etag", HFILL
4756                         }
4757                 },
4758                 { &hf_wsp_header_expires,
4759                         {       "Expires",
4760                                 "wsp.header.expires",
4761                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4762                                 "Expires", HFILL
4763                         }
4764                 },
4765                 { &hf_wsp_header_last_modified,
4766                         {       "Last-Modified",
4767                                 "wsp.header.last_modified",
4768                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4769                                 "Last-Modified", HFILL
4770                         }
4771                 },
4772                 { &hf_wsp_header_location,
4773                         {       "Location",
4774                                 "wsp.header.location",
4775                                  FT_STRING, BASE_NONE, NULL, 0x00,
4776                                 "Location", HFILL
4777                         }
4778                 },
4779                 { &hf_wsp_header_if_modified_since,
4780                         {       "If-Modified-Since",
4781                                 "wsp.header.if_modified_since",
4782                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4783                                 "If-Modified-Since", HFILL
4784                         }
4785                 },
4786                 { &hf_wsp_header_pragma,
4787                         {       "Pragma",
4788                                 "wsp.header.pragma",
4789                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4790                                  FT_STRING, BASE_NONE, NULL, 0x00,
4791                                 "pragma", HFILL
4792                         }
4793                 },
4794                 { &hf_wsp_header_authorization,
4795                         {       "Authorization",
4796                                 "wsp.header.authorization",
4797                                  FT_NONE, BASE_NONE, NULL, 0x00,
4798                                 "Authorization", HFILL
4799                         }
4800                 },
4801                 { &hf_wsp_header_authorization_scheme,
4802                         {       "Authentication scheme",
4803                                 "wsp.header.authorization.scheme",
4804                                  FT_STRING, BASE_NONE, NULL, 0x00,
4805                                 "Authorization: Authentication Scheme", HFILL
4806                         }
4807                 },
4808                 { &hf_wsp_header_authorization_user_id,
4809                         {       "User-ID",
4810                                 "wsp.header.authorization.user_id",
4811                                  FT_STRING, BASE_NONE, NULL, 0x00,
4812                                 "Authorization: Basic: User-ID", HFILL
4813                         }
4814                 },
4815                 { &hf_wsp_header_authorization_password,
4816                         {       "Password",
4817                                 "wsp.header.authorization.password",
4818                                  FT_STRING, BASE_NONE, NULL, 0x00,
4819                                 "Authorization: Basic: Password", HFILL
4820                         }
4821                 },
4822                 { &hf_wsp_header_proxy_authorization,
4823                         {       "Proxy-Authorization",
4824                                 "wsp.header.proxy_authorization",
4825                                  FT_NONE, BASE_NONE, NULL, 0x00,
4826                                 "Proxy-Authorization", HFILL
4827                         }
4828                 },
4829                 { &hf_wsp_header_proxy_authorization_scheme,
4830                         {       "Authentication scheme",
4831                                 "wsp.header.proxy_authorization.scheme",
4832                                  FT_STRING, BASE_NONE, NULL, 0x00,
4833                                 "Proxy-Authorization: Authentication Scheme", HFILL
4834                         }
4835                 },
4836                 { &hf_wsp_header_proxy_authorization_user_id,
4837                         {       "User-Id",
4838                                 "wsp.header.proxy_authorization.user_id",
4839                                  FT_STRING, BASE_NONE, NULL, 0x00,
4840                                 "Proxy-Authorization: Basic: User-ID", HFILL
4841                         }
4842                 },
4843                 { &hf_wsp_header_proxy_authorization_password,
4844                         {       "Password",
4845                                 "wsp.header.proxy_authorization.password",
4846                                  FT_STRING, BASE_NONE, NULL, 0x00,
4847                                 "Proxy-Authorization: Basic: Password", HFILL
4848                         }
4849                 },
4850                 { &hf_wsp_header_www_authenticate,
4851                         {       "WWW-Authenticate",
4852                                 "wsp.header.www-authenticate",
4853                                  FT_STRING, BASE_NONE, NULL, 0x00,
4854                                 "Authenticate", HFILL
4855                         }
4856                 },
4857                 { &hf_wsp_header_proxy_authenticate,
4858                         {       "Proxy-Authenticate",
4859                                 "wsp.header.proxy_authenticate",
4860                                  FT_STRING, BASE_NONE, NULL, 0x00,
4861                                 "Proxy-Authenticate", HFILL
4862                         }
4863                 },
4864                 { &hf_wsp_header_profile,
4865                         {       "Profile",
4866                                 "wsp.header.profile",
4867                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4868                                  FT_STRING, BASE_NONE, NULL, 0x00,
4869                                 "Profile", HFILL
4870                         }
4871                 },
4872                 { &hf_wsp_header_server,
4873                         {       "Server",
4874                                 "wsp.header.server",
4875                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4876                                  FT_STRING, BASE_NONE, NULL, 0x00,
4877                                 "Server", HFILL
4878                         }
4879                 },
4880                 { &hf_wsp_header_transfer_encoding,
4881                         {       "Transfer Encoding",
4882                                 "wsp.header.transfer_enc",
4883                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4884                                  FT_UINT8, BASE_HEX, VALS ( vals_transfer_encoding ), 0x00,
4885                                 "Transfer Encoding", HFILL
4886                         }
4887                 },
4888                 { &hf_wsp_header_transfer_encoding_str,
4889                         {       "Transfer Encoding",
4890                                 "wsp.header.transfer_enc_str",
4891                                  FT_STRING, BASE_NONE, NULL, 0x00,
4892                                 "Transfer Encoding", HFILL
4893                         }
4894                 },
4895                 { &hf_wsp_header_user_agent,
4896                         {       "User-Agent",
4897                                 "wsp.header.user_agent",
4898                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4899                                  FT_STRING, BASE_NONE, NULL, 0x00,
4900                                 "User-Agent", HFILL
4901                         }
4902                 },
4903                 { &hf_wsp_header_via,
4904                         {       "Via",
4905                                 "wsp.header.via",
4906                                  FT_STRING, BASE_NONE, NULL, 0x00,
4907                                 "Via", HFILL
4908                         }
4909                 },
4910                 { &hf_wsp_header_wap_application_id,
4911                         {       "X-Wap-Application-Id",
4912                                 "wsp.header.wap_application_id",
4913                                  FT_UINT8, BASE_HEX, NULL, 0x00,
4914                                 "WAP application id", HFILL
4915                         }
4916                 },
4917                 { &hf_wsp_header_wap_application_id_str,
4918                         {       "X-Wap-Application-Id",
4919                                 "wsp.header.wap_application_id.string",
4920                                  FT_STRING, BASE_NONE, NULL, 0x00,
4921                                 "WAP application id", HFILL
4922                         }
4923                 },
4924                 { &hf_wsp_header_warning,
4925                         {       "Warning",
4926                                 "wsp.header.warning",
4927                                  FT_NONE, BASE_NONE, NULL, 0x00,
4928                                 "Warning", HFILL
4929                         }
4930                 },
4931                 { &hf_wsp_header_warning_code,
4932                         {       "Warning Code",
4933                                 "wsp.header.warning.code",
4934                                  FT_UINT8, BASE_DEC, VALS (vals_wsp_warning_code), 0x00,
4935                                 "Warning Code", HFILL
4936                         }
4937                 },
4938                 { &hf_wsp_header_warning_agent,
4939                         {       "Warning Agent",
4940                                 "wsp.header.warning.agent",
4941                                  FT_STRING, BASE_NONE, NULL, 0x00,
4942                                 "Warning Agent", HFILL
4943                         }
4944                 },
4945                 { &hf_wsp_header_warning_text,
4946                         {       "Warning Text",
4947                                 "wsp.header.warning.text",
4948                                  FT_STRING, BASE_NONE, NULL, 0x00,
4949                                 "Warning Text", HFILL
4950                         }
4951                 },
4952                 { &hf_wsp_header_application_header,
4953                         {       "Application Header",
4954                                 "wsp.header.application_header",
4955                                  FT_STRING, BASE_NONE, NULL, 0x00,
4956                                 "Application Header", HFILL
4957                         }
4958                 },
4959                 { &hf_wsp_header_application_value,
4960                         {       "Application Header Value",
4961                                 "wsp.header.application_header.value",
4962                                  FT_STRING, BASE_NONE, NULL, 0x00,
4963                                 "Application Header Value", HFILL
4964                         }
4965                 },
4966                 { &hf_wsp_header_content_ID,
4967                         {       "Content-ID",
4968                                 "wsp.header.content-id",
4969                                  FT_STRING, BASE_NONE, NULL, 0x00,
4970                                 "Content-ID", HFILL
4971                         }
4972                 },
4973                 { &hf_wsp_header_x_wap_tod,
4974                         {       "X-WAP.TOD",
4975                                 "wsp.header.x_wap_tod",
4976                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4977                                 "X-WAP.TOD", HFILL
4978                         }
4979                 },
4980                 { &hf_wsp_capabilities_client_SDU,
4981                         {       "Client SDU",
4982                                 "wsp.capabilities.client_SDU",
4983                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4984                                 "Client SDU", HFILL
4985                         }
4986                 },
4987                 { &hf_wsp_capabilities_server_SDU,
4988                         {       "Server SDU",
4989                                 "wsp.capabilities.server_SDU",
4990                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4991                                 "Server SDU", HFILL
4992                         }
4993                 },
4994                 { &hf_wsp_capabilities_protocol_opt,
4995                         {       "Protocol Options",
4996                                 "wsp.capabilities.protocol_opt",
4997                                  FT_STRING, BASE_HEX, NULL, 0x00,
4998                                 "Protocol Options", HFILL
4999                         }
5000                 },
5001                 { &hf_wsp_capabilities_method_MOR,
5002                         {       "Method MOR",
5003                                 "wsp.capabilities.method_mor",
5004                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5005                                 "Method MOR", HFILL
5006                         }
5007                 },
5008                 { &hf_wsp_capabilities_push_MOR,
5009                         {       "Push MOR",
5010                                 "wsp.capabilities.push_mor",
5011                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5012                                 "Push MOR", HFILL
5013                         }
5014                 },
5015                 { &hf_wsp_capabilities_extended_methods,
5016                         {       "Extended Methods",
5017                                 "wsp.capabilities.extend_methods",
5018                                  FT_STRING, BASE_HEX, NULL, 0x00,
5019                                 "Extended Methods", HFILL
5020                         }
5021                 },
5022                 { &hf_wsp_capabilities_header_code_pages,
5023                         {       "Header Code Pages",
5024                                 "wsp.capabilities.code_pages",
5025                                  FT_STRING, BASE_HEX, NULL, 0x00,
5026                                 "Header Code Pages", HFILL
5027                         }
5028                 },
5029                 { &hf_wsp_capabilities_aliases,
5030                         {       "Aliases",
5031                                 "wsp.capabilities.aliases",
5032                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5033                                 "Aliases", HFILL
5034                         }
5035                 },
5036                 { &hf_wsp_post_data,
5037                         {       "Data (Post)",
5038                                 "wsp.post.data",
5039                                  FT_NONE, BASE_NONE, NULL, 0x00,
5040                                 "Post Data", HFILL
5041                         }
5042                 },
5043                 { &hf_wsp_push_data,
5044                         {       "Push Data",
5045                                 "wsp.push.data",
5046                                  FT_NONE, BASE_NONE, NULL, 0x00,
5047                                 "Push Data", HFILL
5048                         }
5049                 },
5050                 { &hf_wsp_multipart_data,
5051                         {       "Data in this part",
5052                                 "wsp.multipart.data",
5053                                  FT_NONE, BASE_NONE, NULL, 0x00,
5054                                 "The data of 1 MIME-multipart part.", HFILL
5055                         }
5056                 },
5057                 { &hf_wsp_mpart,
5058                         {       "Part",
5059                                 "wsp.multipart",
5060                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5061                                 "MIME part of multipart data.", HFILL
5062                         }
5063                 },
5064                 { &hf_wsp_redirect_flags,
5065                         {       "Flags",
5066                                 "wsp.redirect_flags",
5067                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5068                                 "Redirect Flags", HFILL
5069                         }
5070                 },
5071                 { &hf_wsp_redirect_permanent,
5072                         {       "Permanent Redirect",
5073                                 "wsp.redirect_flags.permanent",
5074                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), PERMANENT_REDIRECT,
5075                                 "Permanent Redirect", HFILL
5076                         }
5077                 },
5078                 { &hf_wsp_redirect_reuse_security_session,
5079                         {       "Reuse Security Session",
5080                                 "wsp.redirect_flags.reuse_security_session",
5081                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), REUSE_SECURITY_SESSION,
5082                                 "Permanent Redirect", HFILL
5083                         }
5084                 },
5085                 { &hf_wsp_redirect_afl,
5086                         {       "Flags/Length",
5087                                 "wsp.redirect_afl",
5088                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5089                                 "Redirect Address Flags/Length", HFILL
5090                         }
5091                 },
5092                 { &hf_wsp_redirect_afl_bearer_type_included,
5093                         {       "Bearer Type Included",
5094                                 "wsp.redirect_afl.bearer_type_included",
5095                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), BEARER_TYPE_INCLUDED,
5096                                 "Redirect Address bearer type included", HFILL
5097                         }
5098                 },
5099                 { &hf_wsp_redirect_afl_port_number_included,
5100                         {       "Port Number Included",
5101                                 "wsp.redirect_afl.port_number_included",
5102                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), PORT_NUMBER_INCLUDED,
5103                                 "Redirect Address port number included", HFILL
5104                         }
5105                 },
5106                 { &hf_wsp_redirect_afl_address_len,
5107                         {       "Address Len",
5108                                 "wsp.redirect_afl.address_len",
5109                                  FT_UINT8, BASE_DEC, NULL, ADDRESS_LEN,
5110                                 "Redirect Address Length", HFILL
5111                         }
5112                 },
5113                 { &hf_wsp_redirect_bearer_type,
5114                         {       "Bearer Type",
5115                                 "wsp.redirect_bearer_type",
5116                                  FT_UINT8, BASE_HEX, VALS(vals_bearer_types), 0x0,
5117                                 "Redirect Bearer Type", HFILL
5118                         }
5119                 },
5120                 { &hf_wsp_redirect_port_num,
5121                         {       "Port Number",
5122                                 "wsp.redirect_port_num",
5123                                  FT_UINT16, BASE_DEC, NULL, 0x0,
5124                                 "Redirect Port Number", HFILL
5125                         }
5126                 },
5127                 { &hf_wsp_redirect_ipv4_addr,
5128                         {       "IP Address",
5129                                 "wsp.redirect_ipv4_addr",
5130                                  FT_IPv4, BASE_NONE, NULL, 0x0,
5131                                 "Redirect Address (IP)", HFILL
5132                         }
5133                 },
5134                 { &hf_wsp_redirect_ipv6_addr,
5135                         {       "IPv6 Address",
5136                                 "wsp.redirect_ipv6_addr",
5137                                  FT_IPv6, BASE_NONE, NULL, 0x0,
5138                                 "Redirect Address (IPv6)", HFILL
5139                         }
5140                 },
5141                 { &hf_wsp_redirect_addr,
5142                         {       "Address",
5143                                 "wsp.redirect_addr",
5144                                  FT_BYTES, BASE_NONE, NULL, 0x0,
5145                                 "Redirect Address", HFILL
5146                         }
5147                 },
5148         };
5149
5150 /* Setup protocol subtree array */
5151         static gint *ett[] = {
5152                 &ett_wsp,
5153                 &ett_content_type_parameters,
5154                 &ett_header,
5155                 &ett_headers,
5156                 &ett_header_warning,
5157                 &ett_header_cache_control_parameters,
5158                 &ett_header_cache_control_field_names,
5159                 &ett_capabilities,
5160                 &ett_post,
5161                 &ett_content_type,
5162                 &ett_redirect_flags,
5163                 &ett_redirect_afl,
5164                 &ett_multiparts,
5165                 &ett_mpartlist,
5166                 &ett_header_credentials,
5167         };
5168
5169 /* Register the protocol name and description */
5170         proto_wsp = proto_register_protocol(
5171                 "Wireless Session Protocol",    /* protocol name for use by ethereal */
5172                 "WSP",                          /* short version of name */
5173                 "wap-wsp"                       /* Abbreviated protocol name, should Match IANA
5174                                                     < URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
5175                                                   */
5176         );
5177
5178 /* Required function calls to register the header fields and subtrees used  */
5179         proto_register_field_array(proto_wsp, hf, array_length(hf));
5180         proto_register_subtree_array(ett, array_length(ett));
5181
5182         register_dissector("wsp-co", dissect_wsp_fromwap_co, proto_wsp);
5183         register_dissector("wsp-cl", dissect_wsp_fromwap_cl, proto_wsp);
5184         wsp_dissector_table = register_dissector_table("wsp.content_type.type",
5185             "WSP content type", FT_UINT8, BASE_HEX);
5186         register_heur_dissector_list("wsp", &heur_subdissector_list);
5187
5188         wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
5189             proto_wsp);
5190 };
5191
5192 void
5193 proto_reg_handoff_wsp(void)
5194 {
5195         /*
5196          * Get a handle for the WBXML dissector.
5197          */
5198         wbxml_handle = find_dissector("wbxml");
5199
5200         /*
5201          * And get a handle for the WTP-over-UDP dissector.
5202          */
5203         wtp_fromudp_handle = find_dissector("wtp-udp");
5204
5205         /* Only connection-less WSP has no previous handler */
5206         dissector_add("udp.port", UDP_PORT_WSP, wsp_fromudp_handle);
5207         dissector_add("udp.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
5208
5209         /* This dissector is also called from the WTP and WTLS dissectors */
5210 }