From Olivier Biot:
[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.67 2003/05/08 08:36:25 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 typedef enum {
981         VALUE_LEN_SUPPLIED,
982         VALUE_IS_TEXT_STRING,
983         VALUE_IN_LEN,
984 } value_type_t;
985
986 static dissector_table_t wsp_dissector_table;
987 static heur_dissector_list_t heur_subdissector_list;
988
989 static void add_uri (proto_tree *, packet_info *, tvbuff_t *, guint, guint);
990 static void add_headers (proto_tree *, tvbuff_t *);
991 static int add_well_known_header (proto_tree *, tvbuff_t *, int, guint8);
992 static int add_unknown_header (proto_tree *, tvbuff_t *, int, guint8);
993 static int add_application_header (proto_tree *, tvbuff_t *, int);
994 static void add_accept_header (proto_tree *, tvbuff_t *, int,
995     tvbuff_t *, value_type_t, int);
996 static void add_accept_xxx_header (proto_tree *, tvbuff_t *, int,
997     tvbuff_t *, value_type_t, int, int, int, const value_string *,
998     const char *);
999 static void add_accept_ranges_header (proto_tree *, tvbuff_t *, int,
1000     tvbuff_t *, value_type_t, int);
1001 static void add_cache_control_header (proto_tree *, tvbuff_t *, int,
1002     tvbuff_t *, value_type_t, int);
1003 static int add_cache_control_field_name (proto_tree *, tvbuff_t *, int, guint);
1004 static void add_connection_header (proto_tree *, tvbuff_t *, int,
1005     tvbuff_t *, value_type_t, int);
1006 static void add_content_type_value (proto_tree *, tvbuff_t *, int, int,
1007     tvbuff_t *, value_type_t, int, int, int, guint *, const char **);
1008 static void add_wap_application_id_header (proto_tree *, tvbuff_t *, int,
1009     tvbuff_t *, value_type_t, int);
1010 static void add_integer_value_header_common (proto_tree *, tvbuff_t *, int,
1011     tvbuff_t *, value_type_t, int, int, guint8, const value_string *);
1012 static void add_integer_value_header (proto_tree *, tvbuff_t *, int,
1013     tvbuff_t *, value_type_t, int, int, guint8);
1014 static void add_string_value_header_common (proto_tree *, tvbuff_t *, int,
1015     tvbuff_t *, value_type_t, int, int, guint8, const value_string *);
1016 static void add_string_value_header (proto_tree *, tvbuff_t *, int,
1017     tvbuff_t *, value_type_t, int, int, guint8);
1018 static void add_quoted_string_value_header (proto_tree *, tvbuff_t *, int,
1019     tvbuff_t *, value_type_t, int, int, guint8);
1020 static void add_date_value_header (proto_tree *, tvbuff_t *, int,
1021     tvbuff_t *, value_type_t, int, int, guint8);
1022 static int add_parameter (proto_tree *, tvbuff_t *, int);
1023 static int add_untyped_parameter (proto_tree *, tvbuff_t *, int, int);
1024 static int add_parameter_charset (proto_tree *, tvbuff_t *, int, int);
1025 static int add_constrained_encoding (proto_tree *, tvbuff_t *, int, int);
1026 static int add_parameter_type (proto_tree *, tvbuff_t *, int, int);
1027 static int add_parameter_text (proto_tree *, tvbuff_t *, int, int, int, const char *);
1028 static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
1029 static void add_multipart_data (proto_tree *, tvbuff_t *);
1030 static void add_pragma_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
1031     value_type_t, int);
1032 static void add_transfer_encoding_header (proto_tree *, tvbuff_t *, int,
1033     tvbuff_t *, value_type_t, int);
1034 static void add_warning_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
1035     value_type_t, int);
1036 static void add_accept_application_header (proto_tree *, tvbuff_t *, int,
1037     tvbuff_t *, value_type_t, int);
1038 static void add_credentials_value_header (proto_tree *tree,
1039                 tvbuff_t *header_buff, int headerLen, tvbuff_t *value_buff,
1040                 value_type_t valueType, int valueLen,
1041                 int hf_main, int hf_scheme, int hf_basic_user_id, int hf_basic_password);
1042 static void add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type);
1043 static void add_capability_vals(tvbuff_t *, gboolean, int, guint, guint, char *, size_t);
1044 static value_type_t get_value_type_len (tvbuff_t *, int, guint *, int *, int *);
1045 static guint get_uintvar (tvbuff_t *, guint, guint);
1046 static gint get_integer (tvbuff_t *, guint, guint, value_type_t, guint *);
1047
1048 static int add_well_known_openwave_header (proto_tree *, tvbuff_t *, int, guint8);
1049 static void add_openwave_integer_value_header (proto_tree *, tvbuff_t *, int,
1050     tvbuff_t *, value_type_t, int, int, guint8);
1051 static void add_openwave_string_value_header (proto_tree *, tvbuff_t *, int,
1052     tvbuff_t *, value_type_t, int, int, guint8);
1053
1054
1055 /* Code to actually dissect the packets */
1056 static void
1057 dissect_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
1058     proto_tree *tree, dissector_handle_t dissector_handle)
1059 {
1060         guint8 flags;
1061         proto_item *ti;
1062         proto_tree *flags_tree;
1063         guint8 bearer_type;
1064         guint8 address_flags_len;
1065         int address_len;
1066         proto_tree *atf_tree;
1067         guint16 port_num;
1068         guint32 address_ipv4;
1069         struct e_in6_addr address_ipv6;
1070         address redir_address;
1071         conversation_t *conv;
1072
1073         flags = tvb_get_guint8 (tvb, offset);
1074         if (tree) {
1075                 ti = proto_tree_add_uint (tree, hf_wsp_redirect_flags,
1076                     tvb, offset, 1, flags);
1077                 flags_tree = proto_item_add_subtree (ti, ett_redirect_flags);
1078                 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_permanent,
1079                     tvb, offset, 1, flags);
1080                 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_reuse_security_session,
1081                     tvb, offset, 1, flags);
1082         }
1083         offset++;
1084         while (tvb_reported_length_remaining (tvb, offset) > 0) {
1085                 address_flags_len = tvb_get_guint8 (tvb, offset);
1086                 if (tree) {
1087                         ti = proto_tree_add_uint (tree, hf_wsp_redirect_afl,
1088                             tvb, offset, 1, address_flags_len);
1089                         atf_tree = proto_item_add_subtree (ti, ett_redirect_afl);
1090                         proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_bearer_type_included,
1091                             tvb, offset, 1, address_flags_len);
1092                         proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_port_number_included,
1093                             tvb, offset, 1, address_flags_len);
1094                         proto_tree_add_uint (atf_tree, hf_wsp_redirect_afl_address_len,
1095                             tvb, offset, 1, address_flags_len);
1096                 }
1097                 offset++;
1098                 if (address_flags_len & BEARER_TYPE_INCLUDED) {
1099                         bearer_type = tvb_get_guint8 (tvb, offset);
1100                         if (tree) {
1101                                 proto_tree_add_uint (tree, hf_wsp_redirect_bearer_type,
1102                                     tvb, offset, 1, bearer_type);
1103                         }
1104                         offset++;
1105                 } else
1106                         bearer_type = 0x00;     /* XXX */
1107                 if (address_flags_len & PORT_NUMBER_INCLUDED) {
1108                         port_num = tvb_get_ntohs (tvb, offset);
1109                         if (tree) {
1110                                 proto_tree_add_uint (tree, hf_wsp_redirect_port_num,
1111                                     tvb, offset, 2, port_num);
1112                         }
1113                         offset += 2;
1114                 } else {
1115                         /*
1116                          * Redirecting to the same server port number as was
1117                          * being used, i.e. the source port number of this
1118                          * redirect.
1119                          */
1120                         port_num = pinfo->srcport;
1121                 }
1122                 address_len = address_flags_len & ADDRESS_LEN;
1123                 if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
1124                         /*
1125                          * We don't have the bearer type in the message,
1126                          * so we don't know the address type.
1127                          * (It's the same bearer type as the original
1128                          * connection.)
1129                          */
1130                         goto unknown_address_type;
1131                 }
1132
1133                 /*
1134                  * We know the bearer type, so we know the address type.
1135                  */
1136                 switch (bearer_type) {
1137
1138                 case BT_IPv4:
1139                 case BT_IS_95_CSD:
1140                 case BT_IS_95_PACKET_DATA:
1141                 case BT_ANSI_136_CSD:
1142                 case BT_ANSI_136_PACKET_DATA:
1143                 case BT_GSM_CSD:
1144                 case BT_GSM_GPRS:
1145                 case BT_GSM_USSD_IPv4:
1146                 case BT_AMPS_CDPD:
1147                 case BT_PDC_CSD:
1148                 case BT_PDC_PACKET_DATA:
1149                 case BT_IDEN_CSD:
1150                 case BT_IDEN_PACKET_DATA:
1151                 case BT_PHS_CSD:
1152                 case BT_TETRA_PACKET_DATA:
1153                         /*
1154                          * IPv4.
1155                          */
1156                         if (address_len != 4) {
1157                                 /*
1158                                  * Say what?
1159                                  */
1160                                 goto unknown_address_type;
1161                         }
1162                         tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
1163                         if (tree) {
1164                                 proto_tree_add_ipv4 (tree,
1165                                     hf_wsp_redirect_ipv4_addr,
1166                                     tvb, offset, 4, address_ipv4);
1167                         }
1168
1169                         /*
1170                          * Create a conversation so that the
1171                          * redirected session will be dissected
1172                          * as WAP.
1173                          */
1174                         redir_address.type = AT_IPv4;
1175                         redir_address.len = 4;
1176                         redir_address.data = (const guint8 *)&address_ipv4;
1177                         conv = find_conversation(&redir_address, &pinfo->dst,
1178                             PT_UDP, port_num, 0, NO_PORT_B);
1179                         if (conv == NULL) {
1180                                 conv = conversation_new(&redir_address,
1181                                     &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
1182                         }
1183                         conversation_set_dissector(conv, dissector_handle);
1184                         break;
1185
1186                 case BT_IPv6:
1187                         /*
1188                          * IPv6.
1189                          */
1190                         if (address_len != 16) {
1191                                 /*
1192                                  * Say what?
1193                                  */
1194                                 goto unknown_address_type;
1195                         }
1196                         tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
1197                         if (tree) {
1198                                 proto_tree_add_ipv6 (tree,
1199                                     hf_wsp_redirect_ipv6_addr,
1200                                     tvb, offset, 16, (guint8 *)&address_ipv6);
1201                         }
1202
1203                         /*
1204                          * Create a conversation so that the
1205                          * redirected session will be dissected
1206                          * as WAP.
1207                          */
1208                         redir_address.type = AT_IPv6;
1209                         redir_address.len = 16;
1210                         redir_address.data = (const guint8 *)&address_ipv4;
1211                         conv = find_conversation(&redir_address, &pinfo->dst,
1212                             PT_UDP, port_num, 0, NO_PORT_B);
1213                         if (conv == NULL) {
1214                                 conv = conversation_new(&redir_address,
1215                                     &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
1216                         }
1217                         conversation_set_dissector(conv, dissector_handle);
1218                         break;
1219
1220                 unknown_address_type:
1221                 default:
1222                         if (address_len != 0) {
1223                                 if (tree) {
1224                                         proto_tree_add_item (tree,
1225                                             hf_wsp_redirect_addr,
1226                                             tvb, offset, address_len,
1227                                             bo_little_endian);
1228                                 }
1229                         }
1230                         break;
1231                 }
1232                 offset += address_len;
1233         }
1234 }
1235
1236 static void
1237 dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1238     dissector_handle_t dissector_handle, gboolean is_connectionless)
1239 {
1240         int offset = 0;
1241
1242         guint8 pdut;
1243         guint count = 0;
1244         guint value = 0;
1245         guint uriLength = 0;
1246         guint uriStart = 0;
1247         guint capabilityLength = 0;
1248         guint capabilityStart = 0;
1249         guint headersLength = 0;
1250         guint headerLength = 0;
1251         guint headerStart = 0;
1252         guint nextOffset = 0;
1253         guint contentTypeStart = 0;
1254         guint contentType = 0;
1255         const char *contentTypeStr;
1256         tvbuff_t *tmp_tvb;
1257
1258 /* Set up structures we will need to add the protocol subtree and manage it */
1259         proto_item *ti;
1260         proto_tree *wsp_tree = NULL;
1261 /*      proto_tree *wsp_header_fixed; */
1262
1263 /* This field shows up as the "Info" column in the display; you should make
1264    it, if possible, summarize what's in the packet, so that a user looking
1265    at the list of packets can tell what type of packet it is. */
1266
1267         /* Connection-less mode has a TID first */
1268         if (is_connectionless)
1269         {
1270                 offset++;
1271         };
1272
1273         /* Find the PDU type */
1274         pdut = tvb_get_guint8 (tvb, offset);
1275
1276         /* Develop the string to put in the Info column */
1277         if (check_col(pinfo->cinfo, COL_INFO))
1278         {
1279                 col_append_fstr(pinfo->cinfo, COL_INFO, "WSP %s",
1280                         val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"));
1281         };
1282
1283 /* In the interest of speed, if "tree" is NULL, don't do any work not
1284    necessary to generate protocol tree items. */
1285         if (tree) {
1286                 ti = proto_tree_add_item(tree, proto_wsp, tvb, 0, -1,
1287                     bo_little_endian);
1288                 wsp_tree = proto_item_add_subtree(ti, ett_wsp);
1289
1290 /* Code to process the packet goes here */
1291 /*
1292                 wsp_header_fixed = proto_item_add_subtree(ti, ett_header );
1293 */
1294
1295                 /* Add common items: only TID and PDU Type */
1296
1297                 /* If this is connectionless, then the TID Field is always first */
1298                 if (is_connectionless)
1299                 {
1300                         ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,tvb,
1301                                 0,1,bo_little_endian);
1302                 }
1303
1304                 ti = proto_tree_add_item(
1305                                 wsp_tree,               /* tree */
1306                                 hf_wsp_header_pdu_type, /* id */
1307                                 tvb,
1308                                 offset,                 /* start of high light */
1309                                 1,                      /* length of high light */
1310                                 bo_little_endian        /* value */
1311                      );
1312         }
1313         offset++;
1314
1315         /* Map extended methods to the main method now the Column info has been written;
1316          * this way we can dissect the extended method PDUs. */
1317         if ((pdut >= 0x50) && (pdut <= 0x5F))
1318                 pdut = GET;
1319         else if ((pdut >= 0x70) && (pdut <= 0x7F))
1320                 pdut = POST;
1321
1322         switch (pdut)
1323         {
1324                 case CONNECT:
1325                 case CONNECTREPLY:
1326                 case RESUME:
1327                         if (tree) {
1328                                 if (pdut == CONNECT)
1329                                 {
1330                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,tvb,offset,1,bo_little_endian);
1331                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,tvb,offset,1,bo_little_endian);
1332                                         offset++;
1333                                 } else {
1334                                         count = 0;      /* Initialise count */
1335                                         value = tvb_get_guintvar (tvb, offset, &count);
1336                                         ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1337                                         offset += count;
1338                                 }
1339                                 capabilityStart = offset;
1340                                 count = 0;      /* Initialise count */
1341                                 capabilityLength = tvb_get_guintvar (tvb, offset, &count);
1342                                 offset += count;
1343                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,tvb,capabilityStart,count,capabilityLength);
1344
1345                                 if (pdut != RESUME)
1346                                 {
1347                                         count = 0;      /* Initialise count */
1348                                         headerLength = tvb_get_guintvar (tvb, offset, &count);
1349                                         ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headerLength);
1350                                         offset += count;
1351                                         capabilityStart = offset;
1352                                         headerStart = capabilityStart + capabilityLength;
1353                                 } else {
1354                                                 /* Resume computes the headerlength by remaining bytes */
1355                                         capabilityStart = offset;
1356                                         headerStart = capabilityStart + capabilityLength;
1357                                         headerLength = tvb_reported_length_remaining (tvb, headerStart);
1358                                 }
1359                                 if (capabilityLength > 0)
1360                                 {
1361                                         tmp_tvb = tvb_new_subset (tvb, offset, capabilityLength, capabilityLength);
1362                                         add_capabilities (wsp_tree, tmp_tvb, pdut);
1363                                         offset += capabilityLength;
1364                                 }
1365
1366                                 if (headerLength > 0)
1367                                 {
1368                                         tmp_tvb = tvb_new_subset (tvb, offset, headerLength, headerLength);
1369                                         add_headers (wsp_tree, tmp_tvb);
1370                                 }
1371                         }
1372
1373                         break;
1374
1375                 case REDIRECT:
1376                         dissect_redirect(tvb, offset, pinfo, wsp_tree,
1377                           dissector_handle);
1378                         break;
1379
1380                 case DISCONNECT:
1381                 case SUSPEND:
1382                         if (tree) {
1383                                 count = 0;      /* Initialise count */
1384                                 value = tvb_get_guintvar (tvb, offset, &count);
1385                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1386                         }
1387                         break;
1388
1389                 case GET:
1390                         count = 0;      /* Initialise count */
1391                                 /* Length of URI and size of URILen field */
1392                         value = tvb_get_guintvar (tvb, offset, &count);
1393                         nextOffset = offset + count;
1394                         add_uri (wsp_tree, pinfo, tvb, offset, nextOffset);
1395                         if (tree) {
1396                                 offset += (value+count); /* VERIFY */
1397                                 tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
1398                                 add_headers (wsp_tree, tmp_tvb);
1399                         }
1400                         break;
1401
1402                 case POST:
1403                         uriStart = offset;
1404                         count = 0;      /* Initialise count */
1405                         uriLength = tvb_get_guintvar (tvb, offset, &count);
1406                         headerStart = uriStart+count;
1407                         count = 0;      /* Initialise count */
1408                         headersLength = tvb_get_guintvar (tvb, headerStart, &count);
1409                         offset = headerStart + count;
1410
1411                         add_uri (wsp_tree, pinfo, tvb, uriStart, offset);
1412                         if (tree) {
1413                                 offset += uriLength;
1414
1415                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,headersLength);
1416
1417                                 if (headersLength == 0)
1418                                         break;
1419
1420                                 contentTypeStart = offset;
1421                                 nextOffset = add_content_type (wsp_tree,
1422                                     tvb, offset, &contentType,
1423                                     &contentTypeStr);
1424
1425                                 /* Add headers subtree that will hold the headers fields */
1426                                 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1427                                 headerLength = headersLength-(nextOffset-contentTypeStart);
1428                                 if (headerLength > 0)
1429                                 {
1430                                         tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1431                                         add_headers (wsp_tree, tmp_tvb);
1432                                 }
1433                                 offset = nextOffset+headerLength;
1434                         }
1435                         /* POST data - First check whether a subdissector exists for the content type */
1436                         if (tvb_reported_length_remaining(tvb, headerStart + count + uriLength + headersLength) > 0)
1437                         {
1438                                 tmp_tvb = tvb_new_subset (tvb, headerStart + count + uriLength + headersLength, -1, -1);
1439                                 /* Try finding a dissector for the content first, then fallback */
1440                                 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1441                                         if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree))
1442                                                 if (tree) /* Only display if needed */
1443                                                         add_post_data (wsp_tree, tmp_tvb, contentType, contentTypeStr);
1444                         }
1445                         break;
1446
1447                 case REPLY:
1448                         count = 0;      /* Initialise count */
1449                         headersLength = tvb_get_guintvar (tvb, offset+1, &count);
1450                         headerStart = offset + count + 1;
1451                         if (tree) {
1452                                 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
1453                                 nextOffset = offset + 1 + count;
1454                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset+1,count,headersLength);
1455
1456                                 if (headersLength == 0)
1457                                         break;
1458
1459                                 contentTypeStart = nextOffset;
1460                                 nextOffset = add_content_type (wsp_tree,
1461                                     tvb, nextOffset, &contentType,
1462                                     &contentTypeStr);
1463
1464                                 /* Add headers subtree that will hold the headers fields */
1465                                 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1466                                 headerLength = headersLength-(nextOffset-contentTypeStart);
1467                                 if (headerLength > 0)
1468                                 {
1469                                         tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1470                                         add_headers (wsp_tree, tmp_tvb);
1471                                 }
1472                                 offset += count+headersLength+1;
1473                         }
1474                         /* REPLY data - First check whether a subdissector exists for the content type */
1475                         if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1476                         {
1477                                 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1478                                 /* Try finding a dissector for the content first, then fallback */
1479                                 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1480                                         if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree))
1481                                                 if (tree) /* Only display if needed */
1482                                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_reply_data,
1483                                                                         tmp_tvb, 0, -1, bo_little_endian);
1484                         }
1485                         break;
1486
1487                 case PUSH:
1488                 case CONFIRMEDPUSH:
1489                         count = 0;      /* Initialise count */
1490                         headersLength = tvb_get_guintvar (tvb, offset, &count);
1491                         headerStart = offset + count;
1492
1493                         if (tree) {
1494                                 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headersLength);
1495
1496                                 if (headersLength == 0)
1497                                         break;
1498
1499                                 offset += count;
1500                                 contentTypeStart = offset;
1501                                 nextOffset = add_content_type (wsp_tree,
1502                                     tvb, offset, &contentType,
1503                                     &contentTypeStr);
1504
1505                                 /* Add headers subtree that will hold the headers fields */
1506                                 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1507                                 headerLength = headersLength-(nextOffset-contentTypeStart);
1508                                 if (headerLength > 0)
1509                                 {
1510                                         tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1511                                         add_headers (wsp_tree, tmp_tvb);
1512                                 }
1513                                 offset += headersLength;
1514                         }
1515                         /* PUSH data - First check whether a subdissector exists for the content type */
1516                         if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1517                         {
1518                                 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1519                                 /* Try finding a dissector for the content first, then fallback */
1520                                 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1521                                         if (!dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree))
1522                                                 if (tree) /* Only display if needed */
1523                                                         ti = proto_tree_add_item (wsp_tree, hf_wsp_push_data,
1524                                                                         tmp_tvb, 0, -1, bo_little_endian);
1525                         }
1526                         break;
1527
1528         }
1529 }
1530
1531 /*
1532  * Called directly from UDP.
1533  * Put "WSP" into the "Protocol" column.
1534  */
1535 static void
1536 dissect_wsp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1537 {
1538         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1539                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSP" );
1540         if (check_col(pinfo->cinfo, COL_INFO))
1541                 col_clear(pinfo->cinfo, COL_INFO);
1542
1543         dissect_wsp_common(tvb, pinfo, tree, wsp_fromudp_handle, TRUE);
1544 }
1545
1546 /*
1547  * Called from a higher-level WAP dissector, in connection-oriented mode.
1548  * Leave the "Protocol" column alone - the dissector calling us should
1549  * have set it.
1550  */
1551 static void
1552 dissect_wsp_fromwap_co(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1553 {
1554         /*
1555          * XXX - what about WTLS->WTP->WSP?
1556          */
1557         dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, FALSE);
1558 }
1559
1560 /*
1561  * Called from a higher-level WAP dissector, in connectionless mode.
1562  * Leave the "Protocol" column alone - the dissector calling us should
1563  * have set it.
1564  */
1565 static void
1566 dissect_wsp_fromwap_cl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1567 {
1568         /*
1569          * XXX - what about WTLS->WSP?
1570          */
1571         if (check_col(pinfo->cinfo, COL_INFO))
1572         {
1573                 col_clear(pinfo->cinfo, COL_INFO);
1574         }
1575         dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, TRUE);
1576 }
1577
1578 static void
1579 add_uri (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint URILenOffset, guint URIOffset)
1580 {
1581         proto_item *ti;
1582
1583         guint count = 0;
1584         guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
1585
1586         if (tree)
1587                 ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,tvb,URILenOffset,count,uriLen);
1588
1589         if (tree)
1590                 ti = proto_tree_add_item (tree, hf_wsp_header_uri,tvb,URIOffset,uriLen,bo_little_endian);
1591         if (check_col(pinfo->cinfo, COL_INFO)) {
1592                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1593                     tvb_format_text (tvb, URIOffset, uriLen));
1594         }
1595 }
1596
1597 static void
1598 add_headers (proto_tree *tree, tvbuff_t *tvb)
1599 {
1600         proto_item *ti;
1601         proto_tree *wsp_headers;
1602         guint offset = 0;
1603         guint headersLen = tvb_reported_length (tvb);
1604         guint headerStart = 0;
1605         guint peek = 0;
1606         guint pageCode = 1;
1607
1608 #ifdef DEBUG
1609         fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, headersLen);
1610 #endif
1611
1612         /* End of buffer */
1613         if (headersLen <= 0)
1614         {
1615                 return;
1616         }
1617
1618 #ifdef DEBUG
1619         fprintf (stderr, "dissect_wsp: Headers to process\n");
1620 #endif
1621
1622         ti = proto_tree_add_item (tree, hf_wsp_headers_section,tvb,offset,headersLen,bo_little_endian);
1623         wsp_headers = proto_item_add_subtree( ti, ett_headers );
1624
1625         /* Parse Headers */
1626
1627         while (offset < headersLen)
1628         {
1629                 /* Loop round each header */
1630                 headerStart = offset;
1631                 peek = tvb_get_guint8 (tvb, headerStart);
1632
1633                 if (peek < 32)          /* Short-cut shift delimiter */
1634                 {
1635                         pageCode = peek;
1636                         proto_tree_add_uint (wsp_headers,
1637                             hf_wsp_header_shift_code, tvb, offset, 1,
1638                             pageCode);
1639                         offset += 1;
1640                         continue;
1641                 }
1642                 else if (peek == 0x7F)  /* Shift delimiter */
1643                 {
1644                         pageCode = tvb_get_guint8(tvb, offset+1);
1645                         proto_tree_add_uint (wsp_headers,
1646                             hf_wsp_header_shift_code, tvb, offset, 2,
1647                             pageCode);
1648                         offset += 2;
1649                         continue;
1650                 }
1651                 else if (peek < 127)
1652                 {
1653 #ifdef DEBUG
1654                         fprintf (stderr, "dissect_wsp: header: application-header start %d (0x%02X)\n", peek, peek);
1655 #endif
1656                         /*
1657                          * Token-text, followed by Application-specific-value.
1658                          */
1659                         offset = add_application_header (wsp_headers, tvb,
1660                             headerStart);
1661                 }
1662                 else if (peek & 0x80)
1663                 {
1664 #ifdef DEBUG
1665                         fprintf (stderr, "dissect_wsp: header: well-known %d (0x%02X)\n", peek, peek);
1666 #endif
1667                         /*
1668                          * Well-known-header; the lower 7 bits of "peek"
1669                          * are the header code.
1670                          */
1671                         switch (pageCode) {
1672                         case 1:
1673                                 offset = add_well_known_header (wsp_headers,
1674                                     tvb, headerStart, peek & 0x7F);
1675                                 break;
1676
1677                         case 2:
1678                         case 16:
1679                                 offset = add_well_known_openwave_header (wsp_headers,
1680                                     tvb, headerStart, peek & 0x7F);
1681                                 break;
1682
1683                         default:
1684                                 offset = add_unknown_header (wsp_headers,
1685                                     tvb, headerStart, peek & 0x7F);
1686                                 break;
1687                         }
1688                 }
1689         }
1690 }
1691
1692 static int
1693 add_well_known_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1694     guint8 headerType)
1695 {
1696         int headerStart;
1697         value_type_t valueType;
1698         int headerLen;
1699         guint valueLen;
1700         int valueStart;
1701         tvbuff_t *header_buff;
1702         tvbuff_t *value_buff;
1703
1704 #ifdef DEBUG
1705         fprintf (stderr, "dissect_wsp: Got header 0x%02x\n", headerType);
1706 #endif
1707         headerStart = offset;
1708
1709         /*
1710          * Skip the Short-Integer header type.
1711          */
1712         offset++;
1713
1714         /*
1715          * Get the value type and length (or, if the type is VALUE_IN_LEN,
1716          * meaning the value is a Short-integer, get the value type
1717          * and the value itself).
1718          */
1719         valueType = get_value_type_len (tvb, offset, &valueLen,
1720             &valueStart, &offset);
1721         headerLen = offset - headerStart;
1722
1723         /*
1724          * Get a tvbuff for the entire header.
1725          * XXX - cut the actual length short so that it doesn't run
1726          * past the actual length of tvb.
1727          */
1728         header_buff = tvb_new_subset (tvb, headerStart, headerLen,
1729             headerLen);
1730
1731         /*
1732          * If the value wasn't in the length, get a tvbuff for the value.
1733          * XXX - can valueLen be 0?
1734          * XXX - cut the actual length short so that it doesn't run
1735          * past the actual length of tvb.
1736          */
1737         if (valueType != VALUE_IN_LEN) {
1738                 value_buff = tvb_new_subset (tvb, valueStart, valueLen,
1739                     valueLen);
1740         } else {
1741                 /*
1742                  * XXX - when the last dissector is tvbuffified,
1743                  * so that NULL is no longer a valid tvb pointer
1744                  * value in "proto_tree_add" calls, just
1745                  * set "value_buff" to NULL.
1746                  *
1747                  * XXX - can we already do that?  I.e., will that
1748                  * cause us always to crash if we mistakenly try
1749                  * to fetch the value of a VALUE_IN_LEN item?
1750                  */
1751                 value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
1752         }
1753
1754         switch (headerType) {
1755
1756         case FN_ACCEPT:                 /* Accept */
1757                 add_accept_header (tree, header_buff, headerLen,
1758                     value_buff, valueType, valueLen);
1759                 break;
1760
1761         case FN_ACCEPT_CHARSET_DEP:     /* Accept-Charset */
1762                 /*
1763                  * XXX - should both encoding versions 1.1 and
1764                  * 1.3 be handled this way?
1765                  */
1766                 add_accept_xxx_header (tree, header_buff, headerLen,
1767                     value_buff, valueType, valueLen,
1768                     hf_wsp_header_accept_charset,
1769                     hf_wsp_header_accept_charset_str,
1770                     vals_character_sets, "Unknown charset (0x%04x)");
1771                 break;
1772
1773         case FN_ACCEPT_LANGUAGE:        /* Accept-Language */
1774                 add_accept_xxx_header (tree, header_buff, headerLen,
1775                     value_buff, valueType, valueLen,
1776                     hf_wsp_header_accept_language,
1777                     hf_wsp_header_accept_language_str,
1778                     vals_languages, "Unknown language (0x%04x)");
1779                 break;
1780
1781         case FN_ACCEPT_RANGES:          /* Accept-Ranges */
1782                 add_accept_ranges_header (tree, header_buff, headerLen,
1783                     value_buff, valueType, valueLen);
1784                 break;
1785
1786         case FN_AGE:                    /* Age */
1787                 add_integer_value_header (tree, header_buff, headerLen,
1788                     value_buff, valueType, valueLen, hf_wsp_header_age,
1789                     headerType);
1790                 break;
1791
1792         case FN_CACHE_CONTROL_DEP:      /* Cache-Control */
1793         case FN_CACHE_CONTROL:
1794         case FN_CACHE_CONTROL14:
1795                 /*
1796                  * XXX - is the only difference in the three different
1797                  * versions (1.1, 1.3, 1.4) really only S_MAXAGE?
1798                  */
1799                 add_cache_control_header (tree, header_buff, headerLen,
1800                     value_buff, valueType, valueLen);
1801                 break;
1802
1803         case FN_CONNECTION:     /* Connection */
1804                 add_connection_header (tree, header_buff, headerLen,
1805                     value_buff, valueType, valueLen);
1806                 break;
1807
1808         case FN_CONTENT_LENGTH:         /* Content-Length */
1809                 add_integer_value_header (tree, header_buff, headerLen,
1810                     value_buff, valueType, valueLen,
1811                     hf_wsp_header_content_length,
1812                     headerType);
1813                 break;
1814
1815         case FN_DATE:                   /* Date */
1816                 add_date_value_header (tree, header_buff, headerLen,
1817                     value_buff, valueType, valueLen,
1818                     hf_wsp_header_date, headerType);
1819                 break;
1820
1821         case FN_ETAG:                   /* Etag */
1822                 add_string_value_header (tree, header_buff, headerLen,
1823                     value_buff, valueType, valueLen,
1824                     hf_wsp_header_etag, headerType);
1825                 break;
1826
1827         case FN_EXPIRES:                /* Expires */
1828                 add_date_value_header (tree, header_buff, headerLen,
1829                     value_buff, valueType, valueLen,
1830                     hf_wsp_header_expires, headerType);
1831                 break;
1832
1833         case FN_IF_MODIFIED_SINCE:      /* If-Modified-Since */
1834                 add_date_value_header (tree, header_buff, headerLen,
1835                     value_buff, valueType, valueLen,
1836                     hf_wsp_header_if_modified_since, headerType);
1837                 break;
1838
1839         case FN_LOCATION:               /* Location */
1840                 add_string_value_header (tree, header_buff, headerLen,
1841                     value_buff, valueType, valueLen,
1842                     hf_wsp_header_location, headerType);
1843                 break;
1844
1845         case FN_LAST_MODIFIED:          /* Last-Modified */
1846                 add_date_value_header (tree, header_buff, headerLen,
1847                     value_buff, valueType, valueLen,
1848                     hf_wsp_header_last_modified, headerType);
1849                 break;
1850
1851         case FN_PRAGMA:                 /* Pragma */
1852                 add_pragma_header (tree, header_buff, headerLen,
1853                     value_buff, valueType, valueLen);
1854                 break;
1855
1856         case FN_SERVER:                 /* Server */
1857                 add_string_value_header (tree, header_buff, headerLen,
1858                     value_buff, valueType, valueLen,
1859                     hf_wsp_header_server, headerType);
1860                 break;
1861
1862         case FN_TRANSFER_ENCODING:      /* Transfer-Encoding */
1863                 add_transfer_encoding_header (tree, header_buff, headerLen,
1864                     value_buff, valueType, valueLen);
1865                 break;
1866
1867         case FN_USER_AGENT:             /* User-Agent */
1868                 add_string_value_header (tree, header_buff, headerLen,
1869                     value_buff, valueType, valueLen,
1870                     hf_wsp_header_user_agent, headerType);
1871                 break;
1872
1873         case FN_VIA:                    /* Via */
1874                 add_string_value_header (tree, header_buff, headerLen,
1875                     value_buff, valueType, valueLen,
1876                     hf_wsp_header_via, headerType);
1877                 break;
1878
1879         case FN_WARNING:                /* Warning */
1880                 add_warning_header (tree, header_buff, headerLen,
1881                     value_buff, valueType, valueLen);
1882                 break;
1883
1884         case FN_ACCEPT_APPLICATION:     /* Accept-Application */
1885                 add_accept_application_header (tree, header_buff, headerLen,
1886                     value_buff, valueType, valueLen);
1887                 break;
1888
1889         case FN_BEARER_INDICATION:      /* Bearer-Indication */
1890                 add_integer_value_header (tree, header_buff, headerLen,
1891                     value_buff, valueType, valueLen,
1892                     hf_wsp_header_bearer_indication, headerType);
1893                 break;
1894
1895         case FN_PROFILE:                /* Profile */
1896                 add_string_value_header (tree, header_buff, headerLen,
1897                     value_buff, valueType, valueLen,
1898                     hf_wsp_header_profile, headerType);
1899                 break;
1900
1901         case FN_X_WAP_APPLICATION_ID:   /* X-Wap-Application-Id */
1902                 add_wap_application_id_header (tree, header_buff, headerLen,
1903                     value_buff, valueType, valueLen);
1904                 break;
1905
1906         case FN_CONTENT_ID:             /* Content-ID   */
1907                 add_quoted_string_value_header (tree, header_buff, headerLen,
1908                     value_buff, valueType, valueLen,
1909                     hf_wsp_header_content_ID, headerType);
1910                 break;
1911         
1912         case FN_AUTHORIZATION: /* Authorization */
1913                 add_credentials_value_header (tree, header_buff, headerLen,
1914                                 value_buff, valueType, valueLen,
1915                                 hf_wsp_header_authorization,
1916                                 hf_wsp_header_authorization_scheme,
1917                                 hf_wsp_header_authorization_user_id,
1918                                 hf_wsp_header_authorization_password);
1919                 break;
1920
1921         case FN_PROXY_AUTHORIZATION: /* Proxy-Authorization */
1922                 add_credentials_value_header (tree, header_buff, headerLen,
1923                                 value_buff, valueType, valueLen,
1924                                 hf_wsp_header_proxy_authorization,
1925                                 hf_wsp_header_proxy_authorization_scheme,
1926                                 hf_wsp_header_proxy_authorization_user_id,
1927                                 hf_wsp_header_proxy_authorization_password);
1928                 break;
1929
1930         case FN_WWW_AUTHENTICATE: /* WWW-Authenticate */
1931         case FN_PROXY_AUTHENTICATE: /* Proxy-Authenticate */
1932
1933
1934         default:
1935                 proto_tree_add_text (tree, header_buff, 0, headerLen,
1936                     "Undecoded Header: %s",
1937                     val_to_str (headerType, vals_field_names, "Unknown (0x%02X)"));
1938                 break;
1939         }
1940         return offset;
1941 }
1942
1943
1944 static int
1945 add_well_known_openwave_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1946     guint8 headerType)
1947 {
1948         int headerStart;
1949         value_type_t valueType;
1950         int headerLen;
1951         guint valueLen;
1952         int valueStart;
1953         tvbuff_t *header_buff;
1954         tvbuff_t *value_buff;
1955
1956 #ifdef DEBUG
1957         fprintf (stderr, "dissect_wsp: Got Openwave header 0x%02x\n", headerType);
1958 #endif
1959         headerStart = offset;
1960
1961         /*
1962          * Skip the Short-Integer header type.
1963          */
1964         offset++;
1965
1966         /*
1967          * Get the value type and length (or, if the type is VALUE_IN_LEN,
1968          * meaning the value is a Short-integer, get the value type
1969          * and the value itself).
1970          */
1971         valueType = get_value_type_len (tvb, offset, &valueLen,
1972             &valueStart, &offset);
1973         headerLen = offset - headerStart;
1974
1975         /*
1976          * Get a tvbuff for the entire header.
1977          * XXX - cut the actual length short so that it doesn't run
1978          * past the actual length of tvb.
1979          */
1980         header_buff = tvb_new_subset (tvb, headerStart, headerLen,
1981             headerLen);
1982
1983         /*
1984          * If the value wasn't in the length, get a tvbuff for the value.
1985          * XXX - can valueLen be 0?
1986          * XXX - cut the actual length short so that it doesn't run
1987          * past the actual length of tvb.
1988          */
1989         if (valueType != VALUE_IN_LEN) {
1990                 value_buff = tvb_new_subset (tvb, valueStart, valueLen,
1991                     valueLen);
1992         } else {
1993                 /*
1994                  * XXX - when the last dissector is tvbuffified,
1995                  * so that NULL is no longer a valid tvb pointer
1996                  * value in "proto_tree_add" calls, just
1997                  * set "value_buff" to NULL.
1998                  *
1999                  * XXX - can we already do that?  I.e., will that
2000                  * cause us always to crash if we mistakenly try
2001                  * to fetch the value of a VALUE_IN_LEN item?
2002                  */
2003                 value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
2004         }
2005
2006         switch (headerType) {
2007
2008 /*      case FN_OPENWAVE_PROXY_PUSH_ADDR:       / x-up-proxy-push-addr */
2009 /*              add_openwave_push_address_header (tree, header_buff, headerLen, */
2010 /*                  value_buff, valueType, valueLen); */
2011 /*              break; */
2012
2013         case FN_OPENWAVE_PROXY_PUSH_ACCEPT:     /* x-up-proxy-push-accept */
2014                 add_accept_header (tree, header_buff, headerLen,
2015                     value_buff, valueType, valueLen);
2016                 break;
2017
2018         case FN_OPENWAVE_PROXY_PUSH_SEQ:        /* x-up-proxy-push-seq */
2019                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2020                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_push_seq,
2021                     headerType);
2022                 break;
2023
2024         case FN_OPENWAVE_PROXY_NOTIFY:          /* x-up-proxy-notify */
2025                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2026                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_notify,
2027                     headerType);
2028                 break;
2029
2030         case FN_OPENWAVE_PROXY_OPERATOR_DOMAIN: /* x-up-proxy-operator-domain */
2031                 add_openwave_string_value_header (tree, header_buff, headerLen,
2032                     value_buff, valueType, valueLen,
2033                     hf_wsp_header_openwave_proxy_operator_domain, headerType);
2034                 break;
2035
2036         case FN_OPENWAVE_PROXY_HOME_PAGE:       /* x-up-proxy-home-page */
2037                 add_openwave_string_value_header (tree, header_buff, headerLen,
2038                     value_buff, valueType, valueLen,
2039                     hf_wsp_header_openwave_proxy_home_page, headerType);
2040                 break;
2041
2042         case FN_OPENWAVE_DEVCAP_HAS_COLOR:      /* x-up-devcap-has-color */
2043                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2044                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_has_color,
2045                     headerType);
2046                 break;
2047
2048         case FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS:   /* x-up-devcap-num-softkeys */
2049                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2050                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_num_softkeys,
2051                     headerType);
2052                 break;
2053
2054         case FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE:   /* x-up-devcap-softkey-size */
2055                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2056                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_softkey_size,
2057                     headerType);
2058                 break;
2059
2060 /*      case FN_OPENWAVE_DEVCAP_SCREEN_CHARS:   / x-up-devcap-screen-chars */
2061 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2062 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_chars, */
2063 /*                  headerType); */
2064 /*              break; */
2065
2066 /*      case FN_OPENWAVE_DEVCAP_SCREEN_PIXELS:  / x-up-devcap-screen-pixels */
2067 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2068 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_pixels, */
2069 /*                  headerType); */
2070 /*              break; */
2071
2072 /*      case FN_OPENWAVE_DEVCAP_EM_SIZE:        / x-up-devcap-em-size */
2073 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2074 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_em_size, */
2075 /*                  headerType); */
2076 /*              break; */
2077
2078         case FN_OPENWAVE_DEVCAP_SCREEN_DEPTH:   /* x-up-devcap-screen-depth */
2079                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2080                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_depth,
2081                     headerType);
2082                 break;
2083
2084         case FN_OPENWAVE_DEVCAP_IMMED_ALERT:    /* x-up-devcap-immed-alert */
2085                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2086                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_immed_alert,
2087                     headerType);
2088                 break;
2089
2090         case FN_OPENWAVE_PROXY_NET_ASK:         /* x-up-proxy-net-ask */
2091                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2092                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_net_ask,
2093                     headerType);
2094                 break;
2095
2096         case FN_OPENWAVE_PROXY_UPLINK_VERSION:          /* x-up-proxy-uplink-version */
2097                 add_openwave_string_value_header (tree, header_buff, headerLen,
2098                     value_buff, valueType, valueLen,
2099                     hf_wsp_header_openwave_proxy_uplink_version, headerType);
2100                 break;
2101
2102         case FN_OPENWAVE_PROXY_TOD:             /* x-up-proxy-tod */
2103                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2104                     value_buff, valueType, valueLen,
2105                     hf_wsp_header_openwave_proxy_tod, headerType);
2106                 break;
2107
2108         case FN_OPENWAVE_PROXY_BA_ENABLE:               /* x-up-proxy-ba-enable */
2109                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2110                     value_buff, valueType, valueLen,
2111                     hf_wsp_header_openwave_proxy_ba_enable, headerType);
2112                 break;
2113
2114         case FN_OPENWAVE_PROXY_BA_REALM:                /* x-up-proxy-ba-realm */
2115                 add_openwave_string_value_header (tree, header_buff, headerLen,
2116                     value_buff, valueType, valueLen,
2117                     hf_wsp_header_openwave_proxy_ba_realm, headerType);
2118                 break;
2119
2120         case FN_OPENWAVE_PROXY_REDIRECT_ENABLE:         /* x-up-proxy-redirect-enable */
2121                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2122                     value_buff, valueType, valueLen,
2123                     hf_wsp_header_openwave_proxy_redirect_enable, headerType);
2124                 break;
2125
2126         case FN_OPENWAVE_PROXY_REQUEST_URI:             /* x-up-proxy-request-uri */
2127                 add_openwave_string_value_header (tree, header_buff, headerLen,
2128                     value_buff, valueType, valueLen,
2129                     hf_wsp_header_openwave_proxy_request_uri, headerType);
2130                 break;
2131
2132 /*      case FN_OPENWAVE_PROXY_REDIRECT_STATUS:         / x-up-proxy-redirect-status */
2133 /*              add_openwave_integer_value_header (tree, header_buff, headerLen, */
2134 /*                  value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_redirect_status, */
2135 /*                  headerType); */
2136 /*              break; */
2137
2138         case FN_OPENWAVE_PROXY_TRANS_CHARSET:           /* x-up-proxy-trans-charset */
2139                 add_accept_xxx_header (tree, header_buff, headerLen,
2140                     value_buff, valueType, valueLen,
2141                     hf_wsp_header_openwave_proxy_trans_charset,
2142                     hf_wsp_header_openwave_proxy_trans_charset_str,
2143                     vals_character_sets, "Unknown charset (%u)");
2144                 break;
2145
2146         case FN_OPENWAVE_PROXY_LINGER:                  /* x-up-proxy-linger */
2147                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2148                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_linger,
2149                     headerType);
2150                 break;
2151
2152 /*      case FN_OPENWAVE_PROXY_CLIENT_ID:               / x-up-proxy-client-id */
2153 /*              add_openwave_string_value_header (tree, header_buff, headerLen, */
2154 /*                  value_buff, valueType, valueLen, */
2155 /*                  hf_wsp_header_openwave_proxy_client_id, headerType); */
2156 /*              break; */
2157
2158         case FN_OPENWAVE_PROXY_ENABLE_TRUST:            /* x-up-proxy-enable-trust */
2159                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2160                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_enable_trust,
2161                     headerType);
2162                 break;
2163
2164         case FN_OPENWAVE_PROXY_TRUST_OLD:               /* x-up-proxy-trust old value */
2165                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2166                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_trust_old,
2167                     headerType);
2168                 break;
2169
2170         case FN_OPENWAVE_PROXY_TRUST:                   /* x-up-proxy-trust */
2171                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2172                     value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_trust,
2173                     headerType);
2174                 break;
2175
2176         case FN_OPENWAVE_PROXY_BOOKMARK:                /* x-up-proxy-bookmark */
2177                 add_openwave_string_value_header (tree, header_buff, headerLen,
2178                     value_buff, valueType, valueLen,
2179                     hf_wsp_header_openwave_proxy_bookmark, headerType);
2180                 break;
2181
2182         case FN_OPENWAVE_DEVCAP_GUI:                    /* x-up-devcap-gui */
2183                 add_openwave_integer_value_header (tree, header_buff, headerLen,
2184                     value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_gui,
2185                     headerType);
2186                 break;
2187
2188         default:
2189                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2190                     "Undecoded Openwave Header: %s",
2191                     val_to_str (headerType, vals_openwave_field_names, "Unknown (0x%02X)"));
2192                 break;
2193         }
2194         return offset;
2195 }
2196
2197 /* *********
2198 static void
2199 add_openwave_push_address_header (proto_tree *tree, tvbuff_t *header_buff,
2200     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2201     int valueLen)
2202 {
2203
2204         ???
2205
2206 }
2207 ********* */
2208
2209 static int
2210 add_unknown_header (proto_tree *tree, tvbuff_t *tvb, int offset,
2211     guint8 headerType)
2212 {
2213         int headerStart;
2214         int valueStart;
2215         value_type_t valueType;
2216         int headerLen;
2217         guint valueLen;
2218         int valueOffset;
2219
2220         headerStart = offset;
2221
2222         /*
2223          * Skip the Short-Integer header type.
2224          */
2225         offset++;
2226
2227         valueStart = offset;
2228
2229         /*
2230          * Get the value type and length (or, if the type is VALUE_IN_LEN,
2231          * meaning the value is a Short-integer, get the value type
2232          * and the value itself).
2233          */
2234         valueType = get_value_type_len (tvb, valueStart, &valueLen,
2235             &valueOffset, &offset);
2236         headerLen = offset - headerStart;
2237
2238         proto_tree_add_text (tree, tvb, headerStart, headerLen,
2239                        "Undecoded Header (0x%02X)", headerType);
2240         return offset;
2241 }
2242
2243 static int
2244 add_application_header (proto_tree *tree, tvbuff_t *tvb, int offset)
2245 {
2246         int startOffset;
2247         guint tokenSize;
2248         const guint8 *token;
2249         value_type_t valueType;
2250         int subvalueLen;
2251         int subvalueOffset;
2252         guint secs;
2253         nstime_t timeValue;
2254         int asvOffset;
2255         guint stringSize;
2256
2257         startOffset = offset;
2258         tokenSize = tvb_strsize (tvb, startOffset);
2259         token = tvb_get_ptr (tvb, startOffset, tokenSize);
2260         offset += tokenSize;
2261
2262         /*
2263          * Special case header "X-WAP.TOD" that is sometimes followed
2264          * by a 4-byte date value.
2265          *
2266          * XXX - according to the 4-May-2000 WSP spec, X-Wap-Tod is
2267          * encoded as a well known header, with a code of 0x3F.
2268          */
2269         if (tokenSize == 10 && strncasecmp ("x-wap.tod", token, 9) == 0)
2270         {
2271                 valueType = get_value_type_len (tvb, offset,
2272                     &subvalueLen, &subvalueOffset, &offset);
2273                 if (get_integer (tvb, subvalueOffset, subvalueLen,
2274                     valueType, &secs) == 0)
2275                 {
2276                         /*
2277                          * Fill in the "struct timeval", and add it to the
2278                          * protocol tree.
2279                          * Note: this will succeed even if it's a Short-integer.
2280                          * A Short-integer would work, but, as the time values
2281                          * are UNIX seconds-since-the-Epoch value, and as
2282                          * there weren't WAP phones or Web servers back in
2283                          * late 1969/early 1970, they're unlikely to be used.
2284                          */
2285                         timeValue.secs = secs;
2286                         timeValue.nsecs = 0;
2287                         proto_tree_add_time (tree, hf_wsp_header_x_wap_tod,
2288                             tvb, startOffset, offset - startOffset, &timeValue);
2289                 }
2290                 else
2291                 {
2292                         proto_tree_add_text (tree, tvb, startOffset,
2293                             offset - startOffset,
2294                             "%s: invalid date value", token);
2295                 }
2296         }
2297         else
2298         {
2299                 asvOffset = offset;
2300                 stringSize = tvb_strsize (tvb, asvOffset);
2301                 offset += stringSize;
2302                 proto_tree_add_text (tree, tvb, startOffset,
2303                     offset - startOffset,
2304                     "%s: %s", token,
2305                     tvb_get_ptr (tvb, asvOffset, stringSize));
2306         }
2307         return offset;
2308 }
2309
2310 static void
2311 add_accept_header (proto_tree *tree, tvbuff_t *header_buff,
2312     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2313     int valueLen)
2314 {
2315         guint contentType;
2316         const char *contentTypeStr;
2317
2318         add_content_type_value (tree, header_buff, 0, headerLen, value_buff,
2319             valueType, valueLen, hf_wsp_header_accept,
2320             hf_wsp_header_accept_str, &contentType, &contentTypeStr);
2321 }
2322
2323 static void
2324 add_accept_xxx_header (proto_tree *tree, tvbuff_t *header_buff,
2325     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2326     int valueLen, int hf_numeric, int hf_string,
2327     const value_string *vals, const char *unknown_tag)
2328 {
2329         int offset = 0;
2330         int subvalueLen;
2331         int subvalueOffset;
2332         guint value = 0;
2333         char valString[100];
2334         const char *valMatch;
2335         guint peek;
2336         double q_value = 1.0;
2337
2338         if (valueType == VALUE_IN_LEN)
2339         {
2340                 /*
2341                  * Constrained-{charset,language} (Short-Integer).
2342                  */
2343                 proto_tree_add_uint (tree, hf_numeric,
2344                     header_buff, 0, headerLen,
2345                     valueLen);  /* valueLen is the value */
2346                 return;
2347         }
2348         if (valueType == VALUE_IS_TEXT_STRING)
2349         {
2350                 /*
2351                  * Constrained-{charset,language} (text, i.e.
2352                  * Extension-Media).
2353                  */
2354                 proto_tree_add_string (tree, hf_string,
2355                     header_buff, 0, headerLen,
2356                     tvb_get_ptr (value_buff, 0, valueLen));
2357                 return;
2358         }
2359
2360         /*
2361          * First byte had the 8th bit set.
2362          */
2363         if (valueLen == 0) {
2364                 /*
2365                  * Any-{charset,language}.
2366                  */
2367                 proto_tree_add_string (tree, hf_string,
2368                         header_buff, 0, headerLen,
2369                         "*");
2370                 return;
2371         }
2372
2373         /*
2374          * Accept-{charset,language}-general-form; Value-length, followed
2375          * by Well-known-{charset,language} or {Token-text,Text-string},
2376          * possibly followed by a Q-value.
2377          *
2378          * Get Value-length.
2379          */
2380         valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2381             &subvalueOffset, &offset);
2382         if (valueType == VALUE_IS_TEXT_STRING)
2383         {
2384                 /*
2385                  * {Token-text,Text-string}.
2386                  */
2387                 valMatch =
2388                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
2389                 proto_tree_add_string (tree, hf_string,
2390                         value_buff, 0, valueLen, valMatch);
2391         } else {
2392                 /*
2393                  * Well-known-{charset,langugage}; starts with an
2394                  * Integer-value.
2395                  */
2396                 if (get_integer (value_buff, subvalueOffset, subvalueLen,
2397                     valueType, &value) < 0)
2398                 {
2399                         valMatch = "Invalid integer";
2400                 }
2401                 else
2402                 {
2403                         valMatch = val_to_str(value, vals, unknown_tag);
2404                 }
2405         }
2406
2407         /* Any remaining data relates to Q-value */
2408         if (offset < valueLen)
2409         {
2410                 peek = tvb_get_guintvar (value_buff, offset, NULL);
2411                 if (peek <= 100) {
2412                         peek = (peek - 1) * 10;
2413                 }
2414                 else {
2415                         peek -= 100;
2416                 }
2417                 q_value = peek/1000.0;
2418         }
2419
2420         /* Build string including Q-value if present */
2421         if (q_value == 1.0)                     /* Default */
2422         {
2423                 snprintf (valString, 100, "%s", valMatch);
2424         }
2425         else
2426         {
2427                 snprintf (valString, 100, "%s; Q=%5.3f", valMatch, q_value);
2428         }
2429         /* Add string to tree */
2430         proto_tree_add_string (tree, hf_string,
2431             header_buff, 0, headerLen, valString);
2432 }
2433
2434 static void
2435 add_accept_ranges_header (proto_tree *tree, tvbuff_t *header_buff,
2436     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2437     int valueLen)
2438 {
2439         if (valueType == VALUE_IN_LEN)
2440         {
2441                 /*
2442                  * Must be 0 (None) or 1 (Bytes) (the 8th bit was stripped
2443                  * off).
2444                  */
2445                 proto_tree_add_uint (tree, hf_wsp_header_accept_ranges,
2446                     header_buff, 0, headerLen,
2447                     valueLen);  /* valueLen is the value */
2448                 return;
2449         }
2450         if (valueType == VALUE_IS_TEXT_STRING)
2451         {
2452                 /*
2453                  * Token-text.
2454                  */
2455                 proto_tree_add_string (tree, hf_wsp_header_accept_ranges_str,
2456                     header_buff, 0, headerLen,
2457                     tvb_get_ptr (value_buff, 0, valueLen));
2458                 return;
2459         }
2460
2461         /*
2462          * Not valid.
2463          */
2464         fprintf(stderr, "dissect_wsp: Accept-Ranges is neither None, Bytes, nor Token-text\n");
2465         return;
2466 }
2467
2468 static void
2469 add_cache_control_header (proto_tree *tree, tvbuff_t *header_buff,
2470     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2471     int valueLen)
2472 {
2473         int offset = 0;
2474         int subvalueLen;
2475         int subvalueOffset;
2476         guint value;
2477         proto_item *ti;
2478         proto_tree *parameter_tree;
2479         proto_tree *field_names_tree;
2480         guint delta_secs;
2481
2482         if (valueType == VALUE_IN_LEN)
2483         {
2484                 /*
2485                  * No-cache, No-store, Max-age, Max-stale, Min-fresh,
2486                  * Only-if-cached, Public, Private, No-transform,
2487                  * Must-revalidate, Proxy-revalidate, or S-maxage.
2488                  */
2489                 proto_tree_add_uint (tree, hf_wsp_header_cache_control,
2490                     header_buff, 0, headerLen,
2491                     valueLen);  /* valueLen is the value */
2492                 return;
2493         }
2494         if (valueType == VALUE_IS_TEXT_STRING)
2495         {
2496                 /*
2497                  * Cache-extension.
2498                  */
2499                 proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
2500                     header_buff, 0, headerLen,
2501                     tvb_get_ptr (value_buff, 0, valueLen));
2502                 return;
2503         }
2504
2505         /*
2506          * Value-length Cache-directive.
2507          * Get first field of Cache-directive.
2508          */
2509         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2510             &subvalueOffset, &offset);
2511         if (valueType == VALUE_IS_TEXT_STRING)
2512         {
2513                 /*
2514                  * Cache-extension Parameter.
2515                  */
2516                 ti = proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
2517                     header_buff, 0, headerLen,
2518                     tvb_get_ptr (value_buff, 0, valueLen));
2519                 parameter_tree = proto_item_add_subtree (ti,
2520                     ett_header_cache_control_parameters);
2521
2522                 /*
2523                  * Process the rest of the value as parameters.
2524                  */
2525                 while (tvb_reported_length_remaining (value_buff, offset) > 0) {
2526                         offset = add_parameter (parameter_tree, value_buff,
2527                             offset);
2528                 }
2529                 return;
2530         }
2531         if (get_integer (value_buff, subvalueOffset, subvalueLen, valueType,
2532             &value) < 0)
2533         {
2534                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2535                     "Invalid Cache-Control Cache-directive value");
2536         }
2537         else
2538         {
2539                 switch (value) {
2540
2541                 case NO_CACHE:
2542                 case PRIVATE:
2543                         /*
2544                          * Loop, processing Field-names.
2545                          */
2546                         ti = proto_tree_add_uint (tree,
2547                             hf_wsp_header_cache_control,
2548                             header_buff, 0, headerLen,
2549                             value);
2550                         field_names_tree = proto_item_add_subtree (ti,
2551                             ett_header_cache_control_field_names);
2552                         while (tvb_reported_length_remaining (value_buff, offset)
2553                             > 0) {
2554                                 offset = add_cache_control_field_name (tree,
2555                                     value_buff, offset, value);
2556                         }
2557                         break;
2558
2559                 case MAX_AGE:
2560                 case MAX_STALE:
2561                 case MIN_FRESH:
2562                 case S_MAXAGE:
2563                         /*
2564                          * Get Delta-second-value.
2565                          */
2566                         valueType = get_value_type_len (value_buff, offset,
2567                             &subvalueLen, &subvalueOffset, &offset);
2568                         if (get_integer (value_buff, subvalueOffset,
2569                             subvalueLen, valueType, &delta_secs) < 0)
2570                         {
2571                                 proto_tree_add_text (tree,
2572                                     header_buff, 0, headerLen,
2573                                     "Invalid Cache-Control %s Delta-second-value",
2574                                     match_strval (value, vals_cache_control));
2575                         }
2576                         else
2577                         {
2578                                 proto_tree_add_uint_format (tree,
2579                                     hf_wsp_header_cache_control,
2580                                     header_buff, 0, headerLen,
2581                                     value,
2582                                     "Cache-Control: %s %u secs",
2583                                     match_strval (value, vals_cache_control),
2584                                     delta_secs);
2585                         }
2586                         break;
2587
2588                 default:
2589                         /*
2590                          * This should not happen, but handle it anyway.
2591                          */
2592                         proto_tree_add_uint (tree,
2593                             hf_wsp_header_cache_control,
2594                             header_buff, 0, headerLen,
2595                             value);
2596                         break;
2597                 }
2598         }
2599 }
2600
2601 static int
2602 add_cache_control_field_name (proto_tree *tree, tvbuff_t *value_buff,
2603     int offset, guint cache_control_value)
2604 {
2605         value_type_t valueType;
2606         int startOffset;
2607         int subvalueLen;
2608         int subvalueOffset;
2609
2610         startOffset = offset;
2611         valueType = get_value_type_len (value_buff, offset,
2612             &subvalueLen, &subvalueOffset, &offset);
2613         if (valueType == VALUE_IS_TEXT_STRING)
2614         {
2615                 /*
2616                  * Token-text.
2617                  */
2618                 proto_tree_add_item (tree,
2619                     hf_wsp_header_cache_control_field_name_str,
2620                     value_buff, startOffset, offset - startOffset,
2621                     bo_little_endian);
2622         }
2623         else if (valueType == VALUE_IN_LEN)
2624         {
2625                 /*
2626                  * Short-integer Field-name.
2627                  */
2628                 proto_tree_add_uint (tree,
2629                     hf_wsp_header_cache_control_field_name,
2630                     value_buff, startOffset, offset - startOffset,
2631                     subvalueLen);
2632         }
2633         else
2634         {
2635                 /*
2636                  * Long-integer - illegal.
2637                  */
2638                 proto_tree_add_text (tree,
2639                     value_buff, startOffset, offset - startOffset,
2640                     "Invalid Cache-Control %s Field-name",
2641                     match_strval (cache_control_value, vals_cache_control));
2642         }
2643         return offset;
2644 }
2645
2646 static void
2647 add_connection_header (proto_tree *tree, tvbuff_t *header_buff,
2648     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2649     int valueLen)
2650 {
2651         int offset = 0;
2652
2653         if (valueType == VALUE_LEN_SUPPLIED)
2654         {
2655                 /*
2656                  * Invalid.
2657                  */
2658                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2659                     "Invalid Connection value");
2660                 return;
2661         }
2662         if (valueType == VALUE_IS_TEXT_STRING)
2663         {
2664                 /*
2665                  * Token-text.
2666                  */
2667                 proto_tree_add_string (tree,
2668                     hf_wsp_header_connection_str,
2669                     header_buff, 0, headerLen,
2670                     tvb_get_ptr (value_buff, 0, valueLen));
2671                 return;
2672         }
2673
2674         /*
2675          * First byte had the 8th bit set.
2676          */
2677         if (valueLen == 0) {
2678                 /*
2679                  * Close.
2680                  */
2681                 proto_tree_add_uint (tree, hf_wsp_header_connection,
2682                     header_buff, offset, headerLen, valueLen);
2683                 return;
2684         }
2685
2686         /*
2687          * Invalid.
2688          */
2689         proto_tree_add_text (tree, header_buff, 0, headerLen,
2690             "Invalid Connection value");
2691 }
2692
2693 static void
2694 add_pragma_header (proto_tree *tree, tvbuff_t *header_buff,
2695     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2696     int valueLen)
2697 {
2698         int offset = 0;
2699         int subvalueLen;
2700         int subvalueOffset;
2701
2702         if (valueType == VALUE_IN_LEN)
2703         {
2704                 /*
2705                  * Invalid.
2706                  */
2707                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2708                     "Invalid Pragma");
2709                 return;
2710         }
2711         if (valueType == VALUE_IS_TEXT_STRING)
2712         {
2713                 /*
2714                  * Invalid?
2715                  */
2716                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2717                     "Invalid Pragma");
2718                 return;
2719         }
2720
2721         /*
2722          * First byte had the 8th bit set.
2723          */
2724         if (valueLen == 0) {
2725                 /*
2726                  * No-cache.
2727                  */
2728                 proto_tree_add_string (tree, hf_wsp_header_pragma,
2729                     header_buff, 0, headerLen, "No-cache");
2730                 return;
2731         }
2732
2733         /*
2734          * Value-length, followed by Parameter.
2735          *
2736          * Get Value-length.
2737          */
2738         valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2739             &subvalueOffset, &offset);
2740         if (valueType == VALUE_IS_TEXT_STRING)
2741         {
2742                 /*
2743                  * Parameter - a text string.
2744                  */
2745                 proto_tree_add_string (tree, hf_wsp_header_pragma,
2746                     header_buff, 0, headerLen,
2747                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
2748         } else {
2749                 /*
2750                  * Parameter - numeric; illegal?
2751                  */
2752                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2753                     "Invalid Pragma");
2754         }
2755 }
2756
2757 static void
2758 add_transfer_encoding_header (proto_tree *tree, tvbuff_t *header_buff,
2759     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2760     int valueLen)
2761 {
2762         int offset = 0;
2763
2764         if (valueType == VALUE_LEN_SUPPLIED)
2765         {
2766                 /*
2767                  * Invalid.
2768                  */
2769                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2770                     "Invalid Transfer-Encoding value");
2771                 return;
2772         }
2773         if (valueType == VALUE_IS_TEXT_STRING)
2774         {
2775                 /*
2776                  * Token-text.
2777                  */
2778                 proto_tree_add_string (tree,
2779                     hf_wsp_header_transfer_encoding_str,
2780                     header_buff, 0, headerLen,
2781                     tvb_get_ptr (value_buff, 0, valueLen));
2782                 return;
2783         }
2784
2785         /*
2786          * First byte had the 8th bit set.
2787          */
2788         if (valueLen == 0) {
2789                 /*
2790                  * Chunked.
2791                  */
2792                 proto_tree_add_uint (tree, hf_wsp_header_transfer_encoding,
2793                     header_buff, offset, headerLen, valueLen);
2794                 return;
2795         }
2796
2797         /*
2798          * Invalid.
2799          */
2800         proto_tree_add_text (tree, header_buff, 0, headerLen,
2801             "Invalid Transfer Encoding value");
2802 }
2803
2804 static void
2805 add_warning_header (proto_tree *tree, tvbuff_t *header_buff,
2806     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2807     int valueLen)
2808 {
2809         int offset = 0;
2810         proto_item *ti;
2811         proto_tree *warning_tree;
2812         int subvalueLen;
2813         int subvalueOffset;
2814         guint8 code;
2815
2816         /*
2817          * Put the items under a header.
2818          * XXX - make the text of the item summarize the elements.
2819          */
2820         ti = proto_tree_add_item (tree, hf_wsp_header_warning,
2821             header_buff, 0, headerLen, bo_little_endian);
2822         warning_tree = proto_item_add_subtree(ti, ett_header_warning);
2823
2824         if (valueType == VALUE_IN_LEN)
2825         {
2826                 /*
2827                  * Warn-code (Short-integer).
2828                  */
2829                 proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2830                     header_buff, 0, headerLen,
2831                     valueLen);  /* valueLen is the value */
2832                 proto_item_append_text (ti, ": %s", match_strval(valueLen, vals_wsp_warning_code));
2833                 return;
2834         }
2835         if (valueType == VALUE_IS_TEXT_STRING)
2836         {
2837                 /*
2838                  * Invalid.
2839                  */
2840                 proto_tree_add_text (warning_tree, header_buff, 0, headerLen,
2841                     "Invalid Warning (all text)");
2842                 return;
2843         }
2844
2845         /*
2846          * Warning-value; Warn-code, followed by Warn-agent, followed by
2847          * Warn-text.
2848          */
2849         /*
2850          * Get Short-integer Warn-code.
2851          */
2852         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2853             &subvalueOffset, &offset);
2854         if (valueType != VALUE_IN_LEN)
2855         {
2856                 /*
2857                  * Not a Short-integer.
2858                  */
2859                 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2860                     subvalueLen, "Invalid Warn-code (not a Short-integer)");
2861                 return;
2862         }
2863         code = subvalueLen;
2864         proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2865             value_buff, subvalueOffset, 1,
2866             subvalueLen);       /* subvalueLen is the value */
2867
2868         /*
2869          * Warn-agent; must be text.
2870          */
2871         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2872             &subvalueOffset, &offset);
2873         if (valueType != VALUE_IS_TEXT_STRING)
2874         {
2875                 /*
2876                  * Not text.
2877                  */
2878                 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2879                     subvalueLen, "Invalid Warn-agent (not a text string)");
2880                 return;
2881         }
2882         proto_tree_add_item (warning_tree,
2883                 hf_wsp_header_warning_agent,
2884                 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2885
2886         /*
2887          * Warn-text; must be text.
2888          */
2889         valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2890             &subvalueOffset, &offset);
2891         if (valueType != VALUE_IS_TEXT_STRING)
2892         {
2893                 /*
2894                  * Not text.
2895                  */
2896                 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2897                     subvalueLen, "Invalid Warn-text (not a text string)");
2898                 return;
2899         }
2900         proto_tree_add_item (warning_tree,
2901                 hf_wsp_header_warning_text,
2902                 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2903         /* Now create the summary warning header */
2904         proto_item_append_text (ti, ": %s %s",
2905                         val_to_str (code, vals_wsp_warning_code_short, "%u"),
2906                         tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
2907 }
2908
2909 static void
2910 add_accept_application_header (proto_tree *tree, tvbuff_t *header_buff,
2911     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2912     int valueLen)
2913 {
2914         guint value;
2915
2916         if (valueType == VALUE_IN_LEN)
2917         {
2918                 /*
2919                  * Application-id-value; numeric, so it's App-assigned-code.
2920                  */
2921                 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2922                     header_buff, 0, headerLen,
2923                     valueLen);  /* valueLen is the value */
2924                 return;
2925         }
2926         if (valueType == VALUE_IS_TEXT_STRING)
2927         {
2928                 /*
2929                  * Uri-value.
2930                  */
2931                 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2932                     header_buff, 0, headerLen,
2933                     tvb_get_ptr (value_buff, 0, valueLen));
2934                 return;
2935         }
2936
2937         /*
2938          * First byte had the 8th bit set.
2939          */
2940         if (valueLen == 0) {
2941                 /*
2942                  * Any-application.
2943                  */
2944                 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2945                         header_buff, 0, headerLen,
2946                         "*");
2947                 return;
2948         }
2949
2950         /*
2951          * Integer-value, hence App-assigned-code.
2952          */
2953         if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
2954         {
2955                 proto_tree_add_text (tree, header_buff, 0, headerLen,
2956                         "Invalid Accept-Application App-assigned-code");
2957         }
2958         else
2959         {
2960                 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2961                     header_buff, 0, headerLen, value);
2962         }
2963 }
2964
2965 static void
2966 add_wap_application_id_header (proto_tree *tree, tvbuff_t *header_buff,
2967     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2968     int valueLen)
2969 {
2970         if (valueType == VALUE_IN_LEN)
2971         {
2972                 /*
2973                  * Must application-id (the 8th bit was stripped off).
2974                  */
2975                 proto_tree_add_uint (tree, hf_wsp_header_wap_application_id,
2976                     header_buff, 0, headerLen,
2977                     valueLen);  /* valueLen is the value */
2978                 return;
2979         }
2980         if (valueType == VALUE_IS_TEXT_STRING)
2981         {
2982                 /*
2983                  * Token-text.
2984                  */
2985                 proto_tree_add_string (tree, hf_wsp_header_wap_application_id_str,
2986                     header_buff, 0, headerLen,
2987                     tvb_get_ptr (value_buff, 0, valueLen));
2988                 return;
2989         }
2990
2991         /*
2992          * Not valid.
2993          */
2994         fprintf(stderr, "dissect_wsp: Suprising format of X-Wap-Application-Id\n");
2995         return;
2996 }
2997
2998 static void
2999 add_credentials_value_header (proto_tree *tree, tvbuff_t *header_buff,
3000                 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3001                 int valueLen _U_ ,
3002                 int hf_main, int hf_scheme,
3003                 int hf_basic_user_id, int hf_basic_password)
3004 {
3005         char *s;
3006         guint32 i, sLen;
3007         proto_item *ti;
3008         proto_tree *basic_tree;
3009
3010         ti = proto_tree_add_item (tree, hf_main, header_buff, 0, headerLen,
3011                         bo_little_endian);
3012         if (valueType == VALUE_LEN_SUPPLIED)
3013         {
3014                 if (tvb_get_guint8 (value_buff, 0) == 0x80)
3015                 { /* Basic */
3016                         basic_tree = proto_item_add_subtree(ti, ett_header_credentials);
3017                         proto_tree_add_string (basic_tree, hf_scheme,
3018                                         value_buff, 0, 1, "Basic" );
3019                         proto_item_append_text (ti, ": Basic");
3020                         /* Now process the Basic Cookie consisting of User-Id and Password */
3021                         i = 1;
3022                         while (tvb_get_guint8(value_buff, i))
3023                                 i++; /* Count length of 1st string */
3024                         /* We reached End of String at offset = i.
3025                          * Get the user id including trailing '\0' (end - start + 1) */
3026                         s = (char *) tvb_get_ptr(value_buff, 1, i - 1 + 1);
3027                         proto_tree_add_string (basic_tree, hf_basic_user_id,
3028                                         value_buff, 1, i - 1 + 1, s );
3029                         proto_item_append_text (ti, "; user-id='%s'", s);
3030                         sLen = ++i; /* Move to 1st byte of password string */
3031
3032                         while (tvb_get_guint8(value_buff, i))
3033                                 i++; /* Count length of 2nd string */
3034                         /* We reached End of String at offset = i.
3035                          * Get the password including trailing '\0' (end - start + 1) */
3036                         s = (char *) tvb_get_ptr(value_buff, sLen, i - sLen + 1);
3037                         proto_tree_add_string (basic_tree, hf_basic_password,
3038                                         value_buff, sLen, i - sLen + 1, s );
3039                         proto_item_append_text (ti, "; password='%s'", s);
3040                 }
3041                 else
3042                 { /* TODO: Authentication-scheme *Auth-param */
3043                         proto_item_append_text (ti, ": (General format not yet decoded)");
3044                 }
3045         }
3046         else
3047         {
3048                 proto_item_append_text (ti, ": (Invalid header value format)");
3049         }
3050         return;
3051 }
3052
3053 static void
3054 add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type)
3055 {
3056         proto_item *ti;
3057         proto_tree *wsp_capabilities;
3058         guint offset = 0;
3059         guint offsetStr = 0;
3060         guint capabilitiesLen = tvb_reported_length (tvb);
3061         guint capabilitiesStart = 0;
3062         guint peek = 0;
3063         guint length = 0;
3064         guint value = 0;
3065         guint i;
3066         int ret;
3067         char valString[200];
3068
3069 #ifdef DEBUG
3070         fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, capabilitiesLen);
3071 #endif
3072
3073         /* End of buffer */
3074         if (capabilitiesLen <= 0)
3075         {
3076                 fprintf (stderr, "dissect_wsp: Capabilities = 0\n");
3077                 return;
3078         }
3079
3080 #ifdef DEBUG
3081         fprintf (stderr, "dissect_wsp: capabilities to process\n");
3082 #endif
3083
3084         ti = proto_tree_add_item (tree, hf_wsp_capabilities_section,tvb,offset,capabilitiesLen,bo_little_endian);
3085         wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
3086
3087         /* Parse Headers */
3088
3089         while (offset < capabilitiesLen)
3090         {
3091                 /* Loop round each header */
3092                 capabilitiesStart = offset;
3093                 length = tvb_get_guint8 (tvb, capabilitiesStart);
3094
3095                 if (length >= 127)              /* length */
3096                 {
3097 #ifdef DEBUG
3098                         fprintf (stderr, "dissect_wsp: capabilities length invalid %d\n",length);
3099 #endif
3100                         offset+=length;
3101                         continue;
3102                 }
3103                 offset++;
3104                 peek = tvb_get_guint8 (tvb, offset);
3105                 offset++;
3106                 switch (peek & 0x7f)
3107                 {
3108                         case 0x00 : /* Client-SDU-Size */
3109                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
3110                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_client_SDU, tvb, capabilitiesStart, length+1, value);
3111                                 break;
3112                         case 0x01 : /* Server-SDU-Size */
3113                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
3114                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_server_SDU, tvb, capabilitiesStart, length+1, value);
3115                                 break;
3116                         case 0x02 : /* Protocol Options */
3117                                 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
3118                                 i = 0;
3119                                 valString[0]=0;
3120                                 if (value & 0x80)
3121                                 {
3122                                         ret = snprintf(valString+i,200-i,"%s","(Confirmed push facility) ");
3123                                         if (ret == -1) {
3124                                                 /*
3125                                                  * Some versions of snprintf
3126                                                  * return -1 if they'd
3127                                                  * truncate the output.
3128                                                  */
3129                                                 goto add_string;
3130                                         }
3131                                         i += ret;
3132                                 }
3133                                 if (value & 0x40)
3134                                 {
3135                                         if (i >= 200) {
3136                                                 /* No more room. */
3137                                                 goto add_string;
3138                                         }
3139                                         ret = snprintf(valString+i,200-i,"%s","(Push facility) ");
3140                                         if (ret == -1) {
3141                                                 /*
3142                                                  * Some versions of snprintf
3143                                                  * return -1 if they'd
3144                                                  * truncate the output.
3145                                                  */
3146                                                 goto add_string;
3147                                         }
3148                                         i += ret;
3149                                 }
3150                                 if (value & 0x20)
3151                                 {
3152                                         if (i >= 200) {
3153                                                 /* No more room. */
3154                                                 goto add_string;
3155                                         }
3156                                         ret = snprintf(valString+i,200-i,"%s","(Session resume facility) ");
3157                                         if (ret == -1) {
3158                                                 /*
3159                                                  * Some versions of snprintf
3160                                                  * return -1 if they'd
3161                                                  * truncate the output.
3162                                                  */
3163                                                 goto add_string;
3164                                         }
3165                                         i += ret;
3166                                 }
3167                                 if (value & 0x10)
3168                                 {
3169                                         if (i >= 200) {
3170                                                 /* No more room. */
3171                                                 goto add_string;
3172                                         }
3173                                         ret = snprintf(valString+i,200-i,"%s","(Acknowledgement headers) ");
3174                                         if (ret == -1) {
3175                                                 /*
3176                                                  * Some versions of snprintf
3177                                                  * return -1 if they'd
3178                                                  * truncate the output.
3179                                                  */
3180                                                 goto add_string;
3181                                         }
3182                                         i += ret;
3183                                 }
3184                         add_string:
3185                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_protocol_opt, tvb, capabilitiesStart, length+1, valString);
3186                                 break;
3187                         case 0x03 : /* Method-MOR */
3188                                 value = tvb_get_guint8(tvb, offset);
3189                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_method_MOR, tvb, capabilitiesStart, length+1, value);
3190                                 break;
3191                         case 0x04 : /* Push-MOR */
3192                                 value = tvb_get_guint8(tvb, offset);
3193                                 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_push_MOR, tvb, capabilitiesStart, length+1, value);
3194                                 break;
3195                                 break;
3196                         case 0x05 : /* Extended Methods */
3197                                 offsetStr = offset;
3198                                 offset++;
3199                                 add_capability_vals(tvb, (type == CONNECT),
3200                                     offsetStr, length, capabilitiesStart,
3201                                     valString, sizeof valString);
3202                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_extended_methods, tvb, capabilitiesStart, length+1, valString);
3203                                 break;
3204                         case 0x06 : /* Header Code Pages */
3205                                 offsetStr = offset;
3206                                 offset++;
3207                                 add_capability_vals(tvb, (type == CONNECT),
3208                                     offsetStr, length, capabilitiesStart,
3209                                     valString, sizeof valString);
3210                                 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_header_code_pages, tvb, capabilitiesStart, length+1, valString);
3211                                 break;
3212                         case 0x07 : /* Aliases */
3213                                 break;
3214                         default:
3215                                 proto_tree_add_text (wsp_capabilities, tvb , capabilitiesStart, length+1,
3216                                        "Undecoded Header (0x%02X)", peek & 0x7F);
3217                                 break;
3218                 }
3219                 offset=capabilitiesStart+length+1;
3220         }
3221 }
3222
3223 static void
3224 add_capability_vals(tvbuff_t *tvb, gboolean add_string, int offsetStr,
3225     guint length, guint capabilitiesStart, char *valString,
3226     size_t valStringSize)
3227 {
3228         guint i;
3229         int ret;
3230         guint value;
3231         guint8 c;
3232
3233         i = 0;
3234         while ((offsetStr-capabilitiesStart) <= length)
3235         {
3236                 value = tvb_get_guint8(tvb, offsetStr);
3237                 if (i >= valStringSize) {
3238                         /* No more room. */
3239                         break;
3240                 }
3241                 if (add_string)
3242                 {
3243                         ret = snprintf(valString+i,valStringSize-i,
3244                             "(0x%02x - ",value);
3245                 }
3246                 else
3247                 {
3248                         ret = snprintf(valString+i,valStringSize-i,"(0x%02x) ",
3249                             value);
3250                 }
3251                 if (ret == -1) {
3252                         /*
3253                          * Some versions of snprintf return -1
3254                          * if they'd truncate the output.
3255                          */
3256                         break;
3257                 }
3258                 i += ret;
3259                 offsetStr++;
3260                 if (add_string)
3261                 {
3262                         for (;(c = tvb_get_guint8(tvb, offsetStr))
3263                             && i < valStringSize - 1; i++,offsetStr++)
3264                                 valString[i] = c;
3265                         offsetStr++;
3266                         if (i < valStringSize - 2) {
3267                                 valString[i++] = ')';
3268                                 valString[i++] = ' ';
3269                         }
3270                 }
3271         }
3272         valString[i] = '\0';
3273 }
3274
3275 static value_type_t
3276 get_value_type_len (tvbuff_t *tvb, int offset, guint *valueLen,
3277     int *valueOffset, int *nextOffset)
3278 {
3279         guint8 peek;
3280         guint32 len;
3281         guint count;
3282
3283         /* Get value part of header */
3284         peek = tvb_get_guint8 (tvb, offset);
3285         if (peek <= 30)
3286         {
3287                 /*
3288                  * The value follows "peek", and is "peek" octets long.
3289                  */
3290 #ifdef DEBUG
3291                 fprintf (stderr, "dissect_wsp: Looking for %d octets\n", peek);
3292 #endif
3293                 len = peek;
3294                 *valueLen = len;        /* Length of value */
3295                 offset++;               /* Skip the length */
3296                 *valueOffset = offset;  /* Offset of value */
3297                 offset += len;          /* Skip the value */
3298                 *nextOffset = offset;   /* Offset after value */
3299                 return VALUE_LEN_SUPPLIED;
3300         }
3301         else if (peek == 31)
3302         {
3303                 /*
3304                  * A uintvar giving the length of the value follows
3305                  * "peek", and the value follows that.
3306                  */
3307 #ifdef DEBUG
3308                 fprintf (stderr, "dissect_wsp: Looking for uintvar octets\n");
3309 #endif
3310                 offset++;               /* Skip the uintvar indicator */
3311                 count = 0;              /* Initialise count */
3312                 len = tvb_get_guintvar (tvb, offset, &count);
3313                 *valueLen = len;        /* Length of value */
3314                 offset += count;        /* Skip the length */
3315                 *valueOffset = offset;  /* Offset of value */
3316                 offset += len;          /* Skip the value */
3317                 *nextOffset = offset;   /* Offset after value */
3318                 return VALUE_LEN_SUPPLIED;
3319         }
3320         else if (peek <= 127)
3321         {
3322                 /*
3323                  * The value is a NUL-terminated string, and "peek"
3324                  * is the first octet of the string.
3325                  */
3326 #ifdef DEBUG
3327                 fprintf (stderr, "dissect_wsp: Looking for NUL-terminated string\n");
3328 #endif
3329                 len = tvb_strsize (tvb, offset);
3330                 *valueLen = len;        /* Length of value */
3331                 *valueOffset = offset;  /* Offset of value */
3332                 offset += len;          /* Skip the value */
3333                 *nextOffset = offset;   /* Offset after value */
3334                 return VALUE_IS_TEXT_STRING;
3335         }
3336         else
3337         {
3338                 /*
3339                  * "peek", with the 8th bit stripped off, is the value.
3340                  */
3341 #ifdef DEBUG
3342                 fprintf (stderr, "dissect_wsp: Value is %d\n", (peek & 0x7F));
3343 #endif
3344                 *valueLen = peek & 0x7F; /* Return the value itself */
3345                 *valueOffset = offset;  /* Offset of value */
3346                 offset++;               /* Skip the value */
3347                 *nextOffset = offset;   /* Offset after value */
3348                 return VALUE_IN_LEN;
3349         }
3350 }
3351
3352 static guint
3353 get_uintvar (tvbuff_t *tvb, guint offset, guint offsetEnd)
3354 {
3355         guint value = 0;
3356         guint octet;
3357
3358         do
3359         {
3360                 octet = tvb_get_guint8 (tvb, offset);
3361                 offset++;
3362                 value <<= 7;
3363                 value += octet & 0x7f;
3364         }
3365         while ((offsetEnd > offset) && (octet & 0x80));
3366         return value;
3367 }
3368
3369 static void
3370 add_content_type_value (proto_tree *tree, tvbuff_t *header_buff,
3371     int headerOffset, int headerLen, tvbuff_t *value_buff,
3372     value_type_t valueType, int valueLen, int hf_numeric, int hf_string,
3373     guint *contentTypep, const char **contentTypeStrp)
3374 {
3375         proto_item *ti;
3376         proto_tree *parameter_tree;
3377         const char *contentTypeStr;
3378         int offset;
3379         int subvalueLen;
3380         int subvalueOffset;
3381         guint value;
3382
3383         if (valueType == VALUE_IN_LEN)
3384         {
3385                 /*
3386                  * Constrained-media (Short-Integer).
3387                  */
3388                 proto_tree_add_uint (tree, hf_numeric,
3389                     header_buff, headerOffset, headerLen,
3390                     valueLen);  /* valueLen is the value */
3391
3392                 /*
3393                  * Return the numerical value, and a null string value
3394                  * indicating that the value is numerical.
3395                  */
3396                 *contentTypep = valueLen;
3397                 *contentTypeStrp = NULL;
3398                 return;
3399         }
3400         if (valueType == VALUE_IS_TEXT_STRING)
3401         {
3402                 /*
3403                  * Constrained-media (text, i.e. Extension-Media).
3404                  */
3405                 contentTypeStr = tvb_get_ptr (value_buff, 0, valueLen);
3406                 proto_tree_add_string (tree, hf_string,
3407                     header_buff, headerOffset, headerLen,
3408                     contentTypeStr);
3409
3410                 /*
3411                  * Return the string value, and set the numerical value
3412                  * to 0 (as it shouldn't be used).
3413                  */
3414                 *contentTypep = 0;
3415                 *contentTypeStrp = contentTypeStr;
3416                 return;
3417         }
3418
3419         /*
3420          * Content-general-form; Value-length, followed by Media-range,
3421          * followed by optional Accept-parameters.
3422          *
3423          * Get Value-length.
3424          */
3425         valueType = get_value_type_len (value_buff, 0, &subvalueLen,
3426             &subvalueOffset, &offset);
3427         if (valueType == VALUE_IS_TEXT_STRING)
3428         {
3429                 /*
3430                  * Extension-Media; value is a string.
3431                  */
3432                 contentTypeStr =
3433                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
3434                 ti = proto_tree_add_string (tree, hf_string, header_buff,
3435                     headerOffset, headerLen, contentTypeStr);
3436
3437                 /*
3438                  * Return the string value, and set the numerical value
3439                  * to 0 (as it shouldn't be used).
3440                  */
3441                 *contentTypep = 0;
3442                 *contentTypeStrp = contentTypeStr;
3443         }
3444         else
3445         {
3446                 /*
3447                  * Well-known-media; value is an Integer.
3448                  */
3449                 if (get_integer (value_buff, subvalueOffset, subvalueLen,
3450                     valueType, &value) < 0)
3451                 {
3452                         proto_tree_add_text (tree, header_buff,
3453                             headerOffset, headerLen,
3454                             "Invalid integer for Well-known-media");
3455
3456                         /*
3457                          * Content type is invalid.
3458                          * Don't try to parse the rest of the value.
3459                          */
3460                         *contentTypep = 0;
3461                         *contentTypeStrp = NULL;
3462                         return;
3463                 }
3464                 ti = proto_tree_add_uint (tree, hf_numeric,
3465                     header_buff, headerOffset, headerLen, value);
3466
3467                 /*
3468                  * Return the numerical value, and a null string value
3469                  * indicating that the value is numerical.
3470                  */
3471                 *contentTypep = value;
3472                 *contentTypeStrp = NULL;
3473         }
3474
3475         /*
3476          * Process the rest of the value as parameters.
3477          */
3478         parameter_tree = proto_item_add_subtree(ti,
3479             ett_content_type_parameters);
3480         while (tvb_reported_length_remaining (value_buff, offset) > 0)
3481                 offset = add_parameter (parameter_tree, value_buff, offset);
3482 }
3483
3484 guint
3485 add_content_type (proto_tree *tree, tvbuff_t *tvb, guint offset,
3486     guint *contentTypep, const char **contentTypeStrp)
3487 {
3488         int valueStart;
3489         value_type_t valueType;
3490         int valueTypeLen;
3491         guint valueLen;
3492         int valueOffset;
3493         tvbuff_t *value_buff;
3494
3495         valueStart = offset;
3496
3497         /*
3498          * Get the value type and length (or, if the type is VALUE_IN_LEN,
3499          * meaning the value is a Short-integer, get the value type
3500          * and the value itself).
3501          */
3502         valueType = get_value_type_len (tvb, valueStart, &valueLen,
3503             &valueOffset, &offset);
3504         valueTypeLen = offset - valueStart;
3505
3506         /*
3507          * Get a tvbuff for the value.
3508          * XXX - can valueLen be 0?
3509          * XXX - cut the actual length short so that it doesn't run
3510          * past the actual length of tvb.
3511          */
3512         if (valueType != VALUE_IN_LEN) {
3513                 value_buff = tvb_new_subset (tvb, valueOffset, valueLen,
3514                     valueLen);
3515         } else {
3516                 /*
3517                  * XXX - when the last dissector is tvbuffified,
3518                  * so that NULL is no longer a valid tvb pointer
3519                  * value in "proto_tree_add" calls, just
3520                  * set "value_buff" to NULL.
3521                  *
3522                  * XXX - can we already do that?  I.e., will that
3523                  * cause us always to crash if we mistakenly try
3524                  * to fetch the value of a VALUE_IN_LEN item?
3525                  */
3526                 value_buff = tvb_new_subset (tvb, valueStart, 0, 0);
3527         }
3528
3529         add_content_type_value (tree, tvb, valueStart, valueTypeLen, value_buff,
3530             valueType, valueLen, hf_wsp_content_type,
3531             hf_wsp_content_type_str, contentTypep, contentTypeStrp);
3532
3533         return offset;
3534 }
3535
3536 static void
3537 add_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
3538     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3539     int valueLen, int hf_numeric, guint8 headerType)
3540 {
3541         add_integer_value_header_common (tree, header_buff, headerLen,
3542             value_buff, valueType, valueLen, hf_numeric, headerType,
3543             vals_field_names);
3544 }
3545
3546 static void
3547 add_openwave_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
3548     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3549     int valueLen, int hf_numeric, guint8 headerType)
3550 {
3551         add_integer_value_header_common (tree, header_buff, headerLen,
3552             value_buff, valueType, valueLen, hf_numeric, headerType,
3553             vals_openwave_field_names);
3554 }
3555
3556 static void
3557 add_integer_value_header_common (proto_tree *tree, tvbuff_t *header_buff,
3558     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3559     int valueLen, int hf_numeric, guint8 headerType,
3560     const value_string *vals)
3561 {
3562         guint value;
3563
3564         if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
3565         {
3566                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3567                     "Invalid %s integer value",
3568                     match_strval (headerType, vals));
3569         }
3570         else
3571         {
3572                 proto_tree_add_uint (tree, hf_numeric,
3573                     header_buff, 0, headerLen, value);
3574         }
3575 }
3576
3577 static void
3578 add_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
3579     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3580     int valueLen, int hf_string, guint8 headerType)
3581 {
3582         add_string_value_header_common (tree, header_buff, headerLen,
3583             value_buff, valueType, valueLen, hf_string, headerType,
3584             vals_field_names);
3585 }
3586
3587 static void
3588 add_openwave_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
3589     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3590     int valueLen, int hf_string, guint8 headerType)
3591 {
3592         add_string_value_header_common (tree, header_buff, headerLen,
3593             value_buff, valueType, valueLen, hf_string, headerType,
3594             vals_openwave_field_names);
3595 }
3596
3597 static void
3598 add_string_value_header_common (proto_tree *tree, tvbuff_t *header_buff,
3599     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3600     int valueLen, int hf_string, guint8 headerType,
3601     const value_string *vals)
3602 {
3603         if (valueType != VALUE_IS_TEXT_STRING)
3604         {
3605                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3606                     "Invalid %s string value",
3607                     match_strval (headerType, vals));
3608         }
3609         else
3610         {
3611                 proto_tree_add_string (tree, hf_string, header_buff,
3612                         0, headerLen, tvb_get_ptr (value_buff, 0, valueLen));
3613         }
3614 }
3615
3616 static void
3617 add_quoted_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
3618     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3619     int valueLen, int hf_string, guint8 headerType)
3620 {
3621         if (valueType != VALUE_IS_TEXT_STRING)
3622         {
3623                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3624                     "Invalid %s quoted string value",
3625                     match_strval (headerType, vals_field_names));
3626         }
3627         else
3628         {
3629                 proto_tree_add_string (tree, hf_string, header_buff,
3630                         0, headerLen, tvb_get_ptr (value_buff, 1, valueLen - 1));
3631         }
3632 }
3633
3634 /* Utility function to add a date value to the protocol tree */
3635 static void
3636 add_date_value_header (proto_tree *tree, tvbuff_t *header_buff,
3637     int headerLen, tvbuff_t *value_buff, value_type_t valueType,
3638     int valueLen, int hf_time, guint8 headerType)
3639 {
3640         guint secs;
3641         nstime_t timeValue;
3642
3643         /* Attempt to get the date value from the buffer */
3644         if (get_integer (value_buff, 0, valueLen, valueType, &secs) == 0)
3645         {
3646                 /*
3647                  * Fill in the "struct timeval", and add it to the
3648                  * protocol tree.
3649                  * Note: this will succeed even if it's a Short-integer.
3650                  * A Short-integer would work, but, as the time values
3651                  * are UNIX seconds-since-the-Epoch value, and as
3652                  * there weren't WAP phones or Web servers back in
3653                  * late 1969/early 1970, they're unlikely to be used.
3654                  */
3655                 timeValue.secs = secs;
3656                 timeValue.nsecs = 0;
3657                 proto_tree_add_time (tree, hf_time, header_buff, 0,
3658                         headerLen, &timeValue);
3659         }
3660         else
3661         {
3662                 proto_tree_add_text (tree, header_buff, 0, headerLen,
3663                     "Invalid %s date value",
3664                     match_strval (headerType, vals_field_names));
3665         }
3666 }
3667
3668 static int
3669 add_parameter (proto_tree *tree, tvbuff_t *value_buff, int offset)
3670 {
3671         int startOffset;
3672         value_type_t valueType;
3673         int subvalueLen;
3674         int subvalueOffset;
3675         guint value;
3676
3677         startOffset = offset;
3678         valueType = get_value_type_len (value_buff, offset,
3679             &subvalueLen, &subvalueOffset, &offset);
3680         if (valueType == VALUE_IS_TEXT_STRING)
3681         {
3682                 /*
3683                  * Untyped-parameter.
3684                  */
3685                 offset = add_untyped_parameter (tree, value_buff, startOffset, offset);
3686                 return offset;
3687         }
3688
3689         /*
3690          * Well-known-parameter-token.
3691          */
3692         if (get_integer (value_buff, subvalueOffset,
3693             subvalueLen, valueType, &value) < 0)
3694         {
3695                 proto_tree_add_text (tree, value_buff, startOffset,
3696                     offset - startOffset,
3697                     "Invalid Well-known-parameter-token");
3698                 return offset;
3699         }
3700
3701         switch (value) {
3702
3703                 case 0x01:      /* WSP 1.1 encoding - Charset: Well-known-charset */
3704                         offset = add_parameter_charset (tree, value_buff, startOffset, offset);
3705                         break;
3706
3707                 case 0x03:      /* WSP 1.1 encoding - Type: Integer-value */
3708                         offset = add_parameter_type (tree, value_buff, startOffset, offset);
3709                         break;
3710
3711                 case 0x05:      /* WSP 1.1 encoding - Name: Text-string */
3712                 case 0x17:      /* WSP 1.4 encoding - Name: Text-value */
3713                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3714                                             hf_wsp_parameter_name, "Name");
3715                         break;
3716
3717                 case 0x06:      /* WSP 1.1 encoding - Filename: Text-string */
3718                 case 0x18:      /* WSP 1.4 encoding - Filename: Text-value */
3719                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3720                                             hf_wsp_parameter_filename, "Filename");
3721                         break;
3722
3723                 case 0x09:      /* WSP 1.2 encoding - Type (special): Constrained-encoding */
3724                         offset = add_constrained_encoding(tree, value_buff, startOffset, offset);
3725                         break;
3726
3727                 case 0x0A:      /* WSP 1.2 encoding - Start: Text-string */
3728                 case 0x19:      /* WSP 1.4 encoding - Start (with multipart/related): Text-value */
3729                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3730                                             hf_wsp_parameter_start, "Start");
3731                         break;
3732
3733                 case 0x0B:      /* WSP 1.2 encoding - Start-info: Text-string */
3734                 case 0x1A:      /* WSP 1.4 encoding - Start-info (with multipart/related): Text-value */
3735                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3736                                             hf_wsp_parameter_start_info, "Start-info");
3737                         break;
3738
3739                 case 0x0C:      /* WSP 1.3 encoding - Comment: Text-string */
3740                 case 0x1B:      /* WSP 1.4 encoding - Comment: Text-value */
3741                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3742                                             hf_wsp_parameter_comment, "Comment");
3743                         break;
3744
3745                 case 0x0D:      /* WSP 1.3 encoding - Domain: Text-string */
3746                 case 0x1C:      /* WSP 1.4 encoding - Domain: Text-value */
3747                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3748                                             hf_wsp_parameter_domain, "Domain");
3749                         break;
3750
3751                 case 0x0F:      /* WSP 1.3 encoding - Path: Text-string */
3752                 case 0x1D:      /* WSP 1.4 encoding - Path: Text-value */
3753                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3754                                             hf_wsp_parameter_path, "Path");
3755                         break;
3756
3757                 case 0x11:      /* WSP 1.4 encoding - SEC: Short-integer (OCTET) */
3758                         proto_tree_add_uint (tree, hf_wsp_parameter_sec, value_buff, startOffset, 2,
3759                                         tvb_get_guint8 (value_buff, startOffset+1) & 0x7F);
3760                         offset++;
3761                         break;
3762                 
3763                 case 0x12:      /* WSP 1.4 encoding - MAC: Text-value */
3764                         offset = add_parameter_text (tree, value_buff, startOffset, offset,
3765                                             hf_wsp_parameter_mac, "MAC");
3766                         break;
3767                 
3768                 case 0x00:      /* WSP 1.1 encoding - Q: Q-value */
3769                 case 0x02:      /* WSP 1.1 encoding - Level: Version-value */
3770                 case 0x07:      /* WSP 1.1 encoding - Differences: Field-name */
3771                 case 0x08:      /* WSP 1.1 encoding - Padding: Short-integer */
3772                 case 0x0E:      /* WSP 1.3 encoding - Max-Age: Delta-seconds-value */
3773                 case 0x10:      /* WSP 1.3 encoding - Secure: No-value */
3774                 case 0x13:      /* WSP 1.4 encoding - Creation-date: Date-value */
3775                 case 0x14:      /* WSP 1.4 encoding - Modification-date: Date-value */
3776                 case 0x15:      /* WSP 1.4 encoding - Read-date: Date-value */
3777                 case 0x16:      /* WSP 1.4 encoding - Size: Integer-value */
3778                 default:
3779                         break;
3780         }
3781
3782         return offset;
3783 }
3784
3785 static int
3786 add_untyped_parameter (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3787     int offset)
3788 {
3789         const guint8 *token;
3790         value_type_t valueType;
3791         int subvalueLen;
3792         int subvalueOffset;
3793         guint value;
3794         int vOffset = offset;
3795
3796         token = tvb_get_ptr (value_buff, startOffset, offset - startOffset);
3797         /*
3798          * Now an Untyped-value; either an Integer-value or a Text-value.
3799          */
3800         valueType = get_value_type_len (value_buff, offset,
3801             &subvalueLen, &subvalueOffset, &offset);
3802         if (valueType == VALUE_IS_TEXT_STRING)
3803         {
3804                 /*
3805                  * Text-value.
3806                  */
3807                 if ((offset - vOffset) == 1) {
3808                         /*
3809                          * No-value.  (stringSize includes the terminating
3810                          * null byte, so an empty string has a size of 1.)
3811                          */
3812                         proto_tree_add_text (tree, value_buff, startOffset,
3813                             offset - startOffset,
3814                             "%s", token);
3815                         return offset;
3816                 }
3817                 proto_tree_add_text (tree, value_buff, startOffset,
3818                     offset - startOffset,
3819                     "%s: %s", token,
3820                     tvb_get_ptr (value_buff, vOffset, offset - vOffset));
3821         }
3822         else
3823         {
3824                 /*
3825                  * Integer-value.
3826                  */
3827                 if (get_integer (value_buff, subvalueOffset, subvalueLen,
3828                     valueType, &value) == 0)
3829                 {
3830                         proto_tree_add_text (tree, value_buff, startOffset,
3831                             offset - startOffset,
3832                             "%s: %u", token, value);
3833                 }
3834                 else
3835                 {
3836                         proto_tree_add_text (tree, value_buff, startOffset,
3837                             offset - startOffset,
3838                             "%s: Invalid Integer-value", token);
3839                 }
3840         }
3841         return offset;
3842 }
3843
3844 static int
3845 add_parameter_charset (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3846     int offset)
3847 {
3848         value_type_t valueType;
3849         int subvalueLen;
3850         int subvalueOffset;
3851         guint value;
3852
3853         valueType = get_value_type_len (value_buff, offset,
3854             &subvalueLen, &subvalueOffset, &offset);
3855         if (valueType == VALUE_IN_LEN)
3856         {
3857                 /*
3858                  * Integer-value.
3859                  */
3860                 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3861                     value_buff, startOffset, offset - startOffset,
3862                     subvalueLen);       /* subvalueLen is the value */
3863                 return offset;
3864         }
3865         if (valueType == VALUE_IS_TEXT_STRING)
3866         {
3867                 /*
3868                  * Invalid.
3869                  */
3870                 proto_tree_add_text (tree, value_buff, startOffset,
3871                     offset - startOffset, "Invalid Well-known charset");
3872                 return offset;
3873         }
3874
3875         /*
3876          * First byte had the 8th bit set.
3877          */
3878         if (subvalueLen == 0) {
3879                 /*
3880                  * Any-charset.
3881                  * XXX - add this as a field?
3882                  */
3883                 proto_tree_add_text (tree, value_buff, startOffset,
3884                     offset- startOffset, "*");
3885                 return offset;
3886         }
3887
3888         if (get_integer(value_buff, subvalueOffset, subvalueLen,
3889             valueType, &value) == -1) {
3890                 proto_tree_add_text (tree, value_buff, startOffset,
3891                     offset - startOffset, "Length %u not handled in Well-known charset",
3892                         subvalueLen);
3893         } else {
3894                 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3895                     value_buff, startOffset, offset - startOffset, value);
3896         }
3897         return offset;
3898 }
3899
3900 static int
3901 add_constrained_encoding (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3902     int offset)
3903 {
3904         value_type_t valueType;
3905         int subvalueLen;
3906         int subvalueOffset;
3907         guint value;
3908
3909         valueType = get_value_type_len (value_buff, offset,
3910             &subvalueLen, &subvalueOffset, &offset);
3911         if (valueType == VALUE_IN_LEN)
3912         {
3913                 /*
3914                  * Integer-value, invalid
3915                  */
3916                 proto_tree_add_text (tree, value_buff, startOffset,
3917                     offset - startOffset, "Invalid multipart type parameter");
3918                 return offset;
3919         }
3920         if (valueType == VALUE_IS_TEXT_STRING)
3921         {
3922                 /*
3923                  * type-label.
3924                  */
3925                 proto_tree_add_string (tree, hf_wsp_parameter_upart_type,
3926                     value_buff, startOffset, offset - startOffset,
3927                     tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
3928                 return offset;
3929         }
3930         /*
3931          * First byte had the 8th bit set.
3932          */
3933         get_integer(value_buff, subvalueOffset, subvalueLen, valueType, &value);
3934         proto_tree_add_uint (tree, hf_wsp_parameter_upart_type_value,
3935             value_buff, startOffset, offset - startOffset, value);
3936         return offset;
3937 }
3938
3939 static int
3940 add_parameter_type (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3941     int offset)
3942 {
3943         value_type_t valueType;
3944         int subvalueLen;
3945         int subvalueOffset;
3946         guint value;
3947
3948         valueType = get_value_type_len (value_buff, offset,
3949             &subvalueLen, &subvalueOffset, &offset);
3950         if (get_integer(value_buff, subvalueOffset, subvalueLen,
3951             valueType, &value) == -1) {
3952                 proto_tree_add_text (tree, value_buff, startOffset,
3953                     offset - startOffset, "Invalid type");
3954         } else {
3955                 proto_tree_add_uint (tree, hf_wsp_parameter_type, value_buff,
3956                     startOffset, offset - startOffset, value);
3957         }
3958         return offset;
3959 }
3960
3961 static int
3962 add_parameter_text (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3963     int offset, int hf_string, const char *paramName)
3964 {
3965         value_type_t valueType;
3966         int subvalueLen;
3967         int subvalueOffset;
3968
3969         valueType = get_value_type_len (value_buff, offset,
3970             &subvalueLen, &subvalueOffset, &offset);
3971         if (valueType != VALUE_IS_TEXT_STRING) {
3972                 proto_tree_add_text (tree, value_buff, startOffset,
3973                     offset - startOffset, "Invalid %s", paramName);
3974         } else {
3975                 proto_tree_add_string (tree, hf_string, value_buff,
3976                             startOffset, offset - startOffset,
3977                             tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
3978         }
3979         return offset;
3980 }
3981
3982 void
3983 add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType,
3984     const char *contentTypeStr)
3985 {
3986         guint offset = 0;
3987         guint variableStart = 0;
3988         guint variableEnd = 0;
3989         guint valueStart = 0;
3990         guint valueEnd = 0;
3991         guint8 peek = 0;
3992         proto_item *ti;
3993         proto_tree *sub_tree;
3994
3995         /* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian); */
3996         ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian);
3997         sub_tree = proto_item_add_subtree(ti, ett_post);
3998
3999         if (contentTypeStr == NULL && contentType == 0x12)
4000         {
4001                 /*
4002                  * URL Encoded data.
4003                  * Iterate through post data.
4004                  */
4005                 for (offset = 0; offset < tvb_reported_length (tvb); offset++)
4006                 {
4007                         peek = tvb_get_guint8 (tvb, offset);
4008                         if (peek == '=')
4009                         {
4010                                 variableEnd = offset;
4011                                 valueStart = offset+1;
4012                         }
4013                         else if (peek == '&')
4014                         {
4015                                 if (variableEnd > 0)
4016                                 {
4017                                         add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
4018                                 }
4019                                 variableStart = offset+1;
4020                                 variableEnd = 0;
4021                                 valueStart = 0;
4022                                 valueEnd = 0;
4023                         }
4024                 }
4025
4026                 /* See if there's outstanding data */
4027                 if (variableEnd > 0)
4028                 {
4029                         add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
4030                 }
4031         }
4032         else if ((contentType == 0x22) || (contentType == 0x23) || (contentType == 0x23) || (contentType == 0x24) ||
4033                  (contentType == 0x25) || (contentType == 0x26) || (contentType == 0x33))
4034         {
4035                 add_multipart_data(sub_tree, tvb);
4036         }
4037 }
4038
4039 static void
4040 add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
4041 {
4042         int variableLength = variableEnd-variableStart;
4043         int valueLength = 0;
4044         char *variableBuffer;
4045         char *valueBuffer;
4046
4047         variableBuffer = g_malloc (variableLength+1);
4048         strncpy (variableBuffer, tvb_get_ptr (tvb, variableStart, variableLength), variableLength);
4049         variableBuffer[variableLength] = 0;
4050
4051         if (valueEnd < valueStart)
4052         {
4053                 valueBuffer = g_malloc (1);
4054                 valueBuffer[0] = 0;
4055                 valueEnd = valueStart;
4056         }
4057         else
4058         {
4059                 valueLength = valueEnd-valueStart;
4060                 valueBuffer = g_malloc (valueLength+1);
4061                 strncpy (valueBuffer, tvb_get_ptr (tvb, valueStart, valueLength), valueLength);
4062                 valueBuffer[valueLength] = 0;
4063         }
4064
4065         /* Check for variables with no value */
4066         if (valueStart >= tvb_reported_length (tvb))
4067         {
4068                 valueStart = tvb_reported_length (tvb);
4069                 valueEnd = valueStart;
4070         }
4071         valueLength = valueEnd-valueStart;
4072
4073         proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
4074
4075         g_free (variableBuffer);
4076         g_free (valueBuffer);
4077 }
4078
4079 static void
4080 add_multipart_data (proto_tree *tree, tvbuff_t *tvb)
4081 {
4082         int              offset = 0;
4083         guint            nextOffset;
4084         guint            nEntries = 0;
4085         guint            count;
4086         guint            HeadersLen;
4087         guint            DataLen;
4088         guint            contentType = 0;
4089         const char      *contentTypeStr;
4090         tvbuff_t        *tmp_tvb;
4091         int              partnr = 1;
4092         int              part_start;
4093
4094         proto_item      *sub_tree = NULL,
4095                         *ti;
4096         proto_tree      *mpart_tree;
4097
4098         nEntries = tvb_get_guintvar (tvb, offset, &count);
4099         offset += count;
4100         if (nEntries)
4101         {
4102                 sub_tree = proto_tree_add_text(tree, tvb, offset - count, 0,
4103                                         "Multipart body");
4104                 proto_item_add_subtree(sub_tree, ett_mpartlist);
4105         }
4106         while (nEntries--)
4107         {
4108                 part_start = offset;
4109                 HeadersLen = tvb_get_guintvar (tvb, offset, &count);
4110                 offset += count;
4111                 DataLen = tvb_get_guintvar (tvb, offset, &count);
4112                 offset += count;
4113                 ti = proto_tree_add_uint(sub_tree, hf_wsp_mpart, tvb, part_start,
4114                                         HeadersLen + DataLen + (offset - part_start), partnr);
4115                 mpart_tree = proto_item_add_subtree(ti, ett_multiparts);
4116                 nextOffset = add_content_type (mpart_tree, tvb, offset, &contentType, &contentTypeStr);
4117                 HeadersLen -= (nextOffset - offset);
4118                 if (HeadersLen > 0)
4119                 {
4120                         tmp_tvb = tvb_new_subset (tvb, nextOffset, HeadersLen, HeadersLen);
4121                         add_headers (mpart_tree, tmp_tvb);
4122                 }
4123                 offset = nextOffset + HeadersLen;
4124                 proto_tree_add_item (mpart_tree, hf_wsp_multipart_data, tvb, offset, DataLen, bo_little_endian);
4125                 offset += DataLen;
4126                 partnr++;
4127         }
4128 }
4129
4130 static gint
4131 get_integer (tvbuff_t *tvb, guint offset, guint valueLength,
4132     value_type_t valueType, guint *value)
4133 {
4134         if (valueType == VALUE_IS_TEXT_STRING) {
4135                 /*
4136                  * Not valid.
4137                  */
4138                 return -1;
4139         }
4140
4141         if (valueType == VALUE_IN_LEN) {
4142                 /*
4143                  * Short-integer.
4144                  */
4145                 *value = valueLength;
4146                 return 0;
4147         }
4148
4149         /*
4150          * Long-integer.
4151          */
4152         switch (valueLength)
4153         {
4154                 case 1:
4155                         *value = tvb_get_guint8(tvb, offset);
4156                         break;
4157                 case 2:
4158                         *value = tvb_get_ntohs(tvb, offset);
4159                         break;
4160                 case 3:
4161                         *value = tvb_get_ntoh24(tvb, offset);
4162                         break;
4163                 case 4:
4164                         *value = tvb_get_ntohl(tvb, offset);
4165                         break;
4166                 default:
4167                         /* TODO: Need to read peek octets */
4168                         *value = 0;
4169                         fprintf (stderr, "dissect_wsp: get_integer size %u NYI\n", valueLength);
4170                         break;
4171         }
4172         return 0;
4173 }
4174
4175 /* Register the protocol with Ethereal */
4176 void
4177 proto_register_wsp(void)
4178 {
4179
4180 /* Setup list of header fields */
4181         static hf_register_info hf[] = {
4182                 { &hf_wsp_header_tid,
4183                         {       "Transaction ID",
4184                                 "wsp.TID",
4185                                  FT_UINT8, BASE_HEX, NULL, 0x00,
4186                                 "Transaction ID", HFILL
4187                         }
4188                 },
4189                 { &hf_wsp_header_pdu_type,
4190                         {       "PDU Type",
4191                                 "wsp.pdu_type",
4192                                  FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
4193                                 "PDU Type", HFILL
4194                         }
4195                 },
4196                 { &hf_wsp_version_major,
4197                         {       "Version (Major)",
4198                                 "wsp.version.major",
4199                                  FT_UINT8, BASE_DEC, NULL, 0xF0,
4200                                 "Version (Major)", HFILL
4201                         }
4202                 },
4203                 { &hf_wsp_version_minor,
4204                         {       "Version (Minor)",
4205                                 "wsp.version.minor",
4206                                  FT_UINT8, BASE_DEC, NULL, 0x0F,
4207                                 "Version (Minor)", HFILL
4208                         }
4209                 },
4210                 { &hf_wsp_capability_length,
4211                         {       "Capability Length",
4212                                 "wsp.capability.length",
4213                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4214                                 "Capability Length", HFILL
4215                         }
4216                 },
4217                 { &hf_wsp_header_length,
4218                         {       "Headers Length",
4219                                 "wsp.headers_length",
4220                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4221                                 "Headers Length", HFILL
4222                         }
4223                 },
4224                 { &hf_wsp_capabilities_section,
4225                         {       "Capabilities",
4226                                 "wsp.capabilities",
4227                                  FT_NONE, BASE_DEC, NULL, 0x00,
4228                                 "Capabilities", HFILL
4229                         }
4230                 },
4231                 { &hf_wsp_headers_section,
4232                         {       "Headers",
4233                                 "wsp.headers",
4234                                  FT_NONE, BASE_DEC, NULL, 0x00,
4235                                 "Headers", HFILL
4236                         }
4237                 },
4238                 { &hf_wsp_header,
4239                         {       "Header",
4240                                 "wsp.headers.header",
4241                                  FT_NONE, BASE_DEC, NULL, 0x00,
4242                                 "Header", HFILL
4243                         }
4244                 },
4245                 { &hf_wsp_header_uri_len,
4246                         {       "URI Length",
4247                                 "wsp.uri_length",
4248                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4249                                 "URI Length", HFILL
4250                         }
4251                 },
4252                 { &hf_wsp_header_uri,
4253                         {       "URI",
4254                                 "wsp.uri",
4255                                  FT_STRING, BASE_NONE, NULL, 0x00,
4256                                 "URI", HFILL
4257                         }
4258                 },
4259                 { &hf_wsp_server_session_id,
4260                         {       "Server Session ID",
4261                                 "wsp.server.session_id",
4262                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4263                                 "Server Session ID", HFILL
4264                         }
4265                 },
4266                 { &hf_wsp_header_status,
4267                         {       "Status",
4268                                 "wsp.reply.status",
4269                                  FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
4270                                 "Status", HFILL
4271                         }
4272                 },
4273                 { &hf_wsp_content_type,
4274                         {       "Content Type",
4275                                 "wsp.content_type.type",
4276                                  FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
4277                                 "Content Type", HFILL
4278                         }
4279                 },
4280                 { &hf_wsp_content_type_str,
4281                         {       "Content Type",
4282                                 "wsp.content_type.type.string",
4283                                  FT_STRING, BASE_NONE, NULL, 0x00,
4284                                 "Content Type", HFILL
4285                         }
4286                 },
4287                 { &hf_wsp_parameter_well_known_charset,
4288                         {       "Charset",
4289                                 "wsp.content_type.parameter.charset",
4290                                  FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
4291                                 "Charset", HFILL
4292                         }
4293                 },
4294                 { &hf_wsp_parameter_type,
4295                         {       "Type",
4296                                 "wsp.content_type.parameter.type",
4297                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4298                                 "Type", HFILL
4299                         }
4300                 },
4301                 { &hf_wsp_parameter_name,
4302                         {       "Name",
4303                                 "wsp.content_type.parameter.name",
4304                                  FT_STRING, BASE_NONE, NULL, 0x00,
4305                                 "Name", HFILL
4306                         }
4307                 },
4308                 { &hf_wsp_parameter_filename,
4309                         {       "Filename",
4310                                 "wsp.content_type.parameter.filename",
4311                                  FT_STRING, BASE_NONE, NULL, 0x00,
4312                                 "Filename", HFILL
4313                         }
4314                 },
4315                 { &hf_wsp_parameter_start,
4316                         {       "Start",
4317                                 "wsp.content_type.parameter.start",
4318                                  FT_STRING, BASE_NONE, NULL, 0x00,
4319                                 "Start", HFILL
4320                         }
4321                 },
4322                 { &hf_wsp_parameter_start_info,
4323                         {       "Start-info",
4324                                 "wsp.content_type.parameter.start_info",
4325                                  FT_STRING, BASE_NONE, NULL, 0x00,
4326                                 "Start-info", HFILL
4327                         }
4328                 },
4329                 { &hf_wsp_parameter_comment,
4330                         {       "Comment",
4331                                 "wsp.content_type.parameter.comment",
4332                                  FT_STRING, BASE_NONE, NULL, 0x00,
4333                                 "Comment", HFILL
4334                         }
4335                 },
4336                 { &hf_wsp_parameter_domain,
4337                         {       "Domain",
4338                                 "wsp.content_type.parameter.domain",
4339                                  FT_STRING, BASE_NONE, NULL, 0x00,
4340                                 "Domain", HFILL
4341                         }
4342                 },
4343                 { &hf_wsp_parameter_path,
4344                         {       "Path",
4345                                 "wsp.content_type.parameter.path",
4346                                  FT_STRING, BASE_NONE, NULL, 0x00,
4347                                 "Path", HFILL
4348                         }
4349                 },
4350                 { &hf_wsp_parameter_sec,
4351                         {       "SEC",
4352                                 "wsp.content_type.parameter.sec",
4353                                  FT_UINT8, BASE_HEX, VALS (vals_wsp_parameter_sec), 0x00,
4354                                 "SEC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
4355                         }
4356                 },
4357                 { &hf_wsp_parameter_mac,
4358                         {       "MAC",
4359                                 "wsp.content_type.parameter.mac",
4360                                  FT_STRING, BASE_NONE, NULL, 0x00,
4361                                 "MAC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
4362                         }
4363                 },
4364                 { &hf_wsp_parameter_upart_type,
4365                         {       "Type",
4366                                 "wsp.content_type.parameter.upart.type",
4367                                  FT_STRING, BASE_NONE, NULL, 0x00,
4368                                 "Multipart type", HFILL
4369                         }
4370                 },
4371                 { &hf_wsp_parameter_upart_type_value,
4372                         {       "Type",
4373                                 "wsp.content_type.parameter.upart.type.int",
4374                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4375                                 "Multipart type (int value)", HFILL
4376                         }
4377                 },
4378                 { &hf_wsp_reply_data,
4379                         {       "Data",
4380                                 "wsp.reply.data",
4381                                  FT_NONE, BASE_NONE, NULL, 0x00,
4382                                 "Data", HFILL
4383                         }
4384                 },
4385                 { &hf_wsp_header_shift_code,
4386                         {       "Shift code",
4387                                 "wsp.header.shift",
4388                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4389                                  FT_UINT8, BASE_HEX, NULL, 0x00,
4390                                 "Header code page shift code", HFILL
4391                         }
4392                 },
4393                 { &hf_wsp_header_accept,
4394                         {       "Accept",
4395                                 "wsp.header.accept",
4396                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4397                                  FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
4398                                 "Accept", HFILL
4399                         }
4400                 },
4401                 { &hf_wsp_header_accept_str,
4402                         {       "Accept",
4403                                 "wsp.header.accept.string",
4404                                  FT_STRING, BASE_NONE, NULL, 0x00,
4405                                 "Accept", HFILL
4406                         }
4407                 },
4408                 { &hf_wsp_header_accept_application,
4409                         {       "Accept-Application",
4410                                 "wsp.header.accept_application",
4411                                  FT_UINT32, BASE_HEX, NULL, 0x00,
4412                                 "Accept-Application", HFILL
4413                         }
4414                 },
4415                 { &hf_wsp_header_accept_application_str,
4416                         {       "Accept-Application",
4417                                 "wsp.header.accept_application.string",
4418                                  FT_STRING, BASE_NONE, NULL, 0x00,
4419                                 "Accept-Application", HFILL
4420                         }
4421                 },
4422                 { &hf_wsp_header_accept_charset,
4423                         {       "Accept-Charset",
4424                                 "wsp.header.accept_charset",
4425                                  FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
4426                                 "Accept-Charset", HFILL
4427                         }
4428                 },
4429                 { &hf_wsp_header_accept_charset_str,
4430                         {       "Accept-Charset",
4431                                 "wsp.header.accept_charset.string",
4432                                  FT_STRING, BASE_NONE, NULL, 0x00,
4433                                 "Accept-Charset", HFILL
4434                         }
4435                 },
4436                 { &hf_wsp_header_accept_language,
4437                         {       "Accept-Language",
4438                                 "wsp.header.accept_language",
4439                                  FT_UINT8, BASE_HEX, VALS ( vals_languages ), 0x00,
4440                                 "Accept-Language", HFILL
4441                         }
4442                 },
4443                 { &hf_wsp_header_accept_language_str,
4444                         {       "Accept-Language",
4445                                 "wsp.header.accept_language.string",
4446                                  FT_STRING, BASE_NONE, NULL, 0x00,
4447                                 "Accept-Language", HFILL
4448                         }
4449                 },
4450                 { &hf_wsp_header_accept_ranges,
4451                         {       "Accept-Ranges",
4452                                 "wsp.header.accept_ranges",
4453                                  FT_UINT8, BASE_HEX, VALS ( vals_accept_ranges ), 0x00,
4454                                 "Accept-Ranges", HFILL
4455                         }
4456                 },
4457                 { &hf_wsp_header_accept_ranges_str,
4458                         {       "Accept-Ranges",
4459                                 "wsp.header.accept_ranges.string",
4460                                  FT_STRING, BASE_NONE, NULL, 0x00,
4461                                 "Accept-Ranges", HFILL
4462                         }
4463                 },
4464                 { &hf_wsp_header_age,
4465                         {       "Age",
4466                                 "wsp.header.age",
4467                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4468                                 "Age", HFILL
4469                         }
4470                 },
4471                 { &hf_wsp_header_openwave_proxy_push_addr,
4472                         {       "x-up-proxy-push-addr",
4473                                 "wsp.header.x-up-proxy-push-addr",
4474                                  FT_BYTES, BASE_HEX, NULL, 0x00,
4475                                 "The network address and port number that the handset can receive UPNOTIFY pushes on.", HFILL
4476                         }
4477                 },
4478                 { &hf_wsp_header_openwave_proxy_push_accept,
4479                         {       "x-up-proxy-push-accept",
4480                                 "wsp.header.x-up-proxy-push-accept",
4481                                  FT_STRING, BASE_NONE, NULL, 0x00,
4482                                 "The content types that the handset can handle when sent via UPNOTIFY pushes.", HFILL
4483                         }
4484                 },
4485                 { &hf_wsp_header_openwave_proxy_push_seq,
4486                         {       "x-up-proxy-push-seq",
4487                                 "wsp.header.x-up-proxy-push-seq",
4488                                  FT_UINT16, BASE_DEC, NULL, 0x00,
4489                                 "Specifies the sequence number of the last UPNOTIFY push sent.", HFILL
4490                         }
4491                 },
4492                 { &hf_wsp_header_openwave_proxy_notify,
4493                         {       "x-up-proxy-notify",
4494                                 "wsp.header.x-up-proxy-notify",
4495                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4496                                 "Indicates to the handset that there are pending UPNOTIFY pushes waiting.", HFILL
4497                         }
4498                 },
4499                 { &hf_wsp_header_openwave_proxy_operator_domain,
4500                         {       "x-up-proxy-operator-domain",
4501                                 "wsp.header.x-up-proxy-operator-domain",
4502                                  FT_STRING, BASE_NONE, NULL, 0x00,
4503                                 "Indicates the Trusted Provisioning Domain.", HFILL
4504                         }
4505                 },
4506                 { &hf_wsp_header_openwave_proxy_home_page,
4507                         {       "x-up-proxy-home-page",
4508                                 "wsp.header.x-up-proxy-home-page",
4509                                  FT_STRING, BASE_NONE, NULL, 0x00,
4510                                 "Specifies the server-assigned home page URL.", HFILL
4511                         }
4512                 },
4513                 { &hf_wsp_header_openwave_devcap_has_color,
4514                         {       "x-up-devcap-has-color",
4515                                 "wsp.header.x-up-devcap-has-color",
4516                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4517                                 "Indicates if the handset supports colour.", HFILL
4518                         }
4519                 },
4520                 { &hf_wsp_header_openwave_devcap_num_softkeys,
4521                         {       "x-up-devcap-num-softkeys",
4522                                 "wsp.header.x-up-devcap-num-softkeys",
4523                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4524                                 "The number of softkeys that can be displayed on the handset.", HFILL
4525                         }
4526                 },
4527                 { &hf_wsp_header_openwave_devcap_softkey_size,
4528                         {       "x-up-devcap-softkey-size",
4529                                 "wsp.header.x-up-devcap-softkey-size",
4530                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4531                                 "The number of chars that can be displayed on a softkey label.", HFILL
4532                         }
4533                 },
4534                 { &hf_wsp_header_openwave_devcap_screen_chars,
4535                         {       "x-up-devcap-screen-chars",
4536                                 "wsp.header.x-up-devcap-screen-chars",
4537                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4538                                 "The height and width of the handset's display in characters.", HFILL
4539                         }
4540                 },
4541                 { &hf_wsp_header_openwave_devcap_screen_pixels,
4542                         {       "x-up-devcap-screen-pixels",
4543                                 "wsp.header.x-up-devcap-screen-pixels",
4544                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4545                                 "The height and width of the handset's display in pixels.", HFILL
4546                         }
4547                 },
4548                 { &hf_wsp_header_openwave_devcap_em_size,
4549                         {       "x-up-devcap-em-size",
4550                                 "wsp.header.x-up-devcap-em-size",
4551                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4552                                 "The height and width of an uppercase M in pixels in a handset.", HFILL
4553                         }
4554                 },
4555                 { &hf_wsp_header_openwave_devcap_screen_depth,
4556                         {       "x-up-devcap-screen-depth",
4557                                 "wsp.header.x-up-devcap-screen-depth",
4558                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4559                                 "The colour/gray depth of the display in bits.", HFILL
4560                         }
4561                 },
4562                 { &hf_wsp_header_openwave_devcap_immed_alert,
4563                         {       "x-up-devcap-immed-alert",
4564                                 "wsp.header.x-up-devcap-immed-alert",
4565                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4566                                 "Indicates if the handset has support for immediate UPNOTIFY alerts.", HFILL
4567                         }
4568                 },
4569                 { &hf_wsp_header_openwave_proxy_net_ask,
4570                         {       "x-up-proxy-net-ask",
4571                                 "wsp.header.x-up-proxy-net-ask",
4572                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4573                                 "Indicates to browser if circuit switched call is allowed without user interaction", HFILL
4574                         }
4575                 },
4576                 { &hf_wsp_header_openwave_proxy_uplink_version,
4577                         {       "x-up-proxy-uplink-version",
4578                                 "wsp.header.x-up-proxy-uplink-version",
4579                                  FT_STRING, BASE_NONE, NULL, 0x00,
4580                                 "Version of the MAG WAP gateway", HFILL
4581                         }
4582                 },
4583                 { &hf_wsp_header_openwave_proxy_tod,
4584                         {       "x-up-proxy-tod",
4585                                 "wsp.header.x-up-proxy-tod",
4586                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4587                                 "Time of day", HFILL
4588                         }
4589                 },
4590                 { &hf_wsp_header_openwave_proxy_ba_enable,
4591                         {       "x-up-proxy-ba-enable",
4592                                 "wsp.header.x-up-proxy-ba-enable",
4593                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4594                                 "Indicates if the WAP gateway should cache basic authentication details on behalf of the handset", HFILL
4595                         }
4596                 },
4597                 { &hf_wsp_header_openwave_proxy_ba_realm,
4598                         {       "x-up-proxy-ba-realm",
4599                                 "wsp.header.x-up-proxy-ba-realm",
4600                                  FT_STRING, BASE_NONE, NULL, 0x00,
4601                                 "Indicates the realm within which basic authentication credentials apply", HFILL
4602                         }
4603                 },
4604                 { &hf_wsp_header_openwave_proxy_redirect_enable,
4605                         {       "x-up-proxy-redirect-enable",
4606                                 "wsp.header.x-up-proxy-redirect-enable",
4607                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4608                                 "Indicates if the handset wants the WAP gateway to handle HTTP redirects on its behalf", HFILL
4609                         }
4610                 },
4611                 { &hf_wsp_header_openwave_proxy_request_uri,
4612                         {       "x-up-proxy-request-uri",
4613                                 "wsp.header.x-up-proxy-request-uri",
4614                                  FT_STRING, BASE_NONE, NULL, 0x00,
4615                                 "Indicates to the handset that the previous request was redirected to the specified URI", HFILL
4616                         }
4617                 },
4618                 { &hf_wsp_header_openwave_proxy_redirect_status,
4619                         {       "x-up-proxy-redirect-status",
4620                                 "wsp.header.x-up-proxy-redirect-status",
4621                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4622                                 "Indicates the status of a redirect performed on behalf of a handset", HFILL
4623                         }
4624                 },
4625                 { &hf_wsp_header_openwave_proxy_trans_charset,
4626                         {       "x-up-proxy-trans-charset",
4627                                 "wsp.header.x-up-proxy-trans-charset",
4628                                  FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
4629                                 "For POSTs indicates the charset encoding of a document", HFILL
4630                         }
4631                 },
4632                 { &hf_wsp_header_openwave_proxy_trans_charset_str,
4633                         {       "x-up-proxy-trans-charset",
4634                                 "wsp.header.x-up-proxy-trans-charset.string",
4635                                  FT_STRING, BASE_NONE, NULL, 0x00,
4636                                 "For POSTs indicates the charset encoding of a document", HFILL
4637                         }
4638                 },
4639                 { &hf_wsp_header_openwave_proxy_linger,
4640                         {       "x-up-proxy-linger",
4641                                 "wsp.header.x-up-proxy-linger",
4642                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4643                                 "Indicates the circuit linger time in seconds", HFILL
4644                         }
4645                 },
4646                 { &hf_wsp_header_openwave_proxy_client_id,
4647                         {       "x-up-proxy-client-id",
4648                                 "wsp.header.x-up-proxy-client-id",
4649                                  FT_BYTES, BASE_DEC, NULL, 0x00,
4650                                 "The ClientId of the handset", HFILL
4651                         }
4652                 },
4653                 { &hf_wsp_header_openwave_proxy_enable_trust,
4654                         {       "x-up-proxy-enable-trust",
4655                                 "wsp.header.x-up-proxy-enable-trust",
4656                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4657                                 "Indicates whether to enable Trusted Provisioning Domain", HFILL
4658                         }
4659                 },
4660                 { &hf_wsp_header_openwave_proxy_trust_old,
4661                         {       "x-up-proxy-trust-old",
4662                                 "wsp.header.x-up-proxy-trust-old",
4663                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4664                                 "Indicates if the content being returned was received from within the Trusted Provisioning Domain", HFILL
4665                         }
4666                 },
4667                 { &hf_wsp_header_openwave_proxy_trust,
4668                         {       "x-up-proxy-trust",
4669                                 "wsp.header.x-up-proxy-trust",
4670                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4671                                 "Indicates if the content being returned was received from within the Trusted Provisioning Domain", HFILL
4672                         }
4673                 },
4674                 { &hf_wsp_header_openwave_proxy_bookmark,
4675                         {       "x-up-proxy-bookmark",
4676                                 "wsp.header.x-up-proxy-bookmark",
4677                                  FT_STRING, BASE_NONE, NULL, 0x00,
4678                                 "Specifies the URL to use for server-side bookmarks", HFILL
4679                         }
4680                 },
4681                 { &hf_wsp_header_openwave_devcap_gui,
4682                         {       "x-up-devcap-gui",
4683                                 "wsp.header.x-up-devcap-gui",
4684                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4685                                 "Indicates if the handset has a GUI", HFILL
4686                         }
4687                 },
4688                 { &hf_wsp_header_bearer_indication,
4689                         /*
4690                          * XXX - I'm assuming that the bearer indication is
4691                          * just a bearer type.
4692                          */
4693                         {       "Bearer-indication",
4694                                 "wsp.header.bearer_indication",
4695                                  FT_UINT32, BASE_HEX, VALS(vals_bearer_types), 0x00,
4696                                 "Bearer-indication", HFILL
4697                         }
4698                 },
4699                 { &hf_wsp_header_cache_control,
4700                         {       "Cache-Control",
4701                                 "wsp.header.cache_control",
4702                                  FT_UINT8, BASE_HEX, VALS ( vals_cache_control ), 0x00,
4703                                 "Cache-Control", HFILL
4704                         }
4705                 },
4706                 { &hf_wsp_header_cache_control_str,
4707                         {       "Cache-Control",
4708                                 "wsp.header.cache_control.string",
4709                                  FT_STRING, BASE_NONE, NULL, 0x00,
4710                                 "Cache-Control", HFILL
4711                         }
4712                 },
4713                 { &hf_wsp_header_cache_control_field_name,
4714                         {       "Field Name",
4715                                 "wsp.header.cache_control.field_name",
4716                                  FT_UINT8, BASE_HEX, VALS ( vals_field_names ), 0x00,
4717                                 "Cache-Control field name", HFILL
4718                         }
4719                 },
4720                 { &hf_wsp_header_cache_control_field_name_str,
4721                         {       "Field Name",
4722                                 "wsp.header.cache_control.field_name.str",
4723                                  FT_STRING, BASE_NONE, NULL, 0x00,
4724                                 "Cache-Control field name", HFILL
4725                         }
4726                 },
4727                 { &hf_wsp_header_connection,
4728                         {       "Connection",
4729                                 "wsp.header.connection",
4730                                  FT_UINT8, BASE_HEX, VALS ( vals_connection ), 0x00,
4731                                 "Connection", HFILL
4732                         }
4733                 },
4734                 { &hf_wsp_header_connection_str,
4735                         {       "Connection",
4736                                 "wsp.header.connection_str",
4737                                  FT_STRING, BASE_NONE, NULL, 0x00,
4738                                 "Connection", HFILL
4739                         }
4740                 },
4741                 { &hf_wsp_header_content_length,
4742                         {       "Content-Length",
4743                                 "wsp.header.content_length",
4744                                  FT_UINT32, BASE_DEC, NULL, 0x00,
4745                                 "Content-Length", HFILL
4746                         }
4747                 },
4748                 { &hf_wsp_header_date,
4749                         {       "Date",
4750                                 "wsp.header.date",
4751                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4752                                 "Date", HFILL
4753                         }
4754                 },
4755                 { &hf_wsp_header_etag,
4756                         {       "Etag",
4757                                 "wsp.header.etag",
4758                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4759                                  FT_STRING, BASE_NONE, NULL, 0x00,
4760                                 "Etag", HFILL
4761                         }
4762                 },
4763                 { &hf_wsp_header_expires,
4764                         {       "Expires",
4765                                 "wsp.header.expires",
4766                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4767                                 "Expires", HFILL
4768                         }
4769                 },
4770                 { &hf_wsp_header_last_modified,
4771                         {       "Last-Modified",
4772                                 "wsp.header.last_modified",
4773                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4774                                 "Last-Modified", HFILL
4775                         }
4776                 },
4777                 { &hf_wsp_header_location,
4778                         {       "Location",
4779                                 "wsp.header.location",
4780                                  FT_STRING, BASE_NONE, NULL, 0x00,
4781                                 "Location", HFILL
4782                         }
4783                 },
4784                 { &hf_wsp_header_if_modified_since,
4785                         {       "If-Modified-Since",
4786                                 "wsp.header.if_modified_since",
4787                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4788                                 "If-Modified-Since", HFILL
4789                         }
4790                 },
4791                 { &hf_wsp_header_pragma,
4792                         {       "Pragma",
4793                                 "wsp.header.pragma",
4794                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4795                                  FT_STRING, BASE_NONE, NULL, 0x00,
4796                                 "pragma", HFILL
4797                         }
4798                 },
4799                 { &hf_wsp_header_authorization,
4800                         {       "Authorization",
4801                                 "wsp.header.authorization",
4802                                  FT_NONE, BASE_NONE, NULL, 0x00,
4803                                 "Authorization", HFILL
4804                         }
4805                 },
4806                 { &hf_wsp_header_authorization_scheme,
4807                         {       "Authentication scheme",
4808                                 "wsp.header.authorization.scheme",
4809                                  FT_STRING, BASE_NONE, NULL, 0x00,
4810                                 "Authorization: Authentication Scheme", HFILL
4811                         }
4812                 },
4813                 { &hf_wsp_header_authorization_user_id,
4814                         {       "User-ID",
4815                                 "wsp.header.authorization.user_id",
4816                                  FT_STRING, BASE_NONE, NULL, 0x00,
4817                                 "Authorization: Basic: User-ID", HFILL
4818                         }
4819                 },
4820                 { &hf_wsp_header_authorization_password,
4821                         {       "Password",
4822                                 "wsp.header.authorization.password",
4823                                  FT_STRING, BASE_NONE, NULL, 0x00,
4824                                 "Authorization: Basic: Password", HFILL
4825                         }
4826                 },
4827                 { &hf_wsp_header_proxy_authorization,
4828                         {       "Proxy-Authorization",
4829                                 "wsp.header.proxy_authorization",
4830                                  FT_NONE, BASE_NONE, NULL, 0x00,
4831                                 "Proxy-Authorization", HFILL
4832                         }
4833                 },
4834                 { &hf_wsp_header_proxy_authorization_scheme,
4835                         {       "Authentication scheme",
4836                                 "wsp.header.proxy_authorization.scheme",
4837                                  FT_STRING, BASE_NONE, NULL, 0x00,
4838                                 "Proxy-Authorization: Authentication Scheme", HFILL
4839                         }
4840                 },
4841                 { &hf_wsp_header_proxy_authorization_user_id,
4842                         {       "User-Id",
4843                                 "wsp.header.proxy_authorization.user_id",
4844                                  FT_STRING, BASE_NONE, NULL, 0x00,
4845                                 "Proxy-Authorization: Basic: User-ID", HFILL
4846                         }
4847                 },
4848                 { &hf_wsp_header_proxy_authorization_password,
4849                         {       "Password",
4850                                 "wsp.header.proxy_authorization.password",
4851                                  FT_STRING, BASE_NONE, NULL, 0x00,
4852                                 "Proxy-Authorization: Basic: Password", HFILL
4853                         }
4854                 },
4855                 { &hf_wsp_header_www_authenticate,
4856                         {       "WWW-Authenticate",
4857                                 "wsp.header.www-authenticate",
4858                                  FT_STRING, BASE_NONE, NULL, 0x00,
4859                                 "Authenticate", HFILL
4860                         }
4861                 },
4862                 { &hf_wsp_header_proxy_authenticate,
4863                         {       "Proxy-Authenticate",
4864                                 "wsp.header.proxy_authenticate",
4865                                  FT_STRING, BASE_NONE, NULL, 0x00,
4866                                 "Proxy-Authenticate", HFILL
4867                         }
4868                 },
4869                 { &hf_wsp_header_profile,
4870                         {       "Profile",
4871                                 "wsp.header.profile",
4872                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4873                                  FT_STRING, BASE_NONE, NULL, 0x00,
4874                                 "Profile", HFILL
4875                         }
4876                 },
4877                 { &hf_wsp_header_server,
4878                         {       "Server",
4879                                 "wsp.header.server",
4880                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4881                                  FT_STRING, BASE_NONE, NULL, 0x00,
4882                                 "Server", HFILL
4883                         }
4884                 },
4885                 { &hf_wsp_header_transfer_encoding,
4886                         {       "Transfer Encoding",
4887                                 "wsp.header.transfer_enc",
4888                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4889                                  FT_UINT8, BASE_HEX, VALS ( vals_transfer_encoding ), 0x00,
4890                                 "Transfer Encoding", HFILL
4891                         }
4892                 },
4893                 { &hf_wsp_header_transfer_encoding_str,
4894                         {       "Transfer Encoding",
4895                                 "wsp.header.transfer_enc_str",
4896                                  FT_STRING, BASE_NONE, NULL, 0x00,
4897                                 "Transfer Encoding", HFILL
4898                         }
4899                 },
4900                 { &hf_wsp_header_user_agent,
4901                         {       "User-Agent",
4902                                 "wsp.header.user_agent",
4903                                  /*FT_NONE, BASE_DEC, NULL, 0x00,*/
4904                                  FT_STRING, BASE_NONE, NULL, 0x00,
4905                                 "User-Agent", HFILL
4906                         }
4907                 },
4908                 { &hf_wsp_header_via,
4909                         {       "Via",
4910                                 "wsp.header.via",
4911                                  FT_STRING, BASE_NONE, NULL, 0x00,
4912                                 "Via", HFILL
4913                         }
4914                 },
4915                 { &hf_wsp_header_wap_application_id,
4916                         {       "X-Wap-Application-Id",
4917                                 "wsp.header.wap_application_id",
4918                                  FT_UINT8, BASE_HEX, NULL, 0x00,
4919                                 "WAP application id", HFILL
4920                         }
4921                 },
4922                 { &hf_wsp_header_wap_application_id_str,
4923                         {       "X-Wap-Application-Id",
4924                                 "wsp.header.wap_application_id.string",
4925                                  FT_STRING, BASE_NONE, NULL, 0x00,
4926                                 "WAP application id", HFILL
4927                         }
4928                 },
4929                 { &hf_wsp_header_warning,
4930                         {       "Warning",
4931                                 "wsp.header.warning",
4932                                  FT_NONE, BASE_NONE, NULL, 0x00,
4933                                 "Warning", HFILL
4934                         }
4935                 },
4936                 { &hf_wsp_header_warning_code,
4937                         {       "Warning Code",
4938                                 "wsp.header.warning.code",
4939                                  FT_UINT8, BASE_DEC, VALS (vals_wsp_warning_code), 0x00,
4940                                 "Warning Code", HFILL
4941                         }
4942                 },
4943                 { &hf_wsp_header_warning_agent,
4944                         {       "Warning Agent",
4945                                 "wsp.header.warning.agent",
4946                                  FT_STRING, BASE_NONE, NULL, 0x00,
4947                                 "Warning Agent", HFILL
4948                         }
4949                 },
4950                 { &hf_wsp_header_warning_text,
4951                         {       "Warning Text",
4952                                 "wsp.header.warning.text",
4953                                  FT_STRING, BASE_NONE, NULL, 0x00,
4954                                 "Warning Text", HFILL
4955                         }
4956                 },
4957                 { &hf_wsp_header_application_header,
4958                         {       "Application Header",
4959                                 "wsp.header.application_header",
4960                                  FT_STRING, BASE_NONE, NULL, 0x00,
4961                                 "Application Header", HFILL
4962                         }
4963                 },
4964                 { &hf_wsp_header_application_value,
4965                         {       "Application Header Value",
4966                                 "wsp.header.application_header.value",
4967                                  FT_STRING, BASE_NONE, NULL, 0x00,
4968                                 "Application Header Value", HFILL
4969                         }
4970                 },
4971                 { &hf_wsp_header_content_ID,
4972                         {       "Content-ID",
4973                                 "wsp.header.content-id",
4974                                  FT_STRING, BASE_NONE, NULL, 0x00,
4975                                 "Content-ID", HFILL
4976                         }
4977                 },
4978                 { &hf_wsp_header_x_wap_tod,
4979                         {       "X-WAP.TOD",
4980                                 "wsp.header.x_wap_tod",
4981                                  FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4982                                 "X-WAP.TOD", HFILL
4983                         }
4984                 },
4985                 { &hf_wsp_capabilities_client_SDU,
4986                         {       "Client SDU",
4987                                 "wsp.capabilities.client_SDU",
4988                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4989                                 "Client SDU", HFILL
4990                         }
4991                 },
4992                 { &hf_wsp_capabilities_server_SDU,
4993                         {       "Server SDU",
4994                                 "wsp.capabilities.server_SDU",
4995                                  FT_UINT8, BASE_DEC, NULL, 0x00,
4996                                 "Server SDU", HFILL
4997                         }
4998                 },
4999                 { &hf_wsp_capabilities_protocol_opt,
5000                         {       "Protocol Options",
5001                                 "wsp.capabilities.protocol_opt",
5002                                  FT_STRING, BASE_HEX, NULL, 0x00,
5003                                 "Protocol Options", HFILL
5004                         }
5005                 },
5006                 { &hf_wsp_capabilities_method_MOR,
5007                         {       "Method MOR",
5008                                 "wsp.capabilities.method_mor",
5009                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5010                                 "Method MOR", HFILL
5011                         }
5012                 },
5013                 { &hf_wsp_capabilities_push_MOR,
5014                         {       "Push MOR",
5015                                 "wsp.capabilities.push_mor",
5016                                  FT_UINT8, BASE_DEC, NULL, 0x00,
5017                                 "Push MOR", HFILL
5018                         }
5019                 },
5020                 { &hf_wsp_capabilities_extended_methods,
5021                         {       "Extended Methods",
5022                                 "wsp.capabilities.extend_methods",
5023                                  FT_STRING, BASE_HEX, NULL, 0x00,
5024                                 "Extended Methods", HFILL
5025                         }
5026                 },
5027                 { &hf_wsp_capabilities_header_code_pages,
5028                         {       "Header Code Pages",
5029                                 "wsp.capabilities.code_pages",
5030                                  FT_STRING, BASE_HEX, NULL, 0x00,
5031                                 "Header Code Pages", HFILL
5032                         }
5033                 },
5034                 { &hf_wsp_capabilities_aliases,
5035                         {       "Aliases",
5036                                 "wsp.capabilities.aliases",
5037                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5038                                 "Aliases", HFILL
5039                         }
5040                 },
5041                 { &hf_wsp_post_data,
5042                         {       "Data (Post)",
5043                                 "wsp.post.data",
5044                                  FT_NONE, BASE_NONE, NULL, 0x00,
5045                                 "Post Data", HFILL
5046                         }
5047                 },
5048                 { &hf_wsp_push_data,
5049                         {       "Push Data",
5050                                 "wsp.push.data",
5051                                  FT_NONE, BASE_NONE, NULL, 0x00,
5052                                 "Push Data", HFILL
5053                         }
5054                 },
5055                 { &hf_wsp_multipart_data,
5056                         {       "Data in this part",
5057                                 "wsp.multipart.data",
5058                                  FT_NONE, BASE_NONE, NULL, 0x00,
5059                                 "The data of 1 MIME-multipart part.", HFILL
5060                         }
5061                 },
5062                 { &hf_wsp_mpart,
5063                         {       "Part",
5064                                 "wsp.multipart",
5065                                  FT_UINT32, BASE_DEC, NULL, 0x00,
5066                                 "MIME part of multipart data.", HFILL
5067                         }
5068                 },
5069                 { &hf_wsp_redirect_flags,
5070                         {       "Flags",
5071                                 "wsp.redirect_flags",
5072                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5073                                 "Redirect Flags", HFILL
5074                         }
5075                 },
5076                 { &hf_wsp_redirect_permanent,
5077                         {       "Permanent Redirect",
5078                                 "wsp.redirect_flags.permanent",
5079                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), PERMANENT_REDIRECT,
5080                                 "Permanent Redirect", HFILL
5081                         }
5082                 },
5083                 { &hf_wsp_redirect_reuse_security_session,
5084                         {       "Reuse Security Session",
5085                                 "wsp.redirect_flags.reuse_security_session",
5086                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), REUSE_SECURITY_SESSION,
5087                                 "Permanent Redirect", HFILL
5088                         }
5089                 },
5090                 { &hf_wsp_redirect_afl,
5091                         {       "Flags/Length",
5092                                 "wsp.redirect_afl",
5093                                  FT_UINT8, BASE_HEX, NULL, 0x00,
5094                                 "Redirect Address Flags/Length", HFILL
5095                         }
5096                 },
5097                 { &hf_wsp_redirect_afl_bearer_type_included,
5098                         {       "Bearer Type Included",
5099                                 "wsp.redirect_afl.bearer_type_included",
5100                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), BEARER_TYPE_INCLUDED,
5101                                 "Redirect Address bearer type included", HFILL
5102                         }
5103                 },
5104                 { &hf_wsp_redirect_afl_port_number_included,
5105                         {       "Port Number Included",
5106                                 "wsp.redirect_afl.port_number_included",
5107                                  FT_BOOLEAN, 8, TFS(&yes_no_truth), PORT_NUMBER_INCLUDED,
5108                                 "Redirect Address port number included", HFILL
5109                         }
5110                 },
5111                 { &hf_wsp_redirect_afl_address_len,
5112                         {       "Address Len",
5113                                 "wsp.redirect_afl.address_len",
5114                                  FT_UINT8, BASE_DEC, NULL, ADDRESS_LEN,
5115                                 "Redirect Address Length", HFILL
5116                         }
5117                 },
5118                 { &hf_wsp_redirect_bearer_type,
5119                         {       "Bearer Type",
5120                                 "wsp.redirect_bearer_type",
5121                                  FT_UINT8, BASE_HEX, VALS(vals_bearer_types), 0x0,
5122                                 "Redirect Bearer Type", HFILL
5123                         }
5124                 },
5125                 { &hf_wsp_redirect_port_num,
5126                         {       "Port Number",
5127                                 "wsp.redirect_port_num",
5128                                  FT_UINT16, BASE_DEC, NULL, 0x0,
5129                                 "Redirect Port Number", HFILL
5130                         }
5131                 },
5132                 { &hf_wsp_redirect_ipv4_addr,
5133                         {       "IP Address",
5134                                 "wsp.redirect_ipv4_addr",
5135                                  FT_IPv4, BASE_NONE, NULL, 0x0,
5136                                 "Redirect Address (IP)", HFILL
5137                         }
5138                 },
5139                 { &hf_wsp_redirect_ipv6_addr,
5140                         {       "IPv6 Address",
5141                                 "wsp.redirect_ipv6_addr",
5142                                  FT_IPv6, BASE_NONE, NULL, 0x0,
5143                                 "Redirect Address (IPv6)", HFILL
5144                         }
5145                 },
5146                 { &hf_wsp_redirect_addr,
5147                         {       "Address",
5148                                 "wsp.redirect_addr",
5149                                  FT_BYTES, BASE_NONE, NULL, 0x0,
5150                                 "Redirect Address", HFILL
5151                         }
5152                 },
5153         };
5154
5155 /* Setup protocol subtree array */
5156         static gint *ett[] = {
5157                 &ett_wsp,
5158                 &ett_content_type_parameters,
5159                 &ett_header,
5160                 &ett_headers,
5161                 &ett_header_warning,
5162                 &ett_header_cache_control_parameters,
5163                 &ett_header_cache_control_field_names,
5164                 &ett_capabilities,
5165                 &ett_post,
5166                 &ett_content_type,
5167                 &ett_redirect_flags,
5168                 &ett_redirect_afl,
5169                 &ett_multiparts,
5170                 &ett_mpartlist,
5171                 &ett_header_credentials,
5172         };
5173
5174 /* Register the protocol name and description */
5175         proto_wsp = proto_register_protocol(
5176                 "Wireless Session Protocol",    /* protocol name for use by ethereal */
5177                 "WSP",                          /* short version of name */
5178                 "wap-wsp"                       /* Abbreviated protocol name, should Match IANA
5179                                                     < URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
5180                                                   */
5181         );
5182
5183 /* Required function calls to register the header fields and subtrees used  */
5184         proto_register_field_array(proto_wsp, hf, array_length(hf));
5185         proto_register_subtree_array(ett, array_length(ett));
5186
5187         register_dissector("wsp-co", dissect_wsp_fromwap_co, proto_wsp);
5188         register_dissector("wsp-cl", dissect_wsp_fromwap_cl, proto_wsp);
5189         wsp_dissector_table = register_dissector_table("wsp.content_type.type",
5190             "WSP content type", FT_UINT8, BASE_HEX);
5191         register_heur_dissector_list("wsp", &heur_subdissector_list);
5192
5193         wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
5194             proto_wsp);
5195 };
5196
5197 void
5198 proto_reg_handoff_wsp(void)
5199 {
5200         /*
5201          * Get a handle for the WBXML dissector.
5202          */
5203         wbxml_handle = find_dissector("wbxml");
5204
5205         /*
5206          * And get a handle for the WTP-over-UDP dissector.
5207          */
5208         wtp_fromudp_handle = find_dissector("wtp-udp");
5209
5210         /* Only connection-less WSP has no previous handler */
5211         dissector_add("udp.port", UDP_PORT_WSP, wsp_fromudp_handle);
5212         dissector_add("udp.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
5213
5214         /* This dissector is also called from the WTP and WTLS dissectors */
5215 }