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