3 * Routines to dissect WSP component of WAP traffic.
5 * $Id: packet-wsp.c,v 1.50 2001/12/10 00:25:41 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
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)
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
41 #ifdef HAVE_NETINET_IN_H
42 # include <netinet/in.h>
45 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
57 #include "ipv6-utils.h"
58 #include "conversation.h"
59 #include "packet-wap.h"
60 #include "packet-wsp.h"
62 /* File scoped variables for the protocol and registered fields */
63 static int proto_wsp = HF_EMPTY;
65 /* These fields used by fixed part of header */
66 static int hf_wsp_header_tid = HF_EMPTY;
67 static int hf_wsp_header_pdu_type = HF_EMPTY;
68 static int hf_wsp_version_major = HF_EMPTY;
69 static int hf_wsp_version_minor = HF_EMPTY;
70 static int hf_wsp_capability_length = HF_EMPTY;
71 static int hf_wsp_capabilities_section = HF_EMPTY;
72 static int hf_wsp_capabilities_client_SDU = HF_EMPTY;
73 static int hf_wsp_capabilities_server_SDU = HF_EMPTY;
74 static int hf_wsp_capabilities_protocol_opt = HF_EMPTY;
75 static int hf_wsp_capabilities_method_MOR = HF_EMPTY;
76 static int hf_wsp_capabilities_push_MOR = HF_EMPTY;
77 static int hf_wsp_capabilities_extended_methods = HF_EMPTY;
78 static int hf_wsp_capabilities_header_code_pages = HF_EMPTY;
79 static int hf_wsp_capabilities_aliases = HF_EMPTY;
80 static int hf_wsp_header_uri_len = HF_EMPTY;
81 static int hf_wsp_header_uri = HF_EMPTY;
82 static int hf_wsp_server_session_id = HF_EMPTY;
83 static int hf_wsp_header_status = HF_EMPTY;
84 static int hf_wsp_header_length = HF_EMPTY;
85 static int hf_wsp_headers_section = HF_EMPTY;
86 static int hf_wsp_header = HF_EMPTY;
87 static int hf_wsp_content_type = HF_EMPTY;
88 static int hf_wsp_content_type_str = HF_EMPTY;
89 static int hf_wsp_parameter_well_known_charset = HF_EMPTY;
90 static int hf_wsp_parameter_type = HF_EMPTY;
91 static int hf_wsp_parameter_name = HF_EMPTY;
92 static int hf_wsp_parameter_filename = HF_EMPTY;
93 static int hf_wsp_parameter_start = HF_EMPTY;
94 static int hf_wsp_parameter_start_info = HF_EMPTY;
95 static int hf_wsp_parameter_comment = HF_EMPTY;
96 static int hf_wsp_parameter_domain = HF_EMPTY;
97 static int hf_wsp_parameter_path = HF_EMPTY;
98 static int hf_wsp_parameter_upart_type = HF_EMPTY;
99 static int hf_wsp_parameter_upart_type_value = HF_EMPTY;
100 static int hf_wsp_reply_data = HF_EMPTY;
101 static int hf_wsp_post_data = HF_EMPTY;
102 static int hf_wsp_push_data = HF_EMPTY;
103 static int hf_wsp_multipart_data = HF_EMPTY;
104 static int hf_wsp_mpart = HF_EMPTY;
106 static int hf_wsp_header_shift_code = HF_EMPTY;
107 static int hf_wsp_header_accept = HF_EMPTY;
108 static int hf_wsp_header_accept_str = HF_EMPTY;
109 static int hf_wsp_header_accept_application = HF_EMPTY;
110 static int hf_wsp_header_accept_application_str = HF_EMPTY;
111 static int hf_wsp_header_accept_charset = HF_EMPTY;
112 static int hf_wsp_header_accept_charset_str = HF_EMPTY;
113 static int hf_wsp_header_accept_language = HF_EMPTY;
114 static int hf_wsp_header_accept_language_str = HF_EMPTY;
115 static int hf_wsp_header_accept_ranges = HF_EMPTY;
116 static int hf_wsp_header_accept_ranges_str = HF_EMPTY;
117 static int hf_wsp_header_cache_control = HF_EMPTY;
118 static int hf_wsp_header_cache_control_str = HF_EMPTY;
119 static int hf_wsp_header_cache_control_field_name = HF_EMPTY;
120 static int hf_wsp_header_connection = HF_EMPTY;
121 static int hf_wsp_header_connection_str = HF_EMPTY;
122 static int hf_wsp_header_cache_control_field_name_str = HF_EMPTY;
123 static int hf_wsp_header_content_length = HF_EMPTY;
124 static int hf_wsp_header_age = HF_EMPTY;
125 static int hf_wsp_header_bearer_indication = HF_EMPTY;
126 static int hf_wsp_header_date = HF_EMPTY;
127 static int hf_wsp_header_etag = HF_EMPTY;
128 static int hf_wsp_header_expires = HF_EMPTY;
129 static int hf_wsp_header_last_modified = HF_EMPTY;
130 static int hf_wsp_header_location = HF_EMPTY;
131 static int hf_wsp_header_if_modified_since = HF_EMPTY;
132 static int hf_wsp_header_profile = HF_EMPTY;
133 static int hf_wsp_header_pragma = HF_EMPTY;
134 static int hf_wsp_header_server = HF_EMPTY;
135 static int hf_wsp_header_user_agent = HF_EMPTY;
136 static int hf_wsp_header_warning = HF_EMPTY;
137 static int hf_wsp_header_warning_code = HF_EMPTY;
138 static int hf_wsp_header_warning_agent = HF_EMPTY;
139 static int hf_wsp_header_warning_text = HF_EMPTY;
140 static int hf_wsp_header_application_header = HF_EMPTY;
141 static int hf_wsp_header_application_value = HF_EMPTY;
142 static int hf_wsp_header_x_wap_tod = HF_EMPTY;
143 static int hf_wsp_header_content_ID = HF_EMPTY;
144 static int hf_wsp_header_transfer_encoding = HF_EMPTY;
145 static int hf_wsp_header_transfer_encoding_str = HF_EMPTY;
146 static int hf_wsp_header_via = HF_EMPTY;
147 static int hf_wsp_header_wap_application_id = HF_EMPTY;
148 static int hf_wsp_header_wap_application_id_str = HF_EMPTY;
150 static int hf_wsp_redirect_flags = HF_EMPTY;
151 static int hf_wsp_redirect_permanent = HF_EMPTY;
152 static int hf_wsp_redirect_reuse_security_session = HF_EMPTY;
153 static int hf_wsp_redirect_afl = HF_EMPTY;
154 static int hf_wsp_redirect_afl_bearer_type_included = HF_EMPTY;
155 static int hf_wsp_redirect_afl_port_number_included = HF_EMPTY;
156 static int hf_wsp_redirect_afl_address_len = HF_EMPTY;
157 static int hf_wsp_redirect_bearer_type = HF_EMPTY;
158 static int hf_wsp_redirect_port_num = HF_EMPTY;
159 static int hf_wsp_redirect_ipv4_addr = HF_EMPTY;
160 static int hf_wsp_redirect_ipv6_addr = HF_EMPTY;
161 static int hf_wsp_redirect_addr = HF_EMPTY;
163 /* Initialize the subtree pointers */
164 static gint ett_wsp = ETT_EMPTY;
165 static gint ett_content_type_parameters = ETT_EMPTY;
166 static gint ett_header = ETT_EMPTY;
167 static gint ett_headers = ETT_EMPTY;
168 static gint ett_header_warning = ETT_EMPTY;
169 static gint ett_header_cache_control_parameters = ETT_EMPTY;
170 static gint ett_header_cache_control_field_names = ETT_EMPTY;
171 static gint ett_capabilities = ETT_EMPTY;
172 static gint ett_content_type = ETT_EMPTY;
173 static gint ett_redirect_flags = ETT_EMPTY;
174 static gint ett_redirect_afl = ETT_EMPTY;
175 static gint ett_multiparts = ETT_EMPTY;
176 static gint ett_mpartlist = ETT_EMPTY;
178 /* Handle for WSP-over-UDP dissector */
179 static dissector_handle_t wsp_fromudp_handle;
181 /* Handle for WTP-over-UDP dissector */
182 static dissector_handle_t wtp_fromudp_handle;
184 /* Handle for WMLC dissector */
185 static dissector_handle_t wmlc_handle;
187 static const value_string vals_pdu_type[] = {
188 { 0x00, "Reserved" },
190 { 0x02, "ConnectReply" },
191 { 0x03, "Redirect" },
193 { 0x05, "Disconnect" },
195 { 0x07, "ConfirmedPush" },
199 /* 0x10 - 0x3F Unassigned */
207 /* 0x45 - 0x4F Unassigned (Get PDU) */
208 /* 0x50 - 0x5F Extended method (Get PDU) */
213 /* 0x62 - 0x6F Unassigned (Post PDU) */
214 /* 0x70 - 0x7F Extended method (Post PDU) */
215 /* 0x80 - 0xFF Reserved */
221 static const value_string vals_status[] = {
222 /* 0x00 - 0x0F Reserved */
224 { 0x10, "Continue" },
225 { 0x11, "Switching Protocols" },
229 { 0x22, "Accepted" },
230 { 0x23, "Non-Authoritative Information" },
231 { 0x24, "No Content" },
232 { 0x25, "Reset Content" },
233 { 0x26, "Partial Content" },
235 { 0x30, "Multiple Choices" },
236 { 0x31, "Moved Permanently" },
237 { 0x32, "Moved Temporarily" },
238 { 0x33, "See Other" },
239 { 0x34, "Not Modified" },
240 { 0x35, "Use Proxy" },
241 { 0x37, "Temporary Redirect" },
243 { 0x40, "Bad Request" },
244 { 0x41, "Unauthorised" },
245 { 0x42, "Payment Required" },
246 { 0x43, "Forbidden" },
247 { 0x44, "Not Found" },
248 { 0x45, "Method Not Allowed" },
249 { 0x46, "Not Acceptable" },
250 { 0x47, "Proxy Authentication Required" },
251 { 0x48, "Request Timeout" },
252 { 0x49, "Conflict" },
254 { 0x4B, "Length Required" },
255 { 0x4C, "Precondition Failed" },
256 { 0x4D, "Request Entity Too Large" },
257 { 0x4E, "Request-URI Too Large" },
258 { 0x4F, "Unsupported Media Type" },
259 { 0x50, "Requested Range Not Satisfiable" },
260 { 0x51, "Expectation Failed" },
262 { 0x60, "Internal Server Error" },
263 { 0x61, "Not Implemented" },
264 { 0x62, "Bad Gateway" },
265 { 0x63, "Service Unavailable" },
266 { 0x64, "Gateway Timeout" },
267 { 0x65, "HTTP Version Not Supported" },
274 #define FN_ACCEPT 0x00
275 #define FN_ACCEPT_CHARSET_DEP 0x01 /* encoding version 1.1, deprecated */
276 #define FN_ACCEPT_ENCODING_DEP 0x02 /* encoding version 1.1, deprecated */
277 #define FN_ACCEPT_LANGUAGE 0x03
278 #define FN_ACCEPT_RANGES 0x04
280 #define FN_ALLOW 0x06
281 #define FN_AUTHORIZATION 0x07
282 #define FN_CACHE_CONTROL_DEP 0x08 /* encoding version 1.1, deprecated */
283 #define FN_CONNECTION 0x09
284 #define FN_CONTENT_BASE 0x0A
285 #define FN_CONTENT_ENCODING 0x0B
286 #define FN_CONTENT_LANGUAGE 0x0C
287 #define FN_CONTENT_LENGTH 0x0D
288 #define FN_CONTENT_LOCATION 0x0E
289 #define FN_CONTENT_MD5 0x0F
290 #define FN_CONTENT_RANGE_DEP 0x10 /* encoding version 1.1, deprecated */
291 #define FN_CONTENT_TYPE 0x11
294 #define FN_EXPIRES 0x14
297 #define FN_IF_MODIFIED_SINCE 0x17
298 #define FN_IF_MATCH 0x18
299 #define FN_IF_NONE_MATCH 0x19
300 #define FN_IF_RANGE 0x1A
301 #define FN_IF_UNMODIFIED_SINCE 0x1B
302 #define FN_LOCATION 0x1C
303 #define FN_LAST_MODIFIED 0x1D
304 #define FN_MAX_FORWARDS 0x1E
305 #define FN_PRAGMA 0x1F
306 #define FN_PROXY_AUTHENTICATE 0x20
307 #define FN_PROXY_AUTHORIZATION 0x21
308 #define FN_PUBLIC 0x22
309 #define FN_RANGE 0x23
310 #define FN_REFERER 0x24
311 #define FN_RETRY_AFTER 0x25
312 #define FN_SERVER 0x26
313 #define FN_TRANSFER_ENCODING 0x27
314 #define FN_UPGRADE 0x28
315 #define FN_USER_AGENT 0x29
318 #define FN_WARNING 0x2C
319 #define FN_WWW_AUTHENTICATE 0x2D
320 #define FN_CONTENT_DISPOSITION 0x2E
321 #define FN_X_WAP_APPLICATION_ID 0x2F
322 #define FN_X_WAP_CONTENT_URI 0x30
323 #define FN_X_WAP_INITIATOR_URI 0x31
324 #define FN_ACCEPT_APPLICATION 0x32
325 #define FN_BEARER_INDICATION 0x33
326 #define FN_PUSH_FLAG 0x34
327 #define FN_PROFILE 0x35
328 #define FN_PROFILE_DIFF 0x36
329 #define FN_PROFILE_WARNING 0x37
330 #define FN_EXPECT 0x38
332 #define FN_TRAILER 0x3A
333 #define FN_ACCEPT_CHARSET 0x3B /* encoding version 1.3 */
334 #define FN_ACCEPT_ENCODING 0x3C /* encoding version 1.3 */
335 #define FN_CACHE_CONTROL 0x3D /* encoding version 1.3 */
336 #define FN_CONTENT_RANGE 0x3E /* encoding version 1.3 */
337 #define FN_X_WAP_TOD 0x3F
338 #define FN_CONTENT_ID 0x40
339 #define FN_SET_COOKIE 0x41
340 #define FN_COOKIE 0x42
341 #define FN_ENCODING_VERSION 0x43
342 #define FN_PROFILE_WARNING14 0x44 /* encoding version 1.4 */
343 #define FN_CONTENT_DISPOSITION14 0x45 /* encoding version 1.4 */
344 #define FN_X_WAP_SECURITY 0x46
345 #define FN_CACHE_CONTROL14 0x47 /* encoding version 1.4 */
347 static const value_string vals_field_names[] = {
348 { FN_ACCEPT, "Accept" },
349 { FN_ACCEPT_CHARSET_DEP, "Accept-Charset (encoding 1.1)" },
350 { FN_ACCEPT_ENCODING_DEP, "Accept-Encoding (encoding 1.1)" },
351 { FN_ACCEPT_LANGUAGE, "Accept-Language" },
352 { FN_ACCEPT_RANGES, "Accept-Ranges" },
354 { FN_ALLOW, "Allow" },
355 { FN_AUTHORIZATION, "Authorization" },
356 { FN_CACHE_CONTROL_DEP, "Cache-Control (encoding 1.1)" },
357 { FN_CONNECTION, "Connection" },
358 { FN_CONTENT_BASE, "Content-Base" },
359 { FN_CONTENT_ENCODING, "Content-Encoding" },
360 { FN_CONTENT_LANGUAGE, "Content-Language" },
361 { FN_CONTENT_LENGTH, "Content-Length" },
362 { FN_CONTENT_LOCATION, "Content-Location" },
363 { FN_CONTENT_MD5, "Content-MD5" },
364 { FN_CONTENT_RANGE_DEP, "Content-Range (encoding 1.1)" },
365 { FN_CONTENT_TYPE, "Content-Type" },
368 { FN_EXPIRES, "Expires" },
371 { FN_IF_MODIFIED_SINCE, "If-Modified-Since" },
372 { FN_IF_MATCH, "If-Match" },
373 { FN_IF_NONE_MATCH, "If-None-Match" },
374 { FN_IF_RANGE, "If-Range" },
375 { FN_IF_UNMODIFIED_SINCE, "If-Unmodified-Since" },
376 { FN_LOCATION, "Location" },
377 { FN_LAST_MODIFIED, "Last-Modified" },
378 { FN_MAX_FORWARDS, "Max-Forwards" },
379 { FN_PRAGMA, "Pragma" },
380 { FN_PROXY_AUTHENTICATE, "Proxy-Authenticate" },
381 { FN_PROXY_AUTHORIZATION, "Proxy-Authorization" },
382 { FN_PUBLIC, "Public" },
383 { FN_RANGE, "Range" },
384 { FN_REFERER, "Referer" },
385 { FN_RETRY_AFTER, "Retry-After" },
386 { FN_SERVER, "Server" },
387 { FN_TRANSFER_ENCODING, "Transfer-Encoding" },
388 { FN_UPGRADE, "Upgrade" },
389 { FN_USER_AGENT, "User-Agent" },
392 { FN_WARNING, "Warning" },
393 { FN_WWW_AUTHENTICATE, "WWW-Authenticate" },
394 { FN_CONTENT_DISPOSITION, "Content-Disposition" },
395 { FN_X_WAP_APPLICATION_ID, "X-Wap-Application-ID" },
396 { FN_X_WAP_CONTENT_URI, "X-Wap-Content-URI" },
397 { FN_X_WAP_INITIATOR_URI, "X-Wap-Initiator-URI" },
398 { FN_ACCEPT_APPLICATION, "Accept-Application" },
399 { FN_BEARER_INDICATION, "Bearer-Indication" },
400 { FN_PUSH_FLAG, "Push-Flag" },
401 { FN_PROFILE, "Profile" },
402 { FN_PROFILE_DIFF, "Profile-Diff" },
403 { FN_PROFILE_WARNING, "Profile-Warning" },
404 { FN_EXPECT, "Expect" },
406 { FN_TRAILER, "Trailer" },
407 { FN_ACCEPT_CHARSET, "Accept-Charset" },
408 { FN_ACCEPT_ENCODING, "Accept-Encoding" },
409 { FN_CACHE_CONTROL, "Cache-Control" },
410 { FN_CONTENT_RANGE, "Content-Range" },
411 { FN_X_WAP_TOD, "X-Wap-Tod" },
412 { FN_CONTENT_ID, "Content-ID" },
413 { FN_SET_COOKIE, "Set-Cookie" },
414 { FN_COOKIE, "Cookie" },
415 { FN_ENCODING_VERSION, "Encoding-Version" },
416 { FN_PROFILE_WARNING14, "Profile-Warning (encoding 1.4)" },
417 { FN_CONTENT_DISPOSITION14,"Content-Disposition (encoding 1.4)" },
418 { FN_X_WAP_SECURITY, "X-WAP-Security" },
419 { FN_CACHE_CONTROL14, "Cache-Control (encoding 1.4)" },
424 * Bearer types (from the WDP specification).
428 #define BT_GSM_USSD 0x02
429 #define BT_GSM_SMS 0x03
430 #define BT_ANSI_136_GUTS 0x04
431 #define BT_IS_95_SMS 0x05
432 #define BT_IS_95_CSD 0x06
433 #define BT_IS_95_PACKET_DATA 0x07
434 #define BT_ANSI_136_CSD 0x08
435 #define BT_ANSI_136_PACKET_DATA 0x09
436 #define BT_GSM_CSD 0x0A
437 #define BT_GSM_GPRS 0x0B
438 #define BT_GSM_USSD_IPv4 0x0C
439 #define BT_AMPS_CDPD 0x0D
440 #define BT_PDC_CSD 0x0E
441 #define BT_PDC_PACKET_DATA 0x0F
442 #define BT_IDEN_SMS 0x10
443 #define BT_IDEN_CSD 0x11
444 #define BT_IDEN_PACKET_DATA 0x12
445 #define BT_PAGING_FLEX 0x13
446 #define BT_PHS_SMS 0x14
447 #define BT_PHS_CSD 0x15
448 #define BT_GSM_USSD_GSM_SC 0x16
449 #define BT_TETRA_SDS_ITSI 0x17
450 #define BT_TETRA_SDS_MSISDN 0x18
451 #define BT_TETRA_PACKET_DATA 0x19
452 #define BT_PAGING_REFLEX 0x1A
453 #define BT_GSM_USSD_MSISDN 0x1B
454 #define BT_MOBITEX_MPAK 0x1C
455 #define BT_ANSI_136_GHOST 0x1D
457 static const value_string vals_bearer_types[] = {
460 { BT_GSM_USSD, "GSM USSD" },
461 { BT_GSM_SMS, "GSM SMS" },
462 { BT_ANSI_136_GUTS, "ANSI-136 GUTS/R-Data" },
463 { BT_IS_95_SMS, "IS-95 CDMA SMS" },
464 { BT_IS_95_CSD, "IS-95 CDMA CSD" },
465 { BT_IS_95_PACKET_DATA, "IS-95 CDMA Packet data" },
466 { BT_ANSI_136_CSD, "ANSI-136 CSD" },
467 { BT_ANSI_136_PACKET_DATA, "ANSI-136 Packet data" },
468 { BT_GSM_CSD, "GSM CSD" },
469 { BT_GSM_GPRS, "GSM GPRS" },
470 { BT_GSM_USSD_IPv4, "GSM USSD (IPv4 addresses)" },
471 { BT_AMPS_CDPD, "AMPS CDPD" },
472 { BT_PDC_CSD, "PDC CSD" },
473 { BT_PDC_PACKET_DATA, "PDC Packet data" },
474 { BT_IDEN_SMS, "IDEN SMS" },
475 { BT_IDEN_CSD, "IDEN CSD" },
476 { BT_IDEN_PACKET_DATA, "IDEN Packet data" },
477 { BT_PAGING_FLEX, "Paging network FLEX(TM)" },
478 { BT_PHS_SMS, "PHS SMS" },
479 { BT_PHS_CSD, "PHS CSD" },
480 { BT_GSM_USSD_GSM_SC, "GSM USSD (GSM Service Code addresses)" },
481 { BT_TETRA_SDS_ITSI, "TETRA SDS (ITSI addresses)" },
482 { BT_TETRA_SDS_MSISDN, "TETRA SDS (MSISDN addresses)" },
483 { BT_TETRA_PACKET_DATA, "TETRA Packet data" },
484 { BT_PAGING_REFLEX, "Paging network ReFLEX(TM)" },
485 { BT_GSM_USSD_MSISDN, "GSM USSD (MSISDN addresses)" },
486 { BT_MOBITEX_MPAK, "Mobitex MPAK" },
487 { BT_ANSI_136_GHOST, "ANSI-136 GHOST/R-Data" },
491 static const value_string vals_content_types[] = {
494 { 0x02, "text/html" },
495 { 0x03, "text/plain" },
496 { 0x04, "text/x-hdml" },
497 { 0x05, "text/x-ttml" },
498 { 0x06, "text/x-vCalendar" },
499 { 0x07, "text/x-vCard" },
500 { 0x08, "text/vnd.wap.wml" },
501 { 0x09, "text/vnd.wap.wmlscript" },
502 { 0x0A, "text/vnd.wap.channel" },
503 { 0x0B, "Multipart/*" },
504 { 0x0C, "Multipart/mixed" },
505 { 0x0D, "Multipart/form-data" },
506 { 0x0E, "Multipart/byteranges" },
507 { 0x0F, "Multipart/alternative" },
508 { 0x10, "application/*" },
509 { 0x11, "application/java-vm" },
510 { 0x12, "application/x-www-form-urlencoded" },
511 { 0x13, "application/x-hdmlc" },
512 { 0x14, "application/vnd.wap.wmlc" },
513 { 0x15, "application/vnd.wap.wmlscriptc" },
514 { 0x16, "application/vnd.wap.channelc" },
515 { 0x17, "application/vnd.wap.uaprof" },
516 { 0x18, "application/vnd.wap.wtls-ca-certificate" },
517 { 0x19, "application/vnd.wap.wtls-user-certificate" },
518 { 0x1A, "application/x-x509-ca-cert" },
519 { 0x1B, "application/x-x509-user-cert" },
521 { 0x1D, "image/gif" },
522 { 0x1E, "image/jpeg" },
523 { 0x1F, "image/tiff" },
524 { 0x20, "image/png" },
525 { 0x21, "image/vnd.wap.wbmp" },
526 { 0x22, "application/vnd.wap.multipart.*" },
527 { 0x23, "application/vnd.wap.multipart.mixed" },
528 { 0x24, "application/vnd.wap.multipart.form-data" },
529 { 0x25, "application/vnd.wap.multipart.byteranges" },
530 { 0x26, "application/vnd.wap.multipart.alternative" },
531 { 0x27, "application/xml" },
532 { 0x28, "text/xml" },
533 { 0x29, "application/vnd.wap.wbxml" },
534 { 0x2A, "application/x-x968-cross-cert" },
535 { 0x2B, "application/x-x968-ca-cert" },
536 { 0x2C, "application/x-x968-user-cert" },
537 { 0x2D, "text/vnd.wap.si" },
538 { 0x2E, "application/vnd.wap.sic" },
539 { 0x2F, "text/vnd.wap.sl" },
540 { 0x30, "application/vnd.wap.slc" },
541 { 0x31, "text/vnd.wap.co" },
542 { 0x32, "application/vnd.wap.coc" },
543 { 0x33, "application/vnd.wap.multipart.related" },
544 { 0x34, "application/vnd.wap.sia" },
545 { 0x35, "text/vnd.wap.connectivity-xml" },
546 { 0x36, "application/vnd.wap.connectivity-wbxml" },
547 { 0x37, "application/pkcs7-mime" },
548 { 0x38, "application/vnd.wap.hashed-certificate" },
549 { 0x39, "application/vnd.wap.signed-certificate" },
550 { 0x3A, "application/vnd.wap.cert-response" },
551 { 0x3B, "application/xhtml+xml" },
552 { 0x3C, "application/wml+xml" },
553 { 0x3D, "text/css" },
554 { 0x3E, "application/vnd.wap.mms-message" },
555 { 0x3F, "application/vnd.wap.rollover-certificate" },
559 static const value_string vals_languages[] = {
560 { 0x01, "Afar (aa)" },
561 { 0x02, "Abkhazian (ab)" },
562 { 0x03, "Afrikaans (af)" },
563 { 0x04, "Amharic (am)" },
564 { 0x05, "Arabic (ar)" },
565 { 0x06, "Assamese (as)" },
566 { 0x07, "Aymara (ay)" },
567 { 0x08, "Azerbaijani (az)" },
568 { 0x09, "Bashkir (ba)" },
569 { 0x0A, "Byelorussian (be)" },
570 { 0x0B, "Bulgarian (bg)" },
571 { 0x0C, "Bihari (bh)" },
572 { 0x0D, "Bislama (bi)" },
573 { 0x0E, "Bengali; Bangla (bn)" },
574 { 0x0F, "Tibetan (bo)" },
575 { 0x10, "Breton (br)" },
576 { 0x11, "Catalan (ca)" },
577 { 0x12, "Corsican (co)" },
578 { 0x13, "Czech (cs)" },
579 { 0x14, "Welsh (cy)" },
580 { 0x15, "Danish (da)" },
581 { 0x16, "German (de)" },
582 { 0x17, "Bhutani (dz)" },
583 { 0x18, "Greek (el)" },
584 { 0x19, "English (en)" },
585 { 0x1A, "Esperanto (eo)" },
586 { 0x1B, "Spanish (es)" },
587 { 0x1C, "Estonian (et)" },
588 { 0x1D, "Basque (eu)" },
589 { 0x1E, "Persian (fa)" },
590 { 0x1F, "Finnish (fi)" },
591 { 0x20, "Fiji (fj)" },
592 { 0x22, "French (fr)" },
593 { 0x24, "Irish (ga)" },
594 { 0x25, "Scots Gaelic (gd)" },
595 { 0x26, "Galician (gl)" },
596 { 0x27, "Guarani (gn)" },
597 { 0x28, "Gujarati (gu)" },
598 { 0x29, "Hausa (ha)" },
599 { 0x2A, "Hebrew (formerly iw) (he)" },
600 { 0x2B, "Hindi (hi)" },
601 { 0x2C, "Croatian (hr)" },
602 { 0x2D, "Hungarian (hu)" },
603 { 0x2E, "Armenian (hy)" },
604 { 0x30, "Indonesian (formerly in) (id)" },
605 { 0x47, "Maori (mi)" },
606 { 0x48, "Macedonian (mk)" },
607 { 0x49, "Malayalam (ml)" },
608 { 0x4A, "Mongolian (mn)" },
609 { 0x4B, "Moldavian (mo)" },
610 { 0x4C, "Marathi (mr)" },
611 { 0x4D, "Malay (ms)" },
612 { 0x4E, "Maltese (mt)" },
613 { 0x4F, "Burmese (my)" },
614 { 0x51, "Nepali (ne)" },
615 { 0x52, "Dutch (nl)" },
616 { 0x53, "Norwegian (no)" },
617 { 0x54, "Occitan (oc)" },
618 { 0x55, "(Afan) Oromo (om)" },
619 { 0x56, "Oriya (or)" },
620 { 0x57, "Punjabi (pa)" },
621 { 0x58, "Polish (po)" },
622 { 0x59, "Pashto, Pushto (ps)" },
623 { 0x5A, "Portuguese (pt)" },
624 { 0x5B, "Quechua (qu)" },
625 { 0x5D, "Kirundi (rn)" },
626 { 0x5E, "Romanian (ro)" },
627 { 0x5F, "Russian (ru)" },
628 { 0x60, "Kinyarwanda (rw)" },
629 { 0x61, "Sanskrit (sa)" },
630 { 0x62, "Sindhi (sd)" },
631 { 0x63, "Sangho (sg)" },
632 { 0x64, "Serbo-Croatian (sh)" },
633 { 0x65, "Sinhalese (si)" },
634 { 0x66, "Slovak (sk)" },
635 { 0x67, "Slovenian (sl)" },
636 { 0x68, "Samoan (sm)" },
637 { 0x69, "Shona (sn)" },
638 { 0x6A, "Somali (so)" },
639 { 0x6B, "Albanian (sq)" },
640 { 0x6C, "Serbian (sr)" },
641 { 0x6D, "Siswati (ss)" },
642 { 0x6E, "Sesotho (st)" },
643 { 0x6F, "Sundanese (su)" },
644 { 0x70, "Swedish (sv)" },
645 { 0x71, "Swahili (sw)" },
646 { 0x72, "Tamil (ta)" },
647 { 0x73, "Telugu (te)" },
648 { 0x74, "Tajik (tg)" },
649 { 0x75, "Thai (th)" },
650 { 0x76, "Tigrinya (ti)" },
651 { 0x81, "Nauru (na)" },
652 { 0x82, "Faeroese (fo)" },
653 { 0x83, "Frisian (fy)" },
654 { 0x84, "Interlingua (ia)" },
655 { 0x8C, "Rhaeto-Romance (rm)" },
659 static const value_string vals_accept_ranges[] = {
665 #define NO_CACHE 0x00
666 #define NO_STORE 0x01
668 #define MAX_STALE 0x03
669 #define MIN_FRESH 0x04
670 #define ONLY_IF_CACHED 0x05
673 #define NO_TRANSFORM 0x08
674 #define MUST_REVALIDATE 0x09
675 #define PROXY_REVALIDATE 0x0A
676 #define S_MAXAGE 0x0B
678 static const value_string vals_cache_control[] = {
679 { NO_CACHE, "No-cache" },
680 { NO_STORE, "No-store" },
681 { MAX_AGE, "Max-age" },
682 { MAX_STALE, "Max-stale" },
683 { MIN_FRESH, "Min-fresh" },
684 { ONLY_IF_CACHED, "Only-if-cached" },
685 { PUBLIC, "Public" },
686 { PRIVATE, "Private" },
687 { NO_TRANSFORM, "No-transform" },
688 { MUST_REVALIDATE, "Must-revalidate" },
689 { PROXY_REVALIDATE, "Proxy-revalidate" },
690 { S_MAXAGE, "S-max-age" },
694 static const value_string vals_connection[] = {
699 static const value_string vals_transfer_encoding[] = {
707 #define PERMANENT_REDIRECT 0x80
708 #define REUSE_SECURITY_SESSION 0x40
711 * Redirect address flags and length.
713 #define BEARER_TYPE_INCLUDED 0x80
714 #define PORT_NUMBER_INCLUDED 0x40
715 #define ADDRESS_LEN 0x3f
717 static const true_false_string yes_no_truth = {
723 * Windows appears to define DELETE.
733 REDIRECT = 0x03, /* No sample data */
736 PUSH = 0x06, /* No sample data */
737 CONFIRMEDPUSH = 0x07, /* No sample data */
738 SUSPEND = 0x08, /* No sample data */
739 RESUME = 0x09, /* No sample data */
742 OPTIONS = 0x41, /* No sample data */
743 HEAD = 0x42, /* No sample data */
744 DELETE = 0x43, /* No sample data */
745 TRACE = 0x44, /* No sample data */
748 PUT = 0x61, /* No sample data */
753 VALUE_IS_TEXT_STRING,
757 static dissector_table_t wsp_dissector_table;
758 static heur_dissector_list_t heur_subdissector_list;
760 static void add_uri (proto_tree *, packet_info *, tvbuff_t *, guint, guint);
761 static void add_headers (proto_tree *, tvbuff_t *);
762 static int add_well_known_header (proto_tree *, tvbuff_t *, int, guint8);
763 static int add_unknown_header (proto_tree *, tvbuff_t *, int, guint8);
764 static int add_application_header (proto_tree *, tvbuff_t *, int);
765 static void add_accept_header (proto_tree *, tvbuff_t *, int,
766 tvbuff_t *, value_type_t, int);
767 static void add_accept_xxx_header (proto_tree *, tvbuff_t *, int,
768 tvbuff_t *, value_type_t, int, int, int, const value_string *,
770 static void add_accept_ranges_header (proto_tree *, tvbuff_t *, int,
771 tvbuff_t *, value_type_t, int);
772 static void add_cache_control_header (proto_tree *, tvbuff_t *, int,
773 tvbuff_t *, value_type_t, int);
774 static int add_cache_control_field_name (proto_tree *, tvbuff_t *, int, guint);
775 static void add_connection_header (proto_tree *, tvbuff_t *, int,
776 tvbuff_t *, value_type_t, int);
777 static void add_content_type_value (proto_tree *, tvbuff_t *, int, int,
778 tvbuff_t *, value_type_t, int, int, int, guint *, const char **);
779 static void add_wap_application_id_header (proto_tree *, tvbuff_t *, int,
780 tvbuff_t *, value_type_t, int);
781 static void add_integer_value_header (proto_tree *, tvbuff_t *, int,
782 tvbuff_t *, value_type_t, int, int, guint8);
783 static void add_string_value_header (proto_tree *, tvbuff_t *, int,
784 tvbuff_t *, value_type_t, int, int, guint8);
785 static void add_quoted_string_value_header (proto_tree *, tvbuff_t *, int,
786 tvbuff_t *, value_type_t, int, int, guint8);
787 static void add_date_value_header (proto_tree *, tvbuff_t *, int,
788 tvbuff_t *, value_type_t, int, int, guint8);
789 static int add_parameter (proto_tree *, tvbuff_t *, int);
790 static int add_untyped_parameter (proto_tree *, tvbuff_t *, int, int);
791 static int add_parameter_charset (proto_tree *, tvbuff_t *, int, int);
792 static int add_constrained_encoding (proto_tree *, tvbuff_t *, int, int);
793 static int add_parameter_type (proto_tree *, tvbuff_t *, int, int);
794 static int add_parameter_text (proto_tree *, tvbuff_t *, int, int, int, const char *);
795 static void add_post_data (proto_tree *, tvbuff_t *, guint, const char *);
796 static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
797 static void add_pragma_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
799 static void add_transfer_encoding_header (proto_tree *, tvbuff_t *, int,
800 tvbuff_t *, value_type_t, int);
801 static void add_warning_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
803 static void add_accept_application_header (proto_tree *, tvbuff_t *, int,
804 tvbuff_t *, value_type_t, int);
805 static void add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type);
806 static void add_capability_vals(tvbuff_t *, gboolean, int, guint, guint, char *, size_t);
807 static value_type_t get_value_type_len (tvbuff_t *, int, guint *, int *, int *);
808 static guint get_uintvar (tvbuff_t *, guint, guint);
809 static gint get_integer (tvbuff_t *, guint, guint, value_type_t, guint *);
811 /* Code to actually dissect the packets */
813 dissect_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
814 proto_tree *tree, dissector_handle_t dissector_handle)
818 proto_tree *flags_tree;
820 guint8 address_flags_len;
822 proto_tree *atf_tree;
824 guint32 address_ipv4;
825 struct e_in6_addr address_ipv6;
826 address redir_address;
827 conversation_t *conv;
829 flags = tvb_get_guint8 (tvb, offset);
831 ti = proto_tree_add_uint (tree, hf_wsp_redirect_flags,
832 tvb, offset, 1, flags);
833 flags_tree = proto_item_add_subtree (ti, ett_redirect_flags);
834 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_permanent,
835 tvb, offset, 1, flags);
836 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_reuse_security_session,
837 tvb, offset, 1, flags);
840 while (tvb_reported_length_remaining (tvb, offset) > 0) {
841 address_flags_len = tvb_get_guint8 (tvb, offset);
843 ti = proto_tree_add_uint (tree, hf_wsp_redirect_afl,
844 tvb, offset, 1, address_flags_len);
845 atf_tree = proto_item_add_subtree (ti, ett_redirect_afl);
846 proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_bearer_type_included,
847 tvb, offset, 1, address_flags_len);
848 proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_port_number_included,
849 tvb, offset, 1, address_flags_len);
850 proto_tree_add_uint (atf_tree, hf_wsp_redirect_afl_address_len,
851 tvb, offset, 1, address_flags_len);
854 if (address_flags_len & BEARER_TYPE_INCLUDED) {
855 bearer_type = tvb_get_guint8 (tvb, offset);
857 proto_tree_add_uint (tree, hf_wsp_redirect_bearer_type,
858 tvb, offset, 1, bearer_type);
862 bearer_type = 0x00; /* XXX */
863 if (address_flags_len & PORT_NUMBER_INCLUDED) {
864 port_num = tvb_get_ntohs (tvb, offset);
866 proto_tree_add_uint (tree, hf_wsp_redirect_port_num,
867 tvb, offset, 2, port_num);
872 * Redirecting to the same server port number as was
873 * being used, i.e. the source port number of this
876 port_num = pinfo->srcport;
878 address_len = address_flags_len & ADDRESS_LEN;
879 if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
881 * We don't have the bearer type in the message,
882 * so we don't know the address type.
883 * (It's the same bearer type as the original
886 goto unknown_address_type;
890 * We know the bearer type, so we know the address type.
892 switch (bearer_type) {
896 case BT_IS_95_PACKET_DATA:
897 case BT_ANSI_136_CSD:
898 case BT_ANSI_136_PACKET_DATA:
901 case BT_GSM_USSD_IPv4:
904 case BT_PDC_PACKET_DATA:
906 case BT_IDEN_PACKET_DATA:
908 case BT_TETRA_PACKET_DATA:
912 if (address_len != 4) {
916 goto unknown_address_type;
918 tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
920 proto_tree_add_ipv4 (tree,
921 hf_wsp_redirect_ipv4_addr,
922 tvb, offset, 4, address_ipv4);
926 * Create a conversation so that the
927 * redirected session will be dissected
930 redir_address.type = AT_IPv4;
931 redir_address.len = 4;
932 redir_address.data = (const guint8 *)&address_ipv4;
933 conv = find_conversation(&redir_address, &pinfo->dst,
934 PT_UDP, port_num, 0, NO_PORT_B);
936 conv = conversation_new(&redir_address,
937 &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
939 conversation_set_dissector(conv, dissector_handle);
946 if (address_len != 16) {
950 goto unknown_address_type;
952 tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
954 proto_tree_add_ipv6 (tree,
955 hf_wsp_redirect_ipv6_addr,
956 tvb, offset, 16, (guint8 *)&address_ipv6);
960 * Create a conversation so that the
961 * redirected session will be dissected
964 redir_address.type = AT_IPv6;
965 redir_address.len = 16;
966 redir_address.data = (const guint8 *)&address_ipv4;
967 conv = find_conversation(&redir_address, &pinfo->dst,
968 PT_UDP, port_num, 0, NO_PORT_B);
970 conv = conversation_new(&redir_address,
971 &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
973 conversation_set_dissector(conv, dissector_handle);
976 unknown_address_type:
978 if (address_len != 0) {
980 proto_tree_add_item (tree,
981 hf_wsp_redirect_addr,
982 tvb, offset, address_len,
988 offset += address_len;
993 dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
994 dissector_handle_t dissector_handle, gboolean is_connectionless)
1001 guint uriLength = 0;
1003 guint capabilityLength = 0;
1004 guint capabilityStart = 0;
1005 guint headersLength = 0;
1006 guint headerLength = 0;
1007 guint headerStart = 0;
1008 guint nextOffset = 0;
1009 guint contentTypeStart = 0;
1010 guint contentType = 0;
1011 const char *contentTypeStr;
1014 /* Set up structures we will need to add the protocol subtree and manage it */
1016 proto_tree *wsp_tree = NULL;
1017 /* proto_tree *wsp_header_fixed; */
1019 /* This field shows up as the "Info" column in the display; you should make
1020 it, if possible, summarize what's in the packet, so that a user looking
1021 at the list of packets can tell what type of packet it is. */
1023 /* Connection-less mode has a TID first */
1024 if (is_connectionless)
1029 /* Find the PDU type */
1030 pdut = tvb_get_guint8 (tvb, offset);
1032 /* Develop the string to put in the Info column */
1033 if (check_col(pinfo->cinfo, COL_INFO))
1035 col_append_fstr(pinfo->cinfo, COL_INFO, "WSP %s",
1036 val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"));
1039 /* In the interest of speed, if "tree" is NULL, don't do any work not
1040 necessary to generate protocol tree items. */
1042 ti = proto_tree_add_item(tree, proto_wsp, tvb, 0,
1043 tvb_length(tvb), bo_little_endian);
1044 wsp_tree = proto_item_add_subtree(ti, ett_wsp);
1046 /* Code to process the packet goes here */
1048 wsp_header_fixed = proto_item_add_subtree(ti, ett_header );
1051 /* Add common items: only TID and PDU Type */
1053 /* If this is connectionless, then the TID Field is always first */
1054 if (is_connectionless)
1056 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,tvb,
1057 0,1,bo_little_endian);
1060 ti = proto_tree_add_item(
1061 wsp_tree, /* tree */
1062 hf_wsp_header_pdu_type, /* id */
1064 offset, /* start of high light */
1065 1, /* length of high light */
1066 bo_little_endian /* value */
1077 if (pdut == CONNECT)
1079 ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,tvb,offset,1,bo_little_endian);
1080 ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,tvb,offset,1,bo_little_endian);
1083 count = 0; /* Initialise count */
1084 value = tvb_get_guintvar (tvb, offset, &count);
1085 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1088 capabilityStart = offset;
1089 count = 0; /* Initialise count */
1090 capabilityLength = tvb_get_guintvar (tvb, offset, &count);
1092 ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,tvb,capabilityStart,count,capabilityLength);
1096 count = 0; /* Initialise count */
1097 headerLength = tvb_get_guintvar (tvb, offset, &count);
1098 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headerLength);
1100 capabilityStart = offset;
1101 headerStart = capabilityStart + capabilityLength;
1103 /* Resume computes the headerlength by remaining bytes */
1104 capabilityStart = offset;
1105 headerStart = capabilityStart + capabilityLength;
1106 headerLength = tvb_reported_length_remaining (tvb, headerStart);
1108 if (capabilityLength > 0)
1110 tmp_tvb = tvb_new_subset (tvb, offset, capabilityLength, capabilityLength);
1111 add_capabilities (wsp_tree, tmp_tvb, pdut);
1112 offset += capabilityLength;
1115 if (headerLength > 0)
1117 tmp_tvb = tvb_new_subset (tvb, offset, headerLength, headerLength);
1118 add_headers (wsp_tree, tmp_tvb);
1125 dissect_redirect(tvb, offset, pinfo, wsp_tree,
1132 count = 0; /* Initialise count */
1133 value = tvb_get_guintvar (tvb, offset, &count);
1134 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1139 count = 0; /* Initialise count */
1140 /* Length of URI and size of URILen field */
1141 value = tvb_get_guintvar (tvb, offset, &count);
1142 nextOffset = offset + count;
1143 add_uri (wsp_tree, pinfo, tvb, offset, nextOffset);
1145 offset += (value+count); /* VERIFY */
1146 tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
1147 add_headers (wsp_tree, tmp_tvb);
1153 count = 0; /* Initialise count */
1154 uriLength = tvb_get_guintvar (tvb, offset, &count);
1155 headerStart = uriStart+count;
1156 count = 0; /* Initialise count */
1157 headersLength = tvb_get_guintvar (tvb, headerStart, &count);
1158 offset = headerStart + count;
1160 add_uri (wsp_tree, pinfo, tvb, uriStart, offset);
1162 offset += uriLength;
1164 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,headersLength);
1166 if (headersLength == 0)
1169 contentTypeStart = offset;
1170 nextOffset = add_content_type (wsp_tree,
1171 tvb, offset, &contentType,
1174 /* Add headers subtree that will hold the headers fields */
1175 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1176 headerLength = headersLength-(nextOffset-contentTypeStart);
1177 if (headerLength > 0)
1179 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1180 add_headers (wsp_tree, tmp_tvb);
1183 /* TODO: Post DATA */
1184 /* Runs from start of headers+headerLength to end of frame */
1185 offset = nextOffset+headerLength;
1186 tmp_tvb = tvb_new_subset (tvb, offset, tvb_reported_length (tvb)-offset, tvb_reported_length (tvb)-offset);
1187 add_post_data (wsp_tree, tmp_tvb,
1188 contentType, contentTypeStr);
1190 if (tvb_reported_length_remaining(tvb, headerStart + count + uriLength + headersLength) > 0)
1192 tmp_tvb = tvb_new_subset (tvb, headerStart + count + uriLength + headersLength, -1, -1);
1193 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1194 dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
1199 count = 0; /* Initialise count */
1200 headersLength = tvb_get_guintvar (tvb, offset+1, &count);
1201 headerStart = offset + count + 1;
1203 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
1204 nextOffset = offset + 1 + count;
1205 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset+1,count,headersLength);
1207 if (headersLength == 0)
1210 contentTypeStart = nextOffset;
1211 nextOffset = add_content_type (wsp_tree,
1212 tvb, nextOffset, &contentType,
1215 /* Add headers subtree that will hold the headers fields */
1216 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1217 headerLength = headersLength-(nextOffset-contentTypeStart);
1218 if (headerLength > 0)
1220 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1221 add_headers (wsp_tree, tmp_tvb);
1223 offset += count+headersLength+1;
1225 /* TODO: Data - decode WMLC */
1226 /* Runs from offset+1+count+headerLength+1 to end of frame */
1227 if (tvb_reported_length_remaining (tvb, offset) > 0)
1229 ti = proto_tree_add_item (wsp_tree, hf_wsp_reply_data,tvb,offset,tvb_length_remaining(tvb, offset),bo_little_endian);
1232 if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1234 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1235 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1236 dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
1242 count = 0; /* Initialise count */
1243 headersLength = tvb_get_guintvar (tvb, offset, &count);
1244 headerStart = offset + count;
1247 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headersLength);
1249 if (headersLength == 0)
1253 contentTypeStart = offset;
1254 nextOffset = add_content_type (wsp_tree,
1255 tvb, offset, &contentType,
1258 /* Add headers subtree that will hold the headers fields */
1259 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1260 headerLength = headersLength-(nextOffset-contentTypeStart);
1261 if (headerLength > 0)
1263 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1264 add_headers (wsp_tree, tmp_tvb);
1266 offset += headersLength;
1269 if (tvb_reported_length_remaining (tvb, offset) > 0)
1271 ti = proto_tree_add_item (wsp_tree, hf_wsp_push_data,tvb,offset,tvb_length_remaining(tvb, offset),bo_little_endian);
1274 if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1276 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1277 if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
1278 dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
1286 * Called directly from UDP.
1287 * Put "WSP" into the "Protocol" column.
1290 dissect_wsp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1292 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1293 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSP" );
1294 if (check_col(pinfo->cinfo, COL_INFO))
1295 col_clear(pinfo->cinfo, COL_INFO);
1297 dissect_wsp_common(tvb, pinfo, tree, wsp_fromudp_handle, TRUE);
1301 * Called from a higher-level WAP dissector, in connection-oriented mode.
1302 * Leave the "Protocol" column alone - the dissector calling us should
1306 dissect_wsp_fromwap_co(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1309 * XXX - what about WTLS->WTP->WSP?
1311 dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, FALSE);
1315 * Called from a higher-level WAP dissector, in connectionless mode.
1316 * Leave the "Protocol" column alone - the dissector calling us should
1320 dissect_wsp_fromwap_cl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1323 * XXX - what about WTLS->WSP?
1325 if (check_col(pinfo->cinfo, COL_INFO))
1327 col_clear(pinfo->cinfo, COL_INFO);
1329 dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, TRUE);
1333 add_uri (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint URILenOffset, guint URIOffset)
1339 guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
1342 ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,tvb,URILenOffset,count,uriLen);
1344 newBuffer = g_malloc (uriLen+2);
1345 newBuffer[0] = ' '; /* This is for COL_INFO */
1346 strncpy (newBuffer+1, tvb_get_ptr (tvb, URIOffset, uriLen), uriLen);
1347 newBuffer[uriLen+1] = 0;
1349 ti = proto_tree_add_string (tree, hf_wsp_header_uri,tvb,URIOffset,uriLen,newBuffer+1);
1350 if (check_col(pinfo->cinfo, COL_INFO)) {
1351 col_append_str(pinfo->cinfo, COL_INFO, newBuffer);
1357 add_headers (proto_tree *tree, tvbuff_t *tvb)
1360 proto_tree *wsp_headers;
1362 guint headersLen = tvb_reported_length (tvb);
1363 guint headerStart = 0;
1368 fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, headersLen);
1372 if (headersLen <= 0)
1378 fprintf (stderr, "dissect_wsp: Headers to process\n");
1381 ti = proto_tree_add_item (tree, hf_wsp_headers_section,tvb,offset,headersLen,bo_little_endian);
1382 wsp_headers = proto_item_add_subtree( ti, ett_headers );
1386 while (offset < headersLen)
1388 /* Loop round each header */
1389 headerStart = offset;
1390 peek = tvb_get_guint8 (tvb, headerStart);
1392 if (peek < 32) /* Short-cut shift delimiter */
1395 proto_tree_add_uint (wsp_headers,
1396 hf_wsp_header_shift_code, tvb, offset, 1,
1401 else if (peek == 0x7F) /* Shift delimiter */
1403 pageCode = tvb_get_guint8(tvb, offset+1);
1404 proto_tree_add_uint (wsp_headers,
1405 hf_wsp_header_shift_code, tvb, offset, 2,
1410 else if (peek < 127)
1413 fprintf (stderr, "dissect_wsp: header: application-header start %d (0x%02X)\n", peek, peek);
1416 * Token-text, followed by Application-specific-value.
1418 offset = add_application_header (wsp_headers, tvb,
1421 else if (peek & 0x80)
1424 fprintf (stderr, "dissect_wsp: header: well-known %d (0x%02X)\n", peek, peek);
1427 * Well-known-header; the lower 7 bits of "peek"
1428 * are the header code.
1432 offset = add_well_known_header (wsp_headers,
1433 tvb, headerStart, peek & 0x7F);
1437 offset = add_unknown_header (wsp_headers,
1438 tvb, headerStart, peek & 0x7F);
1445 add_well_known_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1449 value_type_t valueType;
1453 tvbuff_t *header_buff;
1454 tvbuff_t *value_buff;
1457 fprintf (stderr, "dissect_wsp: Got header 0x%02x\n", headerType);
1459 headerStart = offset;
1462 * Skip the Short-Integer header type.
1467 * Get the value type and length (or, if the type is VALUE_IN_LEN,
1468 * meaning the value is a Short-integer, get the value type
1469 * and the value itself).
1471 valueType = get_value_type_len (tvb, offset, &valueLen,
1472 &valueStart, &offset);
1473 headerLen = offset - headerStart;
1476 * Get a tvbuff for the entire header.
1477 * XXX - cut the actual length short so that it doesn't run
1478 * past the actual length of tvb.
1480 header_buff = tvb_new_subset (tvb, headerStart, headerLen,
1484 * If the value wasn't in the length, get a tvbuff for the value.
1485 * XXX - can valueLen be 0?
1486 * XXX - cut the actual length short so that it doesn't run
1487 * past the actual length of tvb.
1489 if (valueType != VALUE_IN_LEN) {
1490 value_buff = tvb_new_subset (tvb, valueStart, valueLen,
1494 * XXX - when the last dissector is tvbuffified,
1495 * so that NULL is no longer a valid tvb pointer
1496 * value in "proto_tree_add" calls, just
1497 * set "value_buff" to NULL.
1499 * XXX - can we already do that? I.e., will that
1500 * cause us always to crash if we mistakenly try
1501 * to fetch the value of a VALUE_IN_LEN item?
1503 value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
1506 switch (headerType) {
1508 case FN_ACCEPT: /* Accept */
1509 add_accept_header (tree, header_buff, headerLen,
1510 value_buff, valueType, valueLen);
1513 case FN_ACCEPT_CHARSET_DEP: /* Accept-Charset */
1515 * XXX - should both encoding versions 1.1 and
1516 * 1.3 be handled this way?
1518 add_accept_xxx_header (tree, header_buff, headerLen,
1519 value_buff, valueType, valueLen,
1520 hf_wsp_header_accept_charset,
1521 hf_wsp_header_accept_charset_str,
1522 vals_character_sets, "Unknown charset (%u)");
1525 case FN_ACCEPT_LANGUAGE: /* Accept-Language */
1526 add_accept_xxx_header (tree, header_buff, headerLen,
1527 value_buff, valueType, valueLen,
1528 hf_wsp_header_accept_language,
1529 hf_wsp_header_accept_language_str,
1530 vals_languages, "Unknown language (%u)");
1533 case FN_ACCEPT_RANGES: /* Accept-Ranges */
1534 add_accept_ranges_header (tree, header_buff, headerLen,
1535 value_buff, valueType, valueLen);
1538 case FN_AGE: /* Age */
1539 add_integer_value_header (tree, header_buff, headerLen,
1540 value_buff, valueType, valueLen, hf_wsp_header_age,
1544 case FN_CACHE_CONTROL_DEP: /* Cache-Control */
1545 case FN_CACHE_CONTROL:
1546 case FN_CACHE_CONTROL14:
1548 * XXX - is the only difference in the three different
1549 * versions (1.1, 1.3, 1.4) really only S_MAXAGE?
1551 add_cache_control_header (tree, header_buff, headerLen,
1552 value_buff, valueType, valueLen);
1555 case FN_CONNECTION: /* Connection */
1556 add_connection_header (tree, header_buff, headerLen,
1557 value_buff, valueType, valueLen);
1560 case FN_CONTENT_LENGTH: /* Content-Length */
1561 add_integer_value_header (tree, header_buff, headerLen,
1562 value_buff, valueType, valueLen,
1563 hf_wsp_header_content_length,
1567 case FN_DATE: /* Date */
1568 add_date_value_header (tree, header_buff, headerLen,
1569 value_buff, valueType, valueLen,
1570 hf_wsp_header_date, headerType);
1573 case FN_ETAG: /* Etag */
1574 add_string_value_header (tree, header_buff, headerLen,
1575 value_buff, valueType, valueLen,
1576 hf_wsp_header_etag, headerType);
1579 case FN_EXPIRES: /* Expires */
1580 add_date_value_header (tree, header_buff, headerLen,
1581 value_buff, valueType, valueLen,
1582 hf_wsp_header_expires, headerType);
1585 case FN_IF_MODIFIED_SINCE: /* If-Modified-Since */
1586 add_date_value_header (tree, header_buff, headerLen,
1587 value_buff, valueType, valueLen,
1588 hf_wsp_header_if_modified_since, headerType);
1591 case FN_LOCATION: /* Location */
1592 add_string_value_header (tree, header_buff, headerLen,
1593 value_buff, valueType, valueLen,
1594 hf_wsp_header_location, headerType);
1597 case FN_LAST_MODIFIED: /* Last-Modified */
1598 add_date_value_header (tree, header_buff, headerLen,
1599 value_buff, valueType, valueLen,
1600 hf_wsp_header_last_modified, headerType);
1603 case FN_PRAGMA: /* Pragma */
1604 add_pragma_header (tree, header_buff, headerLen,
1605 value_buff, valueType, valueLen);
1608 case FN_SERVER: /* Server */
1609 add_string_value_header (tree, header_buff, headerLen,
1610 value_buff, valueType, valueLen,
1611 hf_wsp_header_server, headerType);
1614 case FN_TRANSFER_ENCODING: /* Transfer-Encoding */
1615 add_transfer_encoding_header (tree, header_buff, headerLen,
1616 value_buff, valueType, valueLen);
1619 case FN_USER_AGENT: /* User-Agent */
1620 add_string_value_header (tree, header_buff, headerLen,
1621 value_buff, valueType, valueLen,
1622 hf_wsp_header_user_agent, headerType);
1625 case FN_VIA: /* Via */
1626 add_string_value_header (tree, header_buff, headerLen,
1627 value_buff, valueType, valueLen,
1628 hf_wsp_header_via, headerType);
1631 case FN_WARNING: /* Warning */
1632 add_warning_header (tree, header_buff, headerLen,
1633 value_buff, valueType, valueLen);
1636 case FN_ACCEPT_APPLICATION: /* Accept-Application */
1637 add_accept_application_header (tree, header_buff, headerLen,
1638 value_buff, valueType, valueLen);
1641 case FN_BEARER_INDICATION: /* Bearer-Indication */
1642 add_integer_value_header (tree, header_buff, headerLen,
1643 value_buff, valueType, valueLen,
1644 hf_wsp_header_bearer_indication, headerType);
1647 case FN_PROFILE: /* Profile */
1648 add_string_value_header (tree, header_buff, headerLen,
1649 value_buff, valueType, valueLen,
1650 hf_wsp_header_profile, headerType);
1653 case FN_X_WAP_APPLICATION_ID: /* X-Wap-Application-Id */
1654 add_wap_application_id_header (tree, header_buff, headerLen,
1655 value_buff, valueType, valueLen);
1658 case FN_CONTENT_ID: /* Content-ID */
1659 add_quoted_string_value_header (tree, header_buff, headerLen,
1660 value_buff, valueType, valueLen,
1661 hf_wsp_header_content_ID, headerType);
1665 proto_tree_add_text (tree, header_buff, 0, headerLen,
1666 "Unsupported Header: %s",
1667 val_to_str (headerType, vals_field_names, "Unknown (0x%02X)"));
1674 add_unknown_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1679 value_type_t valueType;
1684 headerStart = offset;
1687 * Skip the Short-Integer header type.
1691 valueStart = offset;
1694 * Get the value type and length (or, if the type is VALUE_IN_LEN,
1695 * meaning the value is a Short-integer, get the value type
1696 * and the value itself).
1698 valueType = get_value_type_len (tvb, valueStart, &valueLen,
1699 &valueOffset, &offset);
1700 headerLen = offset - headerStart;
1702 proto_tree_add_text (tree, tvb, headerStart, headerLen,
1703 "Unsupported Header (0x%02X)", headerType);
1708 add_application_header (proto_tree *tree, tvbuff_t *tvb, int offset)
1712 const guint8 *token;
1713 value_type_t valueType;
1721 startOffset = offset;
1722 tokenSize = tvb_strsize (tvb, startOffset);
1723 token = tvb_get_ptr (tvb, startOffset, tokenSize);
1724 offset += tokenSize;
1727 * Special case header "X-WAP.TOD" that is sometimes followed
1728 * by a 4-byte date value.
1730 * XXX - according to the 4-May-2000 WSP spec, X-Wap-Tod is
1731 * encoded as a well known header, with a code of 0x3F.
1733 if (tokenSize == 10 && strncasecmp ("x-wap.tod", token, 9) == 0)
1735 valueType = get_value_type_len (tvb, offset,
1736 &subvalueLen, &subvalueOffset, &offset);
1737 if (get_integer (tvb, subvalueOffset, subvalueLen,
1738 valueType, &secs) == 0)
1741 * Fill in the "struct timeval", and add it to the
1743 * Note: this will succeed even if it's a Short-integer.
1744 * A Short-integer would work, but, as the time values
1745 * are UNIX seconds-since-the-Epoch value, and as
1746 * there weren't WAP phones or Web servers back in
1747 * late 1969/early 1970, they're unlikely to be used.
1749 timeValue.secs = secs;
1750 timeValue.nsecs = 0;
1751 proto_tree_add_time (tree, hf_wsp_header_x_wap_tod,
1752 tvb, startOffset, offset - startOffset, &timeValue);
1756 proto_tree_add_text (tree, tvb, startOffset,
1757 offset - startOffset,
1758 "%s: invalid date value", token);
1764 stringSize = tvb_strsize (tvb, asvOffset);
1765 offset += stringSize;
1766 proto_tree_add_text (tree, tvb, startOffset,
1767 offset - startOffset,
1769 tvb_get_ptr (tvb, asvOffset, stringSize));
1775 add_accept_header (proto_tree *tree, tvbuff_t *header_buff,
1776 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1780 const char *contentTypeStr;
1782 add_content_type_value (tree, header_buff, 0, headerLen, value_buff,
1783 valueType, valueLen, hf_wsp_header_accept,
1784 hf_wsp_header_accept_str, &contentType, &contentTypeStr);
1788 add_accept_xxx_header (proto_tree *tree, tvbuff_t *header_buff,
1789 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1790 int valueLen, int hf_numeric, int hf_string,
1791 const value_string *vals, const char *unknown_tag)
1797 char valString[100];
1798 const char *valMatch;
1800 double q_value = 1.0;
1802 if (valueType == VALUE_IN_LEN)
1805 * Constrained-{charset,language} (Short-Integer).
1807 proto_tree_add_uint (tree, hf_numeric,
1808 header_buff, 0, headerLen,
1809 valueLen); /* valueLen is the value */
1812 if (valueType == VALUE_IS_TEXT_STRING)
1815 * Constrained-{charset,language} (text, i.e.
1818 proto_tree_add_string (tree, hf_string,
1819 header_buff, 0, headerLen,
1820 tvb_get_ptr (value_buff, 0, valueLen));
1825 * First byte had the 8th bit set.
1827 if (valueLen == 0) {
1829 * Any-{charset,language}.
1831 proto_tree_add_string (tree, hf_string,
1832 header_buff, 0, headerLen,
1838 * Accept-{charset,language}-general-form; Value-length, followed
1839 * by Well-known-{charset,language} or {Token-text,Text-string},
1840 * possibly followed by a Q-value.
1844 valueType = get_value_type_len (value_buff, 0, &subvalueLen,
1845 &subvalueOffset, &offset);
1846 if (valueType == VALUE_IS_TEXT_STRING)
1849 * {Token-text,Text-string}.
1852 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
1853 proto_tree_add_string (tree, hf_string,
1854 value_buff, 0, valueLen, valMatch);
1857 * Well-known-{charset,langugage}; starts with an
1860 if (get_integer (value_buff, subvalueOffset, subvalueLen,
1861 valueType, &value) < 0)
1863 valMatch = "Invalid integer";
1867 valMatch = val_to_str(value, vals, unknown_tag);
1871 /* Any remaining data relates to Q-value */
1872 if (offset < valueLen)
1874 peek = tvb_get_guintvar (value_buff, offset, NULL);
1876 peek = (peek - 1) * 10;
1881 q_value = peek/1000.0;
1884 /* Build string including Q-value if present */
1885 if (q_value == 1.0) /* Default */
1887 snprintf (valString, 100, "%s", valMatch);
1891 snprintf (valString, 100, "%s; Q=%5.3f", valMatch, q_value);
1893 /* Add string to tree */
1894 proto_tree_add_string (tree, hf_string,
1895 header_buff, 0, headerLen, valString);
1899 add_accept_ranges_header (proto_tree *tree, tvbuff_t *header_buff,
1900 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1903 if (valueType == VALUE_IN_LEN)
1906 * Must be 0 (None) or 1 (Bytes) (the 8th bit was stripped
1909 proto_tree_add_uint (tree, hf_wsp_header_accept_ranges,
1910 header_buff, 0, headerLen,
1911 valueLen); /* valueLen is the value */
1914 if (valueType == VALUE_IS_TEXT_STRING)
1919 proto_tree_add_string (tree, hf_wsp_header_accept_ranges_str,
1920 header_buff, 0, headerLen,
1921 tvb_get_ptr (value_buff, 0, valueLen));
1928 fprintf(stderr, "dissect_wsp: Accept-Ranges is neither None, Bytes, nor Token-text\n");
1933 add_cache_control_header (proto_tree *tree, tvbuff_t *header_buff,
1934 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1942 proto_tree *parameter_tree;
1943 proto_tree *field_names_tree;
1946 if (valueType == VALUE_IN_LEN)
1949 * No-cache, No-store, Max-age, Max-stale, Min-fresh,
1950 * Only-if-cached, Public, Private, No-transform,
1951 * Must-revalidate, Proxy-revalidate, or S-maxage.
1953 proto_tree_add_uint (tree, hf_wsp_header_cache_control,
1954 header_buff, 0, headerLen,
1955 valueLen); /* valueLen is the value */
1958 if (valueType == VALUE_IS_TEXT_STRING)
1963 proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
1964 header_buff, 0, headerLen,
1965 tvb_get_ptr (value_buff, 0, valueLen));
1970 * Value-length Cache-directive.
1971 * Get first field of Cache-directive.
1973 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
1974 &subvalueOffset, &offset);
1975 if (valueType == VALUE_IS_TEXT_STRING)
1978 * Cache-extension Parameter.
1980 ti = proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
1981 header_buff, 0, headerLen,
1982 tvb_get_ptr (value_buff, 0, valueLen));
1983 parameter_tree = proto_item_add_subtree (ti,
1984 ett_header_cache_control_parameters);
1987 * Process the rest of the value as parameters.
1989 while (tvb_reported_length_remaining (value_buff, offset) > 0) {
1990 offset = add_parameter (parameter_tree, value_buff,
1995 if (get_integer (value_buff, subvalueOffset, subvalueLen, valueType,
1998 proto_tree_add_text (tree, header_buff, 0, headerLen,
1999 "Invalid Cache-Control Cache-directive value");
2008 * Loop, processing Field-names.
2010 ti = proto_tree_add_uint (tree,
2011 hf_wsp_header_cache_control,
2012 header_buff, 0, headerLen,
2014 field_names_tree = proto_item_add_subtree (ti,
2015 ett_header_cache_control_field_names);
2016 while (tvb_reported_length_remaining (value_buff, offset)
2018 offset = add_cache_control_field_name (tree,
2019 value_buff, offset, value);
2028 * Get Delta-second-value.
2030 valueType = get_value_type_len (value_buff, offset,
2031 &subvalueLen, &subvalueOffset, &offset);
2032 if (get_integer (value_buff, subvalueOffset,
2033 subvalueLen, valueType, &delta_secs) < 0)
2035 proto_tree_add_text (tree,
2036 header_buff, 0, headerLen,
2037 "Invalid Cache-Control %s Delta-second-value",
2038 match_strval (value, vals_cache_control));
2042 proto_tree_add_uint_format (tree,
2043 hf_wsp_header_cache_control,
2044 header_buff, 0, headerLen,
2046 "Cache-Control: %s %u secs",
2047 match_strval (value, vals_cache_control),
2054 * This should not happen, but handle it anyway.
2056 proto_tree_add_uint (tree,
2057 hf_wsp_header_cache_control,
2058 header_buff, 0, headerLen,
2066 add_cache_control_field_name (proto_tree *tree, tvbuff_t *value_buff,
2067 int offset, guint cache_control_value)
2069 value_type_t valueType;
2074 startOffset = offset;
2075 valueType = get_value_type_len (value_buff, offset,
2076 &subvalueLen, &subvalueOffset, &offset);
2077 if (valueType == VALUE_IS_TEXT_STRING)
2082 proto_tree_add_item (tree,
2083 hf_wsp_header_cache_control_field_name_str,
2084 value_buff, startOffset, offset - startOffset,
2087 else if (valueType == VALUE_IN_LEN)
2090 * Short-integer Field-name.
2092 proto_tree_add_uint (tree,
2093 hf_wsp_header_cache_control_field_name,
2094 value_buff, startOffset, offset - startOffset,
2100 * Long-integer - illegal.
2102 proto_tree_add_text (tree,
2103 value_buff, startOffset, offset - startOffset,
2104 "Invalid Cache-Control %s Field-name",
2105 match_strval (cache_control_value, vals_cache_control));
2111 add_connection_header (proto_tree *tree, tvbuff_t *header_buff,
2112 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2117 if (valueType == VALUE_LEN_SUPPLIED)
2122 proto_tree_add_text (tree, header_buff, 0, headerLen,
2123 "Invalid Connection value");
2126 if (valueType == VALUE_IS_TEXT_STRING)
2131 proto_tree_add_string (tree,
2132 hf_wsp_header_connection_str,
2133 header_buff, 0, headerLen,
2134 tvb_get_ptr (value_buff, 0, valueLen));
2139 * First byte had the 8th bit set.
2141 if (valueLen == 0) {
2145 proto_tree_add_uint (tree, hf_wsp_header_connection,
2146 header_buff, offset, headerLen, valueLen);
2153 proto_tree_add_text (tree, header_buff, 0, headerLen,
2154 "Invalid Connection value");
2158 add_pragma_header (proto_tree *tree, tvbuff_t *header_buff,
2159 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2166 if (valueType == VALUE_IN_LEN)
2171 proto_tree_add_text (tree, header_buff, 0, headerLen,
2175 if (valueType == VALUE_IS_TEXT_STRING)
2180 proto_tree_add_text (tree, header_buff, 0, headerLen,
2186 * First byte had the 8th bit set.
2188 if (valueLen == 0) {
2192 proto_tree_add_string (tree, hf_wsp_header_pragma,
2193 header_buff, 0, headerLen, "No-cache");
2198 * Value-length, followed by Parameter.
2202 valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2203 &subvalueOffset, &offset);
2204 if (valueType == VALUE_IS_TEXT_STRING)
2207 * Parameter - a text string.
2209 proto_tree_add_string (tree, hf_wsp_header_pragma,
2210 header_buff, 0, headerLen,
2211 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
2214 * Parameter - numeric; illegal?
2216 proto_tree_add_text (tree, header_buff, 0, headerLen,
2222 add_transfer_encoding_header (proto_tree *tree, tvbuff_t *header_buff,
2223 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2228 if (valueType == VALUE_LEN_SUPPLIED)
2233 proto_tree_add_text (tree, header_buff, 0, headerLen,
2234 "Invalid Transfer-Encoding value");
2237 if (valueType == VALUE_IS_TEXT_STRING)
2242 proto_tree_add_string (tree,
2243 hf_wsp_header_transfer_encoding_str,
2244 header_buff, 0, headerLen,
2245 tvb_get_ptr (value_buff, 0, valueLen));
2250 * First byte had the 8th bit set.
2252 if (valueLen == 0) {
2256 proto_tree_add_uint (tree, hf_wsp_header_transfer_encoding,
2257 header_buff, offset, headerLen, valueLen);
2264 proto_tree_add_text (tree, header_buff, 0, headerLen,
2265 "Invalid Transfer Encoding value");
2269 add_warning_header (proto_tree *tree, tvbuff_t *header_buff,
2270 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2275 proto_tree *warning_tree;
2280 * Put the items under a header.
2281 * XXX - make the text of the item summarize the elements.
2283 ti = proto_tree_add_item (tree, hf_wsp_header_warning,
2284 header_buff, 0, headerLen, bo_little_endian);
2285 warning_tree = proto_item_add_subtree(ti, ett_header_warning);
2287 if (valueType == VALUE_IN_LEN)
2290 * Warn-code (Short-integer).
2292 proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2293 header_buff, 0, headerLen,
2294 valueLen); /* valueLen is the value */
2297 if (valueType == VALUE_IS_TEXT_STRING)
2302 proto_tree_add_text (warning_tree, header_buff, 0, headerLen,
2303 "Invalid Warning (all text)");
2308 * Warning-value; Warn-code, followed by Warn-agent, followed by
2312 * Get Short-integer Warn-code.
2314 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2315 &subvalueOffset, &offset);
2316 if (valueType != VALUE_IN_LEN)
2319 * Not a Short-integer.
2321 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2322 subvalueLen, "Invalid Warn-code (not a Short-integer)");
2325 proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2326 value_buff, subvalueOffset, 1,
2327 subvalueLen); /* subvalueLen is the value */
2330 * Warn-agent; must be text.
2332 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2333 &subvalueOffset, &offset);
2334 if (valueType != VALUE_IS_TEXT_STRING)
2339 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2340 subvalueLen, "Invalid Warn-agent (not a text string)");
2343 proto_tree_add_item (warning_tree,
2344 hf_wsp_header_warning_agent,
2345 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2348 * Warn-text; must be text.
2350 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2351 &subvalueOffset, &offset);
2352 if (valueType != VALUE_IS_TEXT_STRING)
2357 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2358 subvalueLen, "Invalid Warn-text (not a text string)");
2361 proto_tree_add_item (warning_tree,
2362 hf_wsp_header_warning_text,
2363 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2367 add_accept_application_header (proto_tree *tree, tvbuff_t *header_buff,
2368 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2373 if (valueType == VALUE_IN_LEN)
2376 * Application-id-value; numeric, so it's App-assigned-code.
2378 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2379 header_buff, 0, headerLen,
2380 valueLen); /* valueLen is the value */
2383 if (valueType == VALUE_IS_TEXT_STRING)
2388 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2389 header_buff, 0, headerLen,
2390 tvb_get_ptr (value_buff, 0, valueLen));
2395 * First byte had the 8th bit set.
2397 if (valueLen == 0) {
2401 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2402 header_buff, 0, headerLen,
2408 * Integer-value, hence App-assigned-code.
2410 if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
2412 proto_tree_add_text (tree, header_buff, 0, headerLen,
2413 "Invalid Accept-Application App-assigned-code");
2417 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2418 header_buff, 0, headerLen, value);
2423 add_wap_application_id_header (proto_tree *tree, tvbuff_t *header_buff,
2424 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2427 if (valueType == VALUE_IN_LEN)
2430 * Must application-id (the 8th bit was stripped off).
2432 proto_tree_add_uint (tree, hf_wsp_header_wap_application_id,
2433 header_buff, 0, headerLen,
2434 valueLen); /* valueLen is the value */
2437 if (valueType == VALUE_IS_TEXT_STRING)
2442 proto_tree_add_string (tree, hf_wsp_header_wap_application_id_str,
2443 header_buff, 0, headerLen,
2444 tvb_get_ptr (value_buff, 0, valueLen));
2451 fprintf(stderr, "dissect_wsp: Suprising format of X-Wap-Application-Id\n");
2456 add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type)
2459 proto_tree *wsp_capabilities;
2461 guint offsetStr = 0;
2462 guint capabilitiesLen = tvb_reported_length (tvb);
2463 guint capabilitiesStart = 0;
2469 char valString[200];
2472 fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, capabilitiesLen);
2476 if (capabilitiesLen <= 0)
2478 fprintf (stderr, "dissect_wsp: Capabilities = 0\n");
2483 fprintf (stderr, "dissect_wsp: capabilities to process\n");
2486 ti = proto_tree_add_item (tree, hf_wsp_capabilities_section,tvb,offset,capabilitiesLen,bo_little_endian);
2487 wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
2491 while (offset < capabilitiesLen)
2493 /* Loop round each header */
2494 capabilitiesStart = offset;
2495 length = tvb_get_guint8 (tvb, capabilitiesStart);
2497 if (length >= 127) /* length */
2500 fprintf (stderr, "dissect_wsp: capabilities length invalid %d\n",length);
2506 peek = tvb_get_guint8 (tvb, offset);
2508 switch (peek & 0x7f)
2510 case 0x00 : /* Client-SDU-Size */
2511 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
2512 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_client_SDU, tvb, capabilitiesStart, length+1, value);
2514 case 0x01 : /* Server-SDU-Size */
2515 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
2516 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_server_SDU, tvb, capabilitiesStart, length+1, value);
2518 case 0x02 : /* Protocol Options */
2519 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
2524 ret = snprintf(valString+i,200-i,"%s","(Confirmed push facility) ");
2527 * Some versions of snprintf
2528 * return -1 if they'd
2529 * truncate the output.
2541 ret = snprintf(valString+i,200-i,"%s","(Push facility) ");
2544 * Some versions of snprintf
2545 * return -1 if they'd
2546 * truncate the output.
2558 ret = snprintf(valString+i,200-i,"%s","(Session resume facility) ");
2561 * Some versions of snprintf
2562 * return -1 if they'd
2563 * truncate the output.
2575 ret = snprintf(valString+i,200-i,"%s","(Acknowledgement headers) ");
2578 * Some versions of snprintf
2579 * return -1 if they'd
2580 * truncate the output.
2587 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_protocol_opt, tvb, capabilitiesStart, length+1, valString);
2589 case 0x03 : /* Method-MOR */
2590 value = tvb_get_guint8(tvb, offset);
2591 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_method_MOR, tvb, capabilitiesStart, length+1, value);
2593 case 0x04 : /* Push-MOR */
2594 value = tvb_get_guint8(tvb, offset);
2595 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_push_MOR, tvb, capabilitiesStart, length+1, value);
2598 case 0x05 : /* Extended Methods */
2601 add_capability_vals(tvb, (type == CONNECT),
2602 offsetStr, length, capabilitiesStart,
2603 valString, sizeof valString);
2604 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_extended_methods, tvb, capabilitiesStart, length+1, valString);
2606 case 0x06 : /* Header Code Pages */
2609 add_capability_vals(tvb, (type == CONNECT),
2610 offsetStr, length, capabilitiesStart,
2611 valString, sizeof valString);
2612 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_header_code_pages, tvb, capabilitiesStart, length+1, valString);
2614 case 0x07 : /* Aliases */
2617 proto_tree_add_text (wsp_capabilities, tvb , capabilitiesStart, length+1,
2618 "Unsupported Header (0x%02X)", peek & 0x7F);
2621 offset=capabilitiesStart+length+1;
2626 add_capability_vals(tvbuff_t *tvb, gboolean add_string, int offsetStr,
2627 guint length, guint capabilitiesStart, char *valString,
2628 size_t valStringSize)
2636 while ((offsetStr-capabilitiesStart) <= length)
2638 value = tvb_get_guint8(tvb, offsetStr);
2639 if (i >= valStringSize) {
2645 ret = snprintf(valString+i,valStringSize-i,
2650 ret = snprintf(valString+i,valStringSize-i,"(%d) ",
2655 * Some versions of snprintf return -1
2656 * if they'd truncate the output.
2664 for (;(c = tvb_get_guint8(tvb, offsetStr))
2665 && i < valStringSize - 1; i++,offsetStr++)
2668 if (i < valStringSize - 2) {
2669 valString[i++] = ')';
2670 valString[i++] = ' ';
2674 valString[i] = '\0';
2678 get_value_type_len (tvbuff_t *tvb, int offset, guint *valueLen,
2679 int *valueOffset, int *nextOffset)
2685 /* Get value part of header */
2686 peek = tvb_get_guint8 (tvb, offset);
2690 * The value follows "peek", and is "peek" octets long.
2693 fprintf (stderr, "dissect_wsp: Looking for %d octets\n", peek);
2696 *valueLen = len; /* Length of value */
2697 offset++; /* Skip the length */
2698 *valueOffset = offset; /* Offset of value */
2699 offset += len; /* Skip the value */
2700 *nextOffset = offset; /* Offset after value */
2701 return VALUE_LEN_SUPPLIED;
2703 else if (peek == 31)
2706 * A uintvar giving the length of the value follows
2707 * "peek", and the value follows that.
2710 fprintf (stderr, "dissect_wsp: Looking for uintvar octets\n");
2712 offset++; /* Skip the uintvar indicator */
2713 count = 0; /* Initialise count */
2714 len = tvb_get_guintvar (tvb, offset, &count);
2715 *valueLen = len; /* Length of value */
2716 offset += count; /* Skip the length */
2717 *valueOffset = offset; /* Offset of value */
2718 offset += len; /* Skip the value */
2719 *nextOffset = offset; /* Offset after value */
2720 return VALUE_LEN_SUPPLIED;
2722 else if (peek <= 127)
2725 * The value is a NUL-terminated string, and "peek"
2726 * is the first octet of the string.
2729 fprintf (stderr, "dissect_wsp: Looking for NUL-terminated string\n");
2731 len = tvb_strsize (tvb, offset);
2732 *valueLen = len; /* Length of value */
2733 *valueOffset = offset; /* Offset of value */
2734 offset += len; /* Skip the value */
2735 *nextOffset = offset; /* Offset after value */
2736 return VALUE_IS_TEXT_STRING;
2741 * "peek", with the 8th bit stripped off, is the value.
2744 fprintf (stderr, "dissect_wsp: Value is %d\n", (peek & 0x7F));
2746 *valueLen = peek & 0x7F; /* Return the value itself */
2747 *valueOffset = offset; /* Offset of value */
2748 offset++; /* Skip the value */
2749 *nextOffset = offset; /* Offset after value */
2750 return VALUE_IN_LEN;
2755 get_uintvar (tvbuff_t *tvb, guint offset, guint offsetEnd)
2762 octet = tvb_get_guint8 (tvb, offset);
2765 value += octet & 0x7f;
2767 while ((offsetEnd > offset) && (octet & 0x80));
2772 add_content_type_value (proto_tree *tree, tvbuff_t *header_buff,
2773 int headerOffset, int headerLen, tvbuff_t *value_buff,
2774 value_type_t valueType, int valueLen, int hf_numeric, int hf_string,
2775 guint *contentTypep, const char **contentTypeStrp)
2778 proto_tree *parameter_tree;
2779 const char *contentTypeStr;
2785 if (valueType == VALUE_IN_LEN)
2788 * Constrained-media (Short-Integer).
2790 proto_tree_add_uint (tree, hf_numeric,
2791 header_buff, headerOffset, headerLen,
2792 valueLen); /* valueLen is the value */
2795 * Return the numerical value, and a null string value
2796 * indicating that the value is numerical.
2798 *contentTypep = valueLen;
2799 *contentTypeStrp = NULL;
2802 if (valueType == VALUE_IS_TEXT_STRING)
2805 * Constrained-media (text, i.e. Extension-Media).
2807 contentTypeStr = tvb_get_ptr (value_buff, 0, valueLen);
2808 proto_tree_add_string (tree, hf_string,
2809 header_buff, headerOffset, headerLen,
2813 * Return the string value, and set the numerical value
2814 * to 0 (as it shouldn't be used).
2817 *contentTypeStrp = contentTypeStr;
2822 * Content-general-form; Value-length, followed by Media-range,
2823 * followed by optional Accept-parameters.
2827 valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2828 &subvalueOffset, &offset);
2829 if (valueType == VALUE_IS_TEXT_STRING)
2832 * Extension-Media; value is a string.
2835 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
2836 ti = proto_tree_add_string (tree, hf_string, header_buff,
2837 headerOffset, headerLen, contentTypeStr);
2840 * Return the string value, and set the numerical value
2841 * to 0 (as it shouldn't be used).
2844 *contentTypeStrp = contentTypeStr;
2849 * Well-known-media; value is an Integer.
2851 if (get_integer (value_buff, subvalueOffset, subvalueLen,
2852 valueType, &value) < 0)
2854 proto_tree_add_text (tree, header_buff,
2855 headerOffset, headerLen,
2856 "Invalid integer for Well-known-media");
2859 * Content type is invalid.
2860 * Don't try to parse the rest of the value.
2863 *contentTypeStrp = NULL;
2866 ti = proto_tree_add_uint (tree, hf_numeric,
2867 header_buff, headerOffset, headerLen, value);
2870 * Return the numerical value, and a null string value
2871 * indicating that the value is numerical.
2873 *contentTypep = value;
2874 *contentTypeStrp = NULL;
2878 * Process the rest of the value as parameters.
2880 parameter_tree = proto_item_add_subtree(ti,
2881 ett_content_type_parameters);
2882 while (tvb_reported_length_remaining (value_buff, offset) > 0)
2883 offset = add_parameter (parameter_tree, value_buff, offset);
2887 add_content_type (proto_tree *tree, tvbuff_t *tvb, guint offset,
2888 guint *contentTypep, const char **contentTypeStrp)
2891 value_type_t valueType;
2895 tvbuff_t *value_buff;
2897 valueStart = offset;
2900 * Get the value type and length (or, if the type is VALUE_IN_LEN,
2901 * meaning the value is a Short-integer, get the value type
2902 * and the value itself).
2904 valueType = get_value_type_len (tvb, valueStart, &valueLen,
2905 &valueOffset, &offset);
2906 valueTypeLen = offset - valueStart;
2909 * Get a tvbuff for the value.
2910 * XXX - can valueLen be 0?
2911 * XXX - cut the actual length short so that it doesn't run
2912 * past the actual length of tvb.
2914 if (valueType != VALUE_IN_LEN) {
2915 value_buff = tvb_new_subset (tvb, valueOffset, valueLen,
2919 * XXX - when the last dissector is tvbuffified,
2920 * so that NULL is no longer a valid tvb pointer
2921 * value in "proto_tree_add" calls, just
2922 * set "value_buff" to NULL.
2924 * XXX - can we already do that? I.e., will that
2925 * cause us always to crash if we mistakenly try
2926 * to fetch the value of a VALUE_IN_LEN item?
2928 value_buff = tvb_new_subset (tvb, valueStart, 0, 0);
2931 add_content_type_value (tree, tvb, valueStart, valueTypeLen, value_buff,
2932 valueType, valueLen, hf_wsp_content_type,
2933 hf_wsp_content_type_str, contentTypep, contentTypeStrp);
2939 add_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
2940 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2941 int valueLen, int hf_numeric, guint8 headerType)
2945 if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
2947 proto_tree_add_text (tree, header_buff, 0, headerLen,
2948 "Invalid %s integer value",
2949 match_strval (headerType, vals_field_names));
2953 proto_tree_add_uint (tree, hf_numeric,
2954 header_buff, 0, headerLen, value);
2959 add_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
2960 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2961 int valueLen, int hf_string, guint8 headerType)
2963 if (valueType != VALUE_IS_TEXT_STRING)
2965 proto_tree_add_text (tree, header_buff, 0, headerLen,
2966 "Invalid %s string value",
2967 match_strval (headerType, vals_field_names));
2971 proto_tree_add_string (tree, hf_string, header_buff,
2972 0, headerLen, tvb_get_ptr (value_buff, 0, valueLen));
2977 add_quoted_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
2978 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2979 int valueLen, int hf_string, guint8 headerType)
2981 if (valueType != VALUE_IS_TEXT_STRING)
2983 proto_tree_add_text (tree, header_buff, 0, headerLen,
2984 "Invalid %s quoted string value",
2985 match_strval (headerType, vals_field_names));
2989 proto_tree_add_string (tree, hf_string, header_buff,
2990 0, headerLen, tvb_get_ptr (value_buff, 1, valueLen - 1));
2994 /* Utility function to add a date value to the protocol tree */
2996 add_date_value_header (proto_tree *tree, tvbuff_t *header_buff,
2997 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2998 int valueLen, int hf_time, guint8 headerType)
3003 /* Attempt to get the date value from the buffer */
3004 if (get_integer (value_buff, 0, valueLen, valueType, &secs) == 0)
3007 * Fill in the "struct timeval", and add it to the
3009 * Note: this will succeed even if it's a Short-integer.
3010 * A Short-integer would work, but, as the time values
3011 * are UNIX seconds-since-the-Epoch value, and as
3012 * there weren't WAP phones or Web servers back in
3013 * late 1969/early 1970, they're unlikely to be used.
3015 timeValue.secs = secs;
3016 timeValue.nsecs = 0;
3017 proto_tree_add_time (tree, hf_time, header_buff, 0,
3018 headerLen, &timeValue);
3022 proto_tree_add_text (tree, header_buff, 0, headerLen,
3023 "Invalid %s date value",
3024 match_strval (headerType, vals_field_names));
3029 add_parameter (proto_tree *tree, tvbuff_t *value_buff, int offset)
3032 value_type_t valueType;
3037 startOffset = offset;
3038 valueType = get_value_type_len (value_buff, offset,
3039 &subvalueLen, &subvalueOffset, &offset);
3040 if (valueType == VALUE_IS_TEXT_STRING)
3043 * Untyped-parameter.
3045 offset = add_untyped_parameter (tree, value_buff, startOffset, offset);
3050 * Well-known-parameter-token.
3052 if (get_integer (value_buff, subvalueOffset,
3053 subvalueLen, valueType, &value) < 0)
3055 proto_tree_add_text (tree, value_buff, startOffset,
3056 offset - startOffset,
3057 "Invalid Well-known-parameter-token");
3063 case 0x01: /* Charset */
3064 offset = add_parameter_charset (tree, value_buff, startOffset, offset);
3067 case 0x03: /* Type */
3068 offset = add_parameter_type (tree, value_buff, startOffset, offset);
3071 case 0x05: /* Name */
3072 offset = add_parameter_text (tree, value_buff, startOffset, offset,
3073 hf_wsp_parameter_name, "Name");
3076 case 0x06: /* Filename */
3077 offset = add_parameter_text (tree, value_buff, startOffset, offset,
3078 hf_wsp_parameter_filename, "Filename");
3081 case 0x09: /* Type (special) */
3082 offset = add_constrained_encoding(tree, value_buff, startOffset, offset);
3085 case 0x0A: /* Start */
3086 offset = add_parameter_text (tree, value_buff, startOffset, offset,
3087 hf_wsp_parameter_start, "Start");
3090 case 0x0B: /* Start-info */
3091 offset = add_parameter_text (tree, value_buff, startOffset, offset,
3092 hf_wsp_parameter_start_info, "Start-info");
3095 case 0x0C: /* Comment */
3096 offset = add_parameter_text (tree, value_buff, startOffset, offset,
3097 hf_wsp_parameter_comment, "Comment");
3100 case 0x0D: /* Domain */
3101 offset = add_parameter_text (tree, value_buff, startOffset, offset,
3102 hf_wsp_parameter_domain, "Domain");
3105 case 0x0F: /* Path */
3106 offset = add_parameter_text (tree, value_buff, startOffset, offset,
3107 hf_wsp_parameter_path, "Path");
3111 case 0x02: /* Level */
3112 case 0x07: /* Differences */
3113 case 0x08: /* Padding */
3114 case 0x0E: /* Max-Age */
3115 case 0x10: /* Secure */
3124 add_untyped_parameter (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3127 const guint8 *token;
3128 value_type_t valueType;
3132 int vOffset = offset;
3134 token = tvb_get_ptr (value_buff, startOffset, offset - startOffset);
3136 * Now an Untyped-value; either an Integer-value or a Text-value.
3138 valueType = get_value_type_len (value_buff, offset,
3139 &subvalueLen, &subvalueOffset, &offset);
3140 if (valueType == VALUE_IS_TEXT_STRING)
3145 if ((offset - vOffset) == 1) {
3147 * No-value. (stringSize includes the terminating
3148 * null byte, so an empty string has a size of 1.)
3150 proto_tree_add_text (tree, value_buff, startOffset,
3151 offset - startOffset,
3155 proto_tree_add_text (tree, value_buff, startOffset,
3156 offset - startOffset,
3158 tvb_get_ptr (value_buff, vOffset, offset - vOffset));
3165 if (get_integer (value_buff, subvalueOffset, subvalueLen,
3166 valueType, &value) == 0)
3168 proto_tree_add_text (tree, value_buff, startOffset,
3169 offset - startOffset,
3170 "%s: %u", token, value);
3174 proto_tree_add_text (tree, value_buff, startOffset,
3175 offset - startOffset,
3176 "%s: Invalid Integer-value", token);
3183 add_parameter_charset (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3186 value_type_t valueType;
3191 valueType = get_value_type_len (value_buff, offset,
3192 &subvalueLen, &subvalueOffset, &offset);
3193 if (valueType == VALUE_IN_LEN)
3198 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3199 value_buff, startOffset, offset - startOffset,
3200 subvalueLen); /* subvalueLen is the value */
3203 if (valueType == VALUE_IS_TEXT_STRING)
3208 proto_tree_add_text (tree, value_buff, startOffset,
3209 offset - startOffset, "Invalid Well-known charset");
3214 * First byte had the 8th bit set.
3216 if (subvalueLen == 0) {
3219 * XXX - add this as a field?
3221 proto_tree_add_text (tree, value_buff, startOffset,
3222 offset- startOffset, "*");
3226 if (get_integer(value_buff, subvalueOffset, subvalueLen,
3227 valueType, &value) == -1) {
3228 proto_tree_add_text (tree, value_buff, startOffset,
3229 offset - startOffset, "Length %u not handled in Well-known charset",
3232 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3233 value_buff, startOffset, offset - startOffset, value);
3239 add_constrained_encoding (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3242 value_type_t valueType;
3247 valueType = get_value_type_len (value_buff, offset,
3248 &subvalueLen, &subvalueOffset, &offset);
3249 if (valueType == VALUE_IN_LEN)
3252 * Integer-value, invalid
3254 proto_tree_add_text (tree, value_buff, startOffset,
3255 offset - startOffset, "Invalid multipart type parameter");
3258 if (valueType == VALUE_IS_TEXT_STRING)
3263 proto_tree_add_string (tree, hf_wsp_parameter_upart_type,
3264 value_buff, startOffset, offset - startOffset,
3265 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
3269 * First byte had the 8th bit set.
3271 get_integer(value_buff, subvalueOffset, subvalueLen, valueType, &value);
3272 proto_tree_add_uint (tree, hf_wsp_parameter_upart_type_value,
3273 value_buff, startOffset, offset - startOffset, value);
3278 add_parameter_type (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3281 value_type_t valueType;
3286 valueType = get_value_type_len (value_buff, offset,
3287 &subvalueLen, &subvalueOffset, &offset);
3288 if (get_integer(value_buff, subvalueOffset, subvalueLen,
3289 valueType, &value) == -1) {
3290 proto_tree_add_text (tree, value_buff, startOffset,
3291 offset - startOffset, "Invalid type");
3293 proto_tree_add_uint (tree, hf_wsp_parameter_type, value_buff,
3294 startOffset, offset - startOffset, value);
3300 add_parameter_text (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3301 int offset, int hf_string, const char *paramName)
3303 value_type_t valueType;
3307 valueType = get_value_type_len (value_buff, offset,
3308 &subvalueLen, &subvalueOffset, &offset);
3309 if (valueType != VALUE_IS_TEXT_STRING) {
3310 proto_tree_add_text (tree, value_buff, startOffset,
3311 offset - startOffset, "Invalid %s", paramName);
3313 proto_tree_add_string (tree, hf_string, value_buff,
3314 startOffset, offset - startOffset,
3315 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
3321 add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType,
3322 const char *contentTypeStr)
3325 guint variableStart = 0;
3326 guint variableEnd = 0;
3327 guint valueStart = 0;
3332 /* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,tvb_length_remaining(tvb, offset),bo_little_endian); */
3333 ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,tvb_reported_length(tvb),bo_little_endian);
3335 if (contentTypeStr == NULL && contentType == 0x12)
3339 * Iterate through post data.
3341 for (offset = 0; offset < tvb_reported_length (tvb); offset++)
3343 peek = tvb_get_guint8 (tvb, offset);
3346 variableEnd = offset;
3347 valueStart = offset+1;
3349 else if (peek == '&')
3351 if (variableEnd > 0)
3353 add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
3355 variableStart = offset+1;
3362 /* See if there's outstanding data */
3363 if (variableEnd > 0)
3365 add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
3368 else if ((contentType == 0x22) || (contentType == 0x23) || (contentType == 0x23) || (contentType == 0x24) ||
3369 (contentType == 0x25) || (contentType == 0x26) || (contentType == 0x33))
3371 add_multipart_data(ti, tvb);
3376 add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
3378 int variableLength = variableEnd-variableStart;
3379 int valueLength = 0;
3380 char *variableBuffer;
3383 variableBuffer = g_malloc (variableLength+1);
3384 strncpy (variableBuffer, tvb_get_ptr (tvb, variableStart, variableLength), variableLength);
3385 variableBuffer[variableLength] = 0;
3387 if (valueEnd < valueStart)
3389 valueBuffer = g_malloc (1);
3391 valueEnd = valueStart;
3395 valueLength = valueEnd-valueStart;
3396 valueBuffer = g_malloc (valueLength+1);
3397 strncpy (valueBuffer, tvb_get_ptr (tvb, valueStart, valueLength), valueLength);
3398 valueBuffer[valueLength] = 0;
3401 /* Check for variables with no value */
3402 if (valueStart >= tvb_reported_length (tvb))
3404 valueStart = tvb_reported_length (tvb);
3405 valueEnd = valueStart;
3407 valueLength = valueEnd-valueStart;
3409 proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
3411 g_free (variableBuffer);
3412 g_free (valueBuffer);
3416 add_multipart_data (proto_tree *tree, tvbuff_t *tvb)
3424 guint contentType = 0;
3425 const char *contentTypeStr;
3430 proto_item *sub_tree = NULL,
3432 proto_tree *mpart_tree;
3434 nEntries = tvb_get_guintvar (tvb, offset, &count);
3438 sub_tree = proto_tree_add_text(tree, tvb, offset - count, 0,
3440 proto_item_add_subtree(sub_tree, ett_mpartlist);
3444 part_start = offset;
3445 HeadersLen = tvb_get_guintvar (tvb, offset, &count);
3447 DataLen = tvb_get_guintvar (tvb, offset, &count);
3449 ti = proto_tree_add_uint(sub_tree, hf_wsp_mpart, tvb, part_start,
3450 HeadersLen + DataLen + (offset - part_start), partnr);
3451 mpart_tree = proto_item_add_subtree(ti, ett_multiparts);
3452 nextOffset = add_content_type (mpart_tree, tvb, offset, &contentType, &contentTypeStr);
3453 HeadersLen -= (nextOffset - offset);
3456 tmp_tvb = tvb_new_subset (tvb, nextOffset, HeadersLen, HeadersLen);
3457 add_headers (mpart_tree, tmp_tvb);
3459 offset = nextOffset + HeadersLen;
3460 proto_tree_add_item (mpart_tree, hf_wsp_multipart_data, tvb, offset, DataLen, bo_little_endian);
3467 get_integer (tvbuff_t *tvb, guint offset, guint valueLength,
3468 value_type_t valueType, guint *value)
3470 if (valueType == VALUE_IS_TEXT_STRING) {
3477 if (valueType == VALUE_IN_LEN) {
3481 *value = valueLength;
3488 switch (valueLength)
3491 *value = tvb_get_guint8(tvb, offset);
3494 *value = tvb_get_ntohs(tvb, offset);
3497 *value = tvb_get_ntoh24(tvb, offset);
3500 *value = tvb_get_ntohl(tvb, offset);
3503 /* TODO: Need to read peek octets */
3505 fprintf (stderr, "dissect_wsp: get_integer size %u NYI\n", valueLength);
3511 /* Register the protocol with Ethereal */
3513 proto_register_wsp(void)
3516 /* Setup list of header fields */
3517 static hf_register_info hf[] = {
3518 { &hf_wsp_header_tid,
3519 { "Transmission ID",
3521 FT_UINT8, BASE_HEX, NULL, 0x00,
3522 "Transmission ID", HFILL
3525 { &hf_wsp_header_pdu_type,
3528 FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
3532 { &hf_wsp_version_major,
3533 { "Version (Major)",
3534 "wsp.version.major",
3535 FT_UINT8, BASE_DEC, NULL, 0xF0,
3536 "Version (Major)", HFILL
3539 { &hf_wsp_version_minor,
3540 { "Version (Minor)",
3541 "wsp.version.minor",
3542 FT_UINT8, BASE_DEC, NULL, 0x0F,
3543 "Version (Minor)", HFILL
3546 { &hf_wsp_capability_length,
3547 { "Capability Length",
3548 "wsp.capability.length",
3549 FT_UINT32, BASE_DEC, NULL, 0x00,
3550 "Capability Length", HFILL
3553 { &hf_wsp_header_length,
3555 "wsp.headers_length",
3556 FT_UINT32, BASE_DEC, NULL, 0x00,
3557 "Headers Length", HFILL
3560 { &hf_wsp_capabilities_section,
3563 FT_NONE, BASE_DEC, NULL, 0x00,
3564 "Capabilities", HFILL
3567 { &hf_wsp_headers_section,
3570 FT_NONE, BASE_DEC, NULL, 0x00,
3576 "wsp.headers.header",
3577 FT_NONE, BASE_DEC, NULL, 0x00,
3581 { &hf_wsp_header_uri_len,
3584 FT_UINT32, BASE_DEC, NULL, 0x00,
3588 { &hf_wsp_header_uri,
3591 FT_STRING, BASE_NONE, NULL, 0x00,
3595 { &hf_wsp_server_session_id,
3596 { "Server Session ID",
3597 "wsp.server.session_id",
3598 FT_UINT32, BASE_DEC, NULL, 0x00,
3599 "Server Session ID", HFILL
3602 { &hf_wsp_header_status,
3605 FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
3609 { &hf_wsp_content_type,
3611 "wsp.content_type.type",
3612 FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
3613 "Content Type", HFILL
3616 { &hf_wsp_content_type_str,
3618 "wsp.content_type.type.string",
3619 FT_STRING, BASE_NONE, NULL, 0x00,
3620 "Content Type", HFILL
3623 { &hf_wsp_parameter_well_known_charset,
3625 "wsp.content_type.parameter.charset",
3626 FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
3630 { &hf_wsp_parameter_type,
3632 "wsp.content_type.parameter.type",
3633 FT_UINT32, BASE_DEC, NULL, 0x00,
3637 { &hf_wsp_parameter_name,
3639 "wsp.content_type.parameter.name",
3640 FT_STRING, BASE_NONE, NULL, 0x00,
3644 { &hf_wsp_parameter_filename,
3646 "wsp.content_type.parameter.filename",
3647 FT_STRING, BASE_NONE, NULL, 0x00,
3651 { &hf_wsp_parameter_start,
3653 "wsp.content_type.parameter.start",
3654 FT_STRING, BASE_NONE, NULL, 0x00,
3658 { &hf_wsp_parameter_start_info,
3660 "wsp.content_type.parameter.start_info",
3661 FT_STRING, BASE_NONE, NULL, 0x00,
3665 { &hf_wsp_parameter_comment,
3667 "wsp.content_type.parameter.comment",
3668 FT_STRING, BASE_NONE, NULL, 0x00,
3672 { &hf_wsp_parameter_domain,
3674 "wsp.content_type.parameter.domain",
3675 FT_STRING, BASE_NONE, NULL, 0x00,
3679 { &hf_wsp_parameter_path,
3681 "wsp.content_type.parameter.path",
3682 FT_STRING, BASE_NONE, NULL, 0x00,
3686 { &hf_wsp_parameter_upart_type,
3688 "wsp.content_type.parameter.upart.type",
3689 FT_STRING, BASE_NONE, NULL, 0x00,
3690 "Multipart type", HFILL
3693 { &hf_wsp_parameter_upart_type_value,
3695 "wsp.content_type.parameter.upart.type.int",
3696 FT_UINT8, BASE_DEC, NULL, 0x00,
3697 "Multipart type (int value)", HFILL
3700 { &hf_wsp_reply_data,
3703 FT_NONE, BASE_NONE, NULL, 0x00,
3707 { &hf_wsp_header_shift_code,
3710 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3711 FT_UINT8, BASE_HEX, NULL, 0x00,
3715 { &hf_wsp_header_accept,
3717 "wsp.header.accept",
3718 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3719 FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
3723 { &hf_wsp_header_accept_str,
3725 "wsp.header.accept.string",
3726 FT_STRING, BASE_NONE, NULL, 0x00,
3730 { &hf_wsp_header_accept_application,
3731 { "Accept-Application",
3732 "wsp.header.accept_application",
3733 FT_UINT32, BASE_HEX, NULL, 0x00,
3734 "Accept-Application", HFILL
3737 { &hf_wsp_header_accept_application_str,
3738 { "Accept-Application",
3739 "wsp.header.accept_application.string",
3740 FT_STRING, BASE_NONE, NULL, 0x00,
3741 "Accept-Application", HFILL
3744 { &hf_wsp_header_accept_charset,
3746 "wsp.header.accept_charset",
3747 FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
3748 "Accept-Charset", HFILL
3751 { &hf_wsp_header_accept_charset_str,
3753 "wsp.header.accept_charset.string",
3754 FT_STRING, BASE_NONE, NULL, 0x00,
3755 "Accept-Charset", HFILL
3758 { &hf_wsp_header_accept_language,
3759 { "Accept-Language",
3760 "wsp.header.accept_language",
3761 FT_UINT8, BASE_HEX, VALS ( vals_languages ), 0x00,
3762 "Accept-Language", HFILL
3765 { &hf_wsp_header_accept_language_str,
3766 { "Accept-Language",
3767 "wsp.header.accept_language.string",
3768 FT_STRING, BASE_NONE, NULL, 0x00,
3769 "Accept-Language", HFILL
3772 { &hf_wsp_header_accept_ranges,
3774 "wsp.header.accept_ranges",
3775 FT_UINT8, BASE_HEX, VALS ( vals_accept_ranges ), 0x00,
3776 "Accept-Ranges", HFILL
3779 { &hf_wsp_header_accept_ranges_str,
3781 "wsp.header.accept_ranges.string",
3782 FT_STRING, BASE_NONE, NULL, 0x00,
3783 "Accept-Ranges", HFILL
3786 { &hf_wsp_header_age,
3789 FT_UINT32, BASE_DEC, NULL, 0x00,
3793 { &hf_wsp_header_bearer_indication,
3795 * XXX - I'm assuming that the bearer indication is
3796 * just a bearer type.
3798 { "Bearer-indication",
3799 "wsp.header.bearer_indication",
3800 FT_UINT32, BASE_HEX, VALS(vals_bearer_types), 0x00,
3801 "Bearer-indication", HFILL
3804 { &hf_wsp_header_cache_control,
3806 "wsp.header.cache_control",
3807 FT_UINT8, BASE_HEX, VALS ( vals_cache_control ), 0x00,
3808 "Cache-Control", HFILL
3811 { &hf_wsp_header_cache_control_str,
3813 "wsp.header.cache_control.string",
3814 FT_STRING, BASE_NONE, NULL, 0x00,
3815 "Cache-Control", HFILL
3818 { &hf_wsp_header_cache_control_field_name,
3820 "wsp.header.cache_control.field_name",
3821 FT_UINT8, BASE_HEX, VALS ( vals_field_names ), 0x00,
3822 "Cache-Control field name", HFILL
3825 { &hf_wsp_header_cache_control_field_name_str,
3827 "wsp.header.cache_control.field_name.str",
3828 FT_STRING, BASE_NONE, NULL, 0x00,
3829 "Cache-Control field name", HFILL
3832 { &hf_wsp_header_connection,
3834 "wsp.header.connection",
3835 FT_UINT8, BASE_HEX, VALS ( vals_connection ), 0x00,
3839 { &hf_wsp_header_connection_str,
3841 "wsp.header.connection_str",
3842 FT_STRING, BASE_NONE, NULL, 0x00,
3846 { &hf_wsp_header_content_length,
3848 "wsp.header.content_length",
3849 FT_UINT32, BASE_DEC, NULL, 0x00,
3850 "Content-Length", HFILL
3853 { &hf_wsp_header_date,
3856 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3860 { &hf_wsp_header_etag,
3863 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3864 FT_STRING, BASE_NONE, NULL, 0x00,
3868 { &hf_wsp_header_expires,
3870 "wsp.header.expires",
3871 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3875 { &hf_wsp_header_last_modified,
3877 "wsp.header.last_modified",
3878 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3879 "Last-Modified", HFILL
3882 { &hf_wsp_header_location,
3884 "wsp.header.location",
3885 FT_STRING, BASE_NONE, NULL, 0x00,
3889 { &hf_wsp_header_if_modified_since,
3890 { "If-Modified-Since",
3891 "wsp.header.if_modified_since",
3892 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3893 "If-Modified-Since", HFILL
3896 { &hf_wsp_header_pragma,
3898 "wsp.header.pragma",
3899 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3900 FT_STRING, BASE_NONE, NULL, 0x00,
3904 { &hf_wsp_header_profile,
3906 "wsp.header.profile",
3907 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3908 FT_STRING, BASE_NONE, NULL, 0x00,
3912 { &hf_wsp_header_server,
3914 "wsp.header.server",
3915 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3916 FT_STRING, BASE_NONE, NULL, 0x00,
3920 { &hf_wsp_header_transfer_encoding,
3921 { "Transfer Encoding",
3922 "wsp.header.transfer_enc",
3923 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3924 FT_UINT8, BASE_HEX, VALS ( vals_transfer_encoding ), 0x00,
3925 "Transfer Encoding", HFILL
3928 { &hf_wsp_header_transfer_encoding_str,
3929 { "Transfer Encoding",
3930 "wsp.header.transfer_enc_str",
3931 FT_STRING, BASE_NONE, NULL, 0x00,
3932 "Transfer Encoding", HFILL
3935 { &hf_wsp_header_user_agent,
3937 "wsp.header.user_agent",
3938 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3939 FT_STRING, BASE_NONE, NULL, 0x00,
3943 { &hf_wsp_header_via,
3946 FT_STRING, BASE_NONE, NULL, 0x00,
3950 { &hf_wsp_header_wap_application_id,
3951 { "X-Wap-Application-Id",
3952 "wsp.header.wap_application_id",
3953 FT_UINT8, BASE_HEX, NULL, 0x00,
3954 "WAP application id", HFILL
3957 { &hf_wsp_header_wap_application_id_str,
3958 { "X-Wap-Application-Id",
3959 "wsp.header.wap_application_id.string",
3960 FT_STRING, BASE_NONE, NULL, 0x00,
3961 "WAP application id", HFILL
3964 { &hf_wsp_header_warning,
3966 "wsp.header.warning",
3967 FT_NONE, BASE_NONE, NULL, 0x00,
3971 { &hf_wsp_header_warning_code,
3973 "wsp.header.warning.code",
3974 FT_UINT32, BASE_DEC, NULL, 0x00,
3975 "Warning Code", HFILL
3978 { &hf_wsp_header_warning_agent,
3980 "wsp.header.warning.agent",
3981 FT_STRING, BASE_NONE, NULL, 0x00,
3982 "Warning Agent", HFILL
3985 { &hf_wsp_header_warning_text,
3987 "wsp.header.warning.text",
3988 FT_STRING, BASE_NONE, NULL, 0x00,
3989 "Warning Text", HFILL
3992 { &hf_wsp_header_application_header,
3993 { "Application Header",
3994 "wsp.header.application_header",
3995 FT_STRING, BASE_NONE, NULL, 0x00,
3996 "Application Header", HFILL
3999 { &hf_wsp_header_application_value,
4000 { "Application Header Value",
4001 "wsp.header.application_header.value",
4002 FT_STRING, BASE_NONE, NULL, 0x00,
4003 "Application Header Value", HFILL
4006 { &hf_wsp_header_content_ID,
4008 "wsp.header.content-id",
4009 FT_STRING, BASE_NONE, NULL, 0x00,
4013 { &hf_wsp_header_x_wap_tod,
4015 "wsp.header.x_wap_tod",
4016 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
4020 { &hf_wsp_capabilities_client_SDU,
4022 "wsp.capabilities.client_SDU",
4023 FT_UINT8, BASE_DEC, NULL, 0x00,
4027 { &hf_wsp_capabilities_server_SDU,
4029 "wsp.capabilities.server_SDU",
4030 FT_UINT8, BASE_DEC, NULL, 0x00,
4034 { &hf_wsp_capabilities_protocol_opt,
4035 { "Protocol Options",
4036 "wsp.capabilities.protocol_opt",
4037 FT_STRING, BASE_HEX, NULL, 0x00,
4038 "Protocol Options", HFILL
4041 { &hf_wsp_capabilities_method_MOR,
4043 "wsp.capabilities.method_mor",
4044 FT_UINT8, BASE_DEC, NULL, 0x00,
4048 { &hf_wsp_capabilities_push_MOR,
4050 "wsp.capabilities.push_mor",
4051 FT_UINT8, BASE_DEC, NULL, 0x00,
4055 { &hf_wsp_capabilities_extended_methods,
4056 { "Extended Methods",
4057 "wsp.capabilities.extend_methods",
4058 FT_STRING, BASE_HEX, NULL, 0x00,
4059 "Extended Methods", HFILL
4062 { &hf_wsp_capabilities_header_code_pages,
4063 { "Header Code Pages",
4064 "wsp.capabilities.code_pages",
4065 FT_STRING, BASE_HEX, NULL, 0x00,
4066 "Header Code Pages", HFILL
4069 { &hf_wsp_capabilities_aliases,
4071 "wsp.capabilities.aliases",
4072 FT_UINT8, BASE_HEX, NULL, 0x00,
4076 { &hf_wsp_post_data,
4079 FT_NONE, BASE_NONE, NULL, 0x00,
4083 { &hf_wsp_push_data,
4086 FT_NONE, BASE_NONE, NULL, 0x00,
4090 { &hf_wsp_multipart_data,
4091 { "Data in this part",
4092 "wsp.multipart.data",
4093 FT_NONE, BASE_NONE, NULL, 0x00,
4094 "The data of 1 MIME-multipart part.", HFILL
4100 FT_UINT32, BASE_DEC, NULL, 0x00,
4101 "MIME part of multipart data.", HFILL
4104 { &hf_wsp_redirect_flags,
4106 "wsp.redirect_flags",
4107 FT_UINT8, BASE_HEX, NULL, 0x00,
4108 "Redirect Flags", HFILL
4111 { &hf_wsp_redirect_permanent,
4112 { "Permanent Redirect",
4113 "wsp.redirect_flags.permanent",
4114 FT_BOOLEAN, 8, TFS(&yes_no_truth), PERMANENT_REDIRECT,
4115 "Permanent Redirect", HFILL
4118 { &hf_wsp_redirect_reuse_security_session,
4119 { "Reuse Security Session",
4120 "wsp.redirect_flags.reuse_security_session",
4121 FT_BOOLEAN, 8, TFS(&yes_no_truth), REUSE_SECURITY_SESSION,
4122 "Permanent Redirect", HFILL
4125 { &hf_wsp_redirect_afl,
4128 FT_UINT8, BASE_HEX, NULL, 0x00,
4129 "Redirect Address Flags/Length", HFILL
4132 { &hf_wsp_redirect_afl_bearer_type_included,
4133 { "Bearer Type Included",
4134 "wsp.redirect_afl.bearer_type_included",
4135 FT_BOOLEAN, 8, TFS(&yes_no_truth), BEARER_TYPE_INCLUDED,
4136 "Redirect Address bearer type included", HFILL
4139 { &hf_wsp_redirect_afl_port_number_included,
4140 { "Port Number Included",
4141 "wsp.redirect_afl.port_number_included",
4142 FT_BOOLEAN, 8, TFS(&yes_no_truth), PORT_NUMBER_INCLUDED,
4143 "Redirect Address port number included", HFILL
4146 { &hf_wsp_redirect_afl_address_len,
4148 "wsp.redirect_afl.address_len",
4149 FT_UINT8, BASE_DEC, NULL, ADDRESS_LEN,
4150 "Redirect Address Length", HFILL
4153 { &hf_wsp_redirect_bearer_type,
4155 "wsp.redirect_bearer_type",
4156 FT_UINT8, BASE_HEX, VALS(vals_bearer_types), 0x0,
4157 "Redirect Bearer Type", HFILL
4160 { &hf_wsp_redirect_port_num,
4162 "wsp.redirect_port_num",
4163 FT_UINT16, BASE_DEC, NULL, 0x0,
4164 "Redirect Port Number", HFILL
4167 { &hf_wsp_redirect_ipv4_addr,
4169 "wsp.redirect_ipv4_addr",
4170 FT_IPv4, BASE_NONE, NULL, 0x0,
4171 "Redirect Address (IP)", HFILL
4174 { &hf_wsp_redirect_ipv6_addr,
4176 "wsp.redirect_ipv6_addr",
4177 FT_IPv6, BASE_NONE, NULL, 0x0,
4178 "Redirect Address (IPv6)", HFILL
4181 { &hf_wsp_redirect_addr,
4183 "wsp.redirect_addr",
4184 FT_BYTES, BASE_NONE, NULL, 0x0,
4185 "Redirect Address", HFILL
4190 /* Setup protocol subtree array */
4191 static gint *ett[] = {
4193 &ett_content_type_parameters,
4196 &ett_header_warning,
4197 &ett_header_cache_control_parameters,
4198 &ett_header_cache_control_field_names,
4201 &ett_redirect_flags,
4207 /* Register the protocol name and description */
4208 proto_wsp = proto_register_protocol(
4209 "Wireless Session Protocol", /* protocol name for use by ethereal */
4210 "WSP", /* short version of name */
4211 "wap-wsp" /* Abbreviated protocol name, should Match IANA
4212 < URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
4216 /* Required function calls to register the header fields and subtrees used */
4217 proto_register_field_array(proto_wsp, hf, array_length(hf));
4218 proto_register_subtree_array(ett, array_length(ett));
4220 register_dissector("wsp-co", dissect_wsp_fromwap_co, proto_wsp);
4221 register_dissector("wsp-cl", dissect_wsp_fromwap_cl, proto_wsp);
4222 wsp_dissector_table = register_dissector_table("wsp.content_type.type",
4223 "WSP content type", FT_UINT8, BASE_HEX);
4224 register_heur_dissector_list("wsp", &heur_subdissector_list);
4226 wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
4231 proto_reg_handoff_wsp(void)
4234 * Get a handle for the WMLC dissector.
4236 wmlc_handle = find_dissector("wmlc"); /* Coming soon :) */
4239 * And get a handle for the WTP-over-UDP dissector.
4241 wtp_fromudp_handle = find_dissector("wtp-udp");
4243 /* Only connection-less WSP has no previous handler */
4244 dissector_add("udp.port", UDP_PORT_WSP, wsp_fromudp_handle);
4245 dissector_add("udp.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
4247 /* This dissector is also called from the WTP and WTLS dissectors */