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