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