3 * Routines to dissect WSP component of WAP traffic.
5 * $Id: packet-wsp.c,v 1.46 2001/12/03 02:10:31 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_reply_data = HF_EMPTY;
99 static int hf_wsp_post_data = HF_EMPTY;
100 static int hf_wsp_push_data = HF_EMPTY;
102 static int hf_wsp_header_shift_code = HF_EMPTY;
103 static int hf_wsp_header_accept = HF_EMPTY;
104 static int hf_wsp_header_accept_str = HF_EMPTY;
105 static int hf_wsp_header_accept_application = HF_EMPTY;
106 static int hf_wsp_header_accept_application_str = HF_EMPTY;
107 static int hf_wsp_header_accept_charset = HF_EMPTY;
108 static int hf_wsp_header_accept_charset_str = HF_EMPTY;
109 static int hf_wsp_header_accept_language = HF_EMPTY;
110 static int hf_wsp_header_accept_language_str = HF_EMPTY;
111 static int hf_wsp_header_accept_ranges = HF_EMPTY;
112 static int hf_wsp_header_accept_ranges_str = HF_EMPTY;
113 static int hf_wsp_header_cache_control = HF_EMPTY;
114 static int hf_wsp_header_cache_control_str = HF_EMPTY;
115 static int hf_wsp_header_cache_control_field_name = HF_EMPTY;
116 static int hf_wsp_header_connection = HF_EMPTY;
117 static int hf_wsp_header_connection_str = HF_EMPTY;
118 static int hf_wsp_header_cache_control_field_name_str = HF_EMPTY;
119 static int hf_wsp_header_content_length = HF_EMPTY;
120 static int hf_wsp_header_age = HF_EMPTY;
121 static int hf_wsp_header_bearer_indication = HF_EMPTY;
122 static int hf_wsp_header_date = HF_EMPTY;
123 static int hf_wsp_header_etag = HF_EMPTY;
124 static int hf_wsp_header_expires = HF_EMPTY;
125 static int hf_wsp_header_last_modified = HF_EMPTY;
126 static int hf_wsp_header_location = HF_EMPTY;
127 static int hf_wsp_header_if_modified_since = HF_EMPTY;
128 static int hf_wsp_header_profile = HF_EMPTY;
129 static int hf_wsp_header_pragma = HF_EMPTY;
130 static int hf_wsp_header_server = HF_EMPTY;
131 static int hf_wsp_header_user_agent = HF_EMPTY;
132 static int hf_wsp_header_warning = HF_EMPTY;
133 static int hf_wsp_header_warning_code = HF_EMPTY;
134 static int hf_wsp_header_warning_agent = HF_EMPTY;
135 static int hf_wsp_header_warning_text = HF_EMPTY;
136 static int hf_wsp_header_application_header = HF_EMPTY;
137 static int hf_wsp_header_application_value = HF_EMPTY;
138 static int hf_wsp_header_x_wap_tod = HF_EMPTY;
139 static int hf_wsp_header_transfer_encoding = HF_EMPTY;
140 static int hf_wsp_header_transfer_encoding_str = HF_EMPTY;
141 static int hf_wsp_header_via = HF_EMPTY;
142 static int hf_wsp_header_wap_application_id = HF_EMPTY;
143 static int hf_wsp_header_wap_application_id_str = HF_EMPTY;
145 static int hf_wsp_redirect_flags = HF_EMPTY;
146 static int hf_wsp_redirect_permanent = HF_EMPTY;
147 static int hf_wsp_redirect_reuse_security_session = HF_EMPTY;
148 static int hf_wsp_redirect_afl = HF_EMPTY;
149 static int hf_wsp_redirect_afl_bearer_type_included = HF_EMPTY;
150 static int hf_wsp_redirect_afl_port_number_included = HF_EMPTY;
151 static int hf_wsp_redirect_afl_address_len = HF_EMPTY;
152 static int hf_wsp_redirect_bearer_type = HF_EMPTY;
153 static int hf_wsp_redirect_port_num = HF_EMPTY;
154 static int hf_wsp_redirect_ipv4_addr = HF_EMPTY;
155 static int hf_wsp_redirect_ipv6_addr = HF_EMPTY;
156 static int hf_wsp_redirect_addr = HF_EMPTY;
158 /* Initialize the subtree pointers */
159 static gint ett_wsp = ETT_EMPTY;
160 static gint ett_content_type_parameters = ETT_EMPTY;
161 static gint ett_header = ETT_EMPTY;
162 static gint ett_headers = ETT_EMPTY;
163 static gint ett_header_warning = ETT_EMPTY;
164 static gint ett_header_cache_control_parameters = ETT_EMPTY;
165 static gint ett_header_cache_control_field_names = ETT_EMPTY;
166 static gint ett_capabilities = ETT_EMPTY;
167 static gint ett_content_type = ETT_EMPTY;
168 static gint ett_redirect_flags = ETT_EMPTY;
169 static gint ett_redirect_afl = ETT_EMPTY;
171 /* Handle for WSP-over-UDP dissector */
172 static dissector_handle_t wsp_fromudp_handle;
174 /* Handle for WTP-over-UDP dissector */
175 static dissector_handle_t wtp_fromudp_handle;
177 /* Handle for WMLC dissector */
178 static dissector_handle_t wmlc_handle;
180 static const value_string vals_pdu_type[] = {
181 { 0x00, "Reserved" },
183 { 0x02, "ConnectReply" },
184 { 0x03, "Redirect" },
186 { 0x05, "Disconnect" },
188 { 0x07, "ConfirmedPush" },
192 /* 0x10 - 0x3F Unassigned */
200 /* 0x45 - 0x4F Unassigned (Get PDU) */
201 /* 0x50 - 0x5F Extended method (Get PDU) */
206 /* 0x62 - 0x6F Unassigned (Post PDU) */
207 /* 0x70 - 0x7F Extended method (Post PDU) */
208 /* 0x80 - 0xFF Reserved */
214 static const value_string vals_status[] = {
215 /* 0x00 - 0x0F Reserved */
217 { 0x10, "Continue" },
218 { 0x11, "Switching Protocols" },
222 { 0x22, "Accepted" },
223 { 0x23, "Non-Authoritative Information" },
224 { 0x24, "No Content" },
225 { 0x25, "Reset Content" },
226 { 0x26, "Partial Content" },
228 { 0x30, "Multiple Choices" },
229 { 0x31, "Moved Permanently" },
230 { 0x32, "Moved Temporarily" },
231 { 0x33, "See Other" },
232 { 0x34, "Not Modified" },
233 { 0x35, "Use Proxy" },
234 { 0x37, "Temporary Redirect" },
236 { 0x40, "Bad Request" },
237 { 0x41, "Unauthorised" },
238 { 0x42, "Payment Required" },
239 { 0x43, "Forbidden" },
240 { 0x44, "Not Found" },
241 { 0x45, "Method Not Allowed" },
242 { 0x46, "Not Acceptable" },
243 { 0x47, "Proxy Authentication Required" },
244 { 0x48, "Request Timeout" },
245 { 0x49, "Conflict" },
247 { 0x4B, "Length Required" },
248 { 0x4C, "Precondition Failed" },
249 { 0x4D, "Request Entity Too Large" },
250 { 0x4E, "Request-URI Too Large" },
251 { 0x4F, "Unsupported Media Type" },
252 { 0x50, "Requested Range Not Satisfiable" },
253 { 0x51, "Expectation Failed" },
255 { 0x60, "Internal Server Error" },
256 { 0x61, "Not Implemented" },
257 { 0x62, "Bad Gateway" },
258 { 0x63, "Service Unavailable" },
259 { 0x64, "Gateway Timeout" },
260 { 0x65, "HTTP Version Not Supported" },
267 #define FN_ACCEPT 0x00
268 #define FN_ACCEPT_CHARSET_DEP 0x01 /* encoding version 1.1, deprecated */
269 #define FN_ACCEPT_ENCODING_DEP 0x02 /* encoding version 1.1, deprecated */
270 #define FN_ACCEPT_LANGUAGE 0x03
271 #define FN_ACCEPT_RANGES 0x04
273 #define FN_ALLOW 0x06
274 #define FN_AUTHORIZATION 0x07
275 #define FN_CACHE_CONTROL_DEP 0x08 /* encoding version 1.1, deprecated */
276 #define FN_CONNECTION 0x09
277 #define FN_CONTENT_BASE 0x0A
278 #define FN_CONTENT_ENCODING 0x0B
279 #define FN_CONTENT_LANGUAGE 0x0C
280 #define FN_CONTENT_LENGTH 0x0D
281 #define FN_CONTENT_LOCATION 0x0E
282 #define FN_CONTENT_MD5 0x0F
283 #define FN_CONTENT_RANGE_DEP 0x10 /* encoding version 1.1, deprecated */
284 #define FN_CONTENT_TYPE 0x11
287 #define FN_EXPIRES 0x14
290 #define FN_IF_MODIFIED_SINCE 0x17
291 #define FN_IF_MATCH 0x18
292 #define FN_IF_NONE_MATCH 0x19
293 #define FN_IF_RANGE 0x1A
294 #define FN_IF_UNMODIFIED_SINCE 0x1B
295 #define FN_LOCATION 0x1C
296 #define FN_LAST_MODIFIED 0x1D
297 #define FN_MAX_FORWARDS 0x1E
298 #define FN_PRAGMA 0x1F
299 #define FN_PROXY_AUTHENTICATE 0x20
300 #define FN_PROXY_AUTHORIZATION 0x21
301 #define FN_PUBLIC 0x22
302 #define FN_RANGE 0x23
303 #define FN_REFERER 0x24
304 #define FN_RETRY_AFTER 0x25
305 #define FN_SERVER 0x26
306 #define FN_TRANSFER_ENCODING 0x27
307 #define FN_UPGRADE 0x28
308 #define FN_USER_AGENT 0x29
311 #define FN_WARNING 0x2C
312 #define FN_WWW_AUTHENTICATE 0x2D
313 #define FN_CONTENT_DISPOSITION 0x2E
314 #define FN_X_WAP_APPLICATION_ID 0x2F
315 #define FN_X_WAP_CONTENT_URI 0x30
316 #define FN_X_WAP_INITIATOR_URI 0x31
317 #define FN_ACCEPT_APPLICATION 0x32
318 #define FN_BEARER_INDICATION 0x33
319 #define FN_PUSH_FLAG 0x34
320 #define FN_PROFILE 0x35
321 #define FN_PROFILE_DIFF 0x36
322 #define FN_PROFILE_WARNING 0x37
323 #define FN_EXPECT 0x38
325 #define FN_TRAILER 0x3A
326 #define FN_ACCEPT_CHARSET 0x3B /* encoding version 1.3 */
327 #define FN_ACCEPT_ENCODING 0x3C /* encoding version 1.3 */
328 #define FN_CACHE_CONTROL 0x3D /* encoding version 1.3 */
329 #define FN_CONTENT_RANGE 0x3E /* encoding version 1.3 */
330 #define FN_X_WAP_TOD 0x3F
331 #define FN_CONTENT_ID 0x40
332 #define FN_SET_COOKIE 0x41
333 #define FN_COOKIE 0x42
334 #define FN_ENCODING_VERSION 0x43
335 #define FN_PROFILE_WARNING14 0x44 /* encoding version 1.4 */
336 #define FN_CONTENT_DISPOSITION14 0x45 /* encoding version 1.4 */
337 #define FN_X_WAP_SECURITY 0x46
338 #define FN_CACHE_CONTROL14 0x47 /* encoding version 1.4 */
340 static const value_string vals_field_names[] = {
341 { FN_ACCEPT, "Accept" },
342 { FN_ACCEPT_CHARSET_DEP, "Accept-Charset (encoding 1.1)" },
343 { FN_ACCEPT_ENCODING_DEP, "Accept-Encoding (encoding 1.1)" },
344 { FN_ACCEPT_LANGUAGE, "Accept-Language" },
345 { FN_ACCEPT_RANGES, "Accept-Ranges" },
347 { FN_ALLOW, "Allow" },
348 { FN_AUTHORIZATION, "Authorization" },
349 { FN_CACHE_CONTROL_DEP, "Cache-Control (encoding 1.1)" },
350 { FN_CONNECTION, "Connection" },
351 { FN_CONTENT_BASE, "Content-Base" },
352 { FN_CONTENT_ENCODING, "Content-Encoding" },
353 { FN_CONTENT_LANGUAGE, "Content-Language" },
354 { FN_CONTENT_LENGTH, "Content-Length" },
355 { FN_CONTENT_LOCATION, "Content-Location" },
356 { FN_CONTENT_MD5, "Content-MD5" },
357 { FN_CONTENT_RANGE_DEP, "Content-Range (encoding 1.1)" },
358 { FN_CONTENT_TYPE, "Content-Type" },
361 { FN_EXPIRES, "Expires" },
364 { FN_IF_MODIFIED_SINCE, "If-Modified-Since" },
365 { FN_IF_MATCH, "If-Match" },
366 { FN_IF_NONE_MATCH, "If-None-Match" },
367 { FN_IF_RANGE, "If-Range" },
368 { FN_IF_UNMODIFIED_SINCE, "If-Unmodified-Since" },
369 { FN_LOCATION, "Location" },
370 { FN_LAST_MODIFIED, "Last-Modified" },
371 { FN_MAX_FORWARDS, "Max-Forwards" },
372 { FN_PRAGMA, "Pragma" },
373 { FN_PROXY_AUTHENTICATE, "Proxy-Authenticate" },
374 { FN_PROXY_AUTHORIZATION, "Proxy-Authorization" },
375 { FN_PUBLIC, "Public" },
376 { FN_RANGE, "Range" },
377 { FN_REFERER, "Referer" },
378 { FN_RETRY_AFTER, "Retry-After" },
379 { FN_SERVER, "Server" },
380 { FN_TRANSFER_ENCODING, "Transfer-Encoding" },
381 { FN_UPGRADE, "Upgrade" },
382 { FN_USER_AGENT, "User-Agent" },
385 { FN_WARNING, "Warning" },
386 { FN_WWW_AUTHENTICATE, "WWW-Authenticate" },
387 { FN_CONTENT_DISPOSITION, "Content-Disposition" },
388 { FN_X_WAP_APPLICATION_ID, "X-Wap-Application-ID" },
389 { FN_X_WAP_CONTENT_URI, "X-Wap-Content-URI" },
390 { FN_X_WAP_INITIATOR_URI, "X-Wap-Initiator-URI" },
391 { FN_ACCEPT_APPLICATION, "Accept-Application" },
392 { FN_BEARER_INDICATION, "Bearer-Indication" },
393 { FN_PUSH_FLAG, "Push-Flag" },
394 { FN_PROFILE, "Profile" },
395 { FN_PROFILE_DIFF, "Profile-Diff" },
396 { FN_PROFILE_WARNING, "Profile-Warning" },
397 { FN_EXPECT, "Expect" },
399 { FN_TRAILER, "Trailer" },
400 { FN_ACCEPT_CHARSET, "Accept-Charset" },
401 { FN_ACCEPT_ENCODING, "Accept-Encoding" },
402 { FN_CACHE_CONTROL, "Cache-Control" },
403 { FN_CONTENT_RANGE, "Content-Range" },
404 { FN_X_WAP_TOD, "X-Wap-Tod" },
405 { FN_CONTENT_ID, "Content-ID" },
406 { FN_SET_COOKIE, "Set-Cookie" },
407 { FN_COOKIE, "Cookie" },
408 { FN_ENCODING_VERSION, "Encoding-Version" },
409 { FN_PROFILE_WARNING14, "Profile-Warning (encoding 1.4)" },
410 { FN_CONTENT_DISPOSITION14,"Content-Disposition (encoding 1.4)" },
411 { FN_X_WAP_SECURITY, "X-WAP-Security" },
412 { FN_CACHE_CONTROL14, "Cache-Control (encoding 1.4)" },
417 * Bearer types (from the WDP specification).
421 #define BT_GSM_USSD 0x02
422 #define BT_GSM_SMS 0x03
423 #define BT_ANSI_136_GUTS 0x04
424 #define BT_IS_95_SMS 0x05
425 #define BT_IS_95_CSD 0x06
426 #define BT_IS_95_PACKET_DATA 0x07
427 #define BT_ANSI_136_CSD 0x08
428 #define BT_ANSI_136_PACKET_DATA 0x09
429 #define BT_GSM_CSD 0x0A
430 #define BT_GSM_GPRS 0x0B
431 #define BT_GSM_USSD_IPv4 0x0C
432 #define BT_AMPS_CDPD 0x0D
433 #define BT_PDC_CSD 0x0E
434 #define BT_PDC_PACKET_DATA 0x0F
435 #define BT_IDEN_SMS 0x10
436 #define BT_IDEN_CSD 0x11
437 #define BT_IDEN_PACKET_DATA 0x12
438 #define BT_PAGING_FLEX 0x13
439 #define BT_PHS_SMS 0x14
440 #define BT_PHS_CSD 0x15
441 #define BT_GSM_USSD_GSM_SC 0x16
442 #define BT_TETRA_SDS_ITSI 0x17
443 #define BT_TETRA_SDS_MSISDN 0x18
444 #define BT_TETRA_PACKET_DATA 0x19
445 #define BT_PAGING_REFLEX 0x1A
446 #define BT_GSM_USSD_MSISDN 0x1B
447 #define BT_MOBITEX_MPAK 0x1C
448 #define BT_ANSI_136_GHOST 0x1D
450 static const value_string vals_bearer_types[] = {
453 { BT_GSM_USSD, "GSM USSD" },
454 { BT_GSM_SMS, "GSM SMS" },
455 { BT_ANSI_136_GUTS, "ANSI-136 GUTS/R-Data" },
456 { BT_IS_95_SMS, "IS-95 CDMA SMS" },
457 { BT_IS_95_CSD, "IS-95 CDMA CSD" },
458 { BT_IS_95_PACKET_DATA, "IS-95 CDMA Packet data" },
459 { BT_ANSI_136_CSD, "ANSI-136 CSD" },
460 { BT_ANSI_136_PACKET_DATA, "ANSI-136 Packet data" },
461 { BT_GSM_CSD, "GSM CSD" },
462 { BT_GSM_GPRS, "GSM GPRS" },
463 { BT_GSM_USSD_IPv4, "GSM USSD (IPv4 addresses)" },
464 { BT_AMPS_CDPD, "AMPS CDPD" },
465 { BT_PDC_CSD, "PDC CSD" },
466 { BT_PDC_PACKET_DATA, "PDC Packet data" },
467 { BT_IDEN_SMS, "IDEN SMS" },
468 { BT_IDEN_CSD, "IDEN CSD" },
469 { BT_IDEN_PACKET_DATA, "IDEN Packet data" },
470 { BT_PAGING_FLEX, "Paging network FLEX(TM)" },
471 { BT_PHS_SMS, "PHS SMS" },
472 { BT_PHS_CSD, "PHS CSD" },
473 { BT_GSM_USSD_GSM_SC, "GSM USSD (GSM Service Code addresses)" },
474 { BT_TETRA_SDS_ITSI, "TETRA SDS (ITSI addresses)" },
475 { BT_TETRA_SDS_MSISDN, "TETRA SDS (MSISDN addresses)" },
476 { BT_TETRA_PACKET_DATA, "TETRA Packet data" },
477 { BT_PAGING_REFLEX, "Paging network ReFLEX(TM)" },
478 { BT_GSM_USSD_MSISDN, "GSM USSD (MSISDN addresses)" },
479 { BT_MOBITEX_MPAK, "Mobitex MPAK" },
480 { BT_ANSI_136_GHOST, "ANSI-136 GHOST/R-Data" },
484 static const value_string vals_content_types[] = {
487 { 0x02, "text/html" },
488 { 0x03, "text/plain" },
489 { 0x04, "text/x-hdml" },
490 { 0x05, "text/x-ttml" },
491 { 0x06, "text/x-vCalendar" },
492 { 0x07, "text/x-vCard" },
493 { 0x08, "text/vnd.wap.wml" },
494 { 0x09, "text/vnd.wap.wmlscript" },
495 { 0x0A, "text/vnd.wap.channel" },
496 { 0x0B, "Multipart/*" },
497 { 0x0C, "Multipart/mixed" },
498 { 0x0D, "Multipart/form-data" },
499 { 0x0E, "Multipart/byteranges" },
500 { 0x0F, "Multipart/alternative" },
501 { 0x10, "application/*" },
502 { 0x11, "application/java-vm" },
503 { 0x12, "application/x-www-form-urlencoded" },
504 { 0x13, "application/x-hdmlc" },
505 { 0x14, "application/vnd.wap.wmlc" },
506 { 0x15, "application/vnd.wap.wmlscriptc" },
507 { 0x16, "application/vnd.wap.channelc" },
508 { 0x17, "application/vnd.wap.uaprof" },
509 { 0x18, "application/vnd.wap.wtls-ca-certificate" },
510 { 0x19, "application/vnd.wap.wtls-user-certificate" },
511 { 0x1A, "application/x-x509-ca-cert" },
512 { 0x1B, "application/x-x509-user-cert" },
514 { 0x1D, "image/gif" },
515 { 0x1E, "image/jpeg" },
516 { 0x1F, "image/tiff" },
517 { 0x20, "image/png" },
518 { 0x21, "image/vnd.wap.wbmp" },
519 { 0x22, "application/vnd.wap.multipart.*" },
520 { 0x23, "application/vnd.wap.multipart.mixed" },
521 { 0x24, "application/vnd.wap.multipart.form-data" },
522 { 0x25, "application/vnd.wap.multipart.byteranges" },
523 { 0x26, "application/vnd.wap.multipart.alternative" },
524 { 0x27, "application/xml" },
525 { 0x28, "text/xml" },
526 { 0x29, "application/vnd.wap.wbxml" },
527 { 0x2A, "application/x-x968-cross-cert" },
528 { 0x2B, "application/x-x968-ca-cert" },
529 { 0x2C, "application/x-x968-user-cert" },
530 { 0x2D, "text/vnd.wap.si" },
531 { 0x2E, "application/vnd.wap.sic" },
532 { 0x2F, "text/vnd.wap.sl" },
533 { 0x30, "application/vnd.wap.slc" },
534 { 0x31, "text/vnd.wap.co" },
535 { 0x32, "application/vnd.wap.coc" },
536 { 0x33, "application/vnd.wap.multipart.related" },
537 { 0x34, "application/vnd.wap.sia" },
538 { 0x35, "text/vnd.wap.connectivity-xml" },
539 { 0x36, "application/vnd.wap.connectivity-wbxml" },
540 { 0x37, "application/pkcs7-mime" },
541 { 0x38, "application/vnd.wap.hashed-certificate" },
542 { 0x39, "application/vnd.wap.signed-certificate" },
543 { 0x3A, "application/vnd.wap.cert-response" },
544 { 0x3B, "application/xhtml+xml" },
545 { 0x3C, "application/wml+xml" },
546 { 0x3D, "text/css" },
547 { 0x3E, "application/vnd.wap.mms-message" },
548 { 0x3F, "application/vnd.wap.rollover-certificate" },
552 static const value_string vals_languages[] = {
553 { 0x01, "Afar (aa)" },
554 { 0x02, "Abkhazian (ab)" },
555 { 0x03, "Afrikaans (af)" },
556 { 0x04, "Amharic (am)" },
557 { 0x05, "Arabic (ar)" },
558 { 0x06, "Assamese (as)" },
559 { 0x07, "Aymara (ay)" },
560 { 0x08, "Azerbaijani (az)" },
561 { 0x09, "Bashkir (ba)" },
562 { 0x0A, "Byelorussian (be)" },
563 { 0x0B, "Bulgarian (bg)" },
564 { 0x0C, "Bihari (bh)" },
565 { 0x0D, "Bislama (bi)" },
566 { 0x0E, "Bengali; Bangla (bn)" },
567 { 0x0F, "Tibetan (bo)" },
568 { 0x10, "Breton (br)" },
569 { 0x11, "Catalan (ca)" },
570 { 0x12, "Corsican (co)" },
571 { 0x13, "Czech (cs)" },
572 { 0x14, "Welsh (cy)" },
573 { 0x15, "Danish (da)" },
574 { 0x16, "German (de)" },
575 { 0x17, "Bhutani (dz)" },
576 { 0x18, "Greek (el)" },
577 { 0x19, "English (en)" },
578 { 0x1A, "Esperanto (eo)" },
579 { 0x1B, "Spanish (es)" },
580 { 0x1C, "Estonian (et)" },
581 { 0x1D, "Basque (eu)" },
582 { 0x1E, "Persian (fa)" },
583 { 0x1F, "Finnish (fi)" },
584 { 0x20, "Fiji (fj)" },
585 { 0x22, "French (fr)" },
586 { 0x24, "Irish (ga)" },
587 { 0x25, "Scots Gaelic (gd)" },
588 { 0x26, "Galician (gl)" },
589 { 0x27, "Guarani (gn)" },
590 { 0x28, "Gujarati (gu)" },
591 { 0x29, "Hausa (ha)" },
592 { 0x2A, "Hebrew (formerly iw) (he)" },
593 { 0x2B, "Hindi (hi)" },
594 { 0x2C, "Croatian (hr)" },
595 { 0x2D, "Hungarian (hu)" },
596 { 0x2E, "Armenian (hy)" },
597 { 0x30, "Indonesian (formerly in) (id)" },
598 { 0x47, "Maori (mi)" },
599 { 0x48, "Macedonian (mk)" },
600 { 0x49, "Malayalam (ml)" },
601 { 0x4A, "Mongolian (mn)" },
602 { 0x4B, "Moldavian (mo)" },
603 { 0x4C, "Marathi (mr)" },
604 { 0x4D, "Malay (ms)" },
605 { 0x4E, "Maltese (mt)" },
606 { 0x4F, "Burmese (my)" },
607 { 0x51, "Nepali (ne)" },
608 { 0x52, "Dutch (nl)" },
609 { 0x53, "Norwegian (no)" },
610 { 0x54, "Occitan (oc)" },
611 { 0x55, "(Afan) Oromo (om)" },
612 { 0x56, "Oriya (or)" },
613 { 0x57, "Punjabi (pa)" },
614 { 0x58, "Polish (po)" },
615 { 0x59, "Pashto, Pushto (ps)" },
616 { 0x5A, "Portuguese (pt)" },
617 { 0x5B, "Quechua (qu)" },
618 { 0x5D, "Kirundi (rn)" },
619 { 0x5E, "Romanian (ro)" },
620 { 0x5F, "Russian (ru)" },
621 { 0x60, "Kinyarwanda (rw)" },
622 { 0x61, "Sanskrit (sa)" },
623 { 0x62, "Sindhi (sd)" },
624 { 0x63, "Sangho (sg)" },
625 { 0x64, "Serbo-Croatian (sh)" },
626 { 0x65, "Sinhalese (si)" },
627 { 0x66, "Slovak (sk)" },
628 { 0x67, "Slovenian (sl)" },
629 { 0x68, "Samoan (sm)" },
630 { 0x69, "Shona (sn)" },
631 { 0x6A, "Somali (so)" },
632 { 0x6B, "Albanian (sq)" },
633 { 0x6C, "Serbian (sr)" },
634 { 0x6D, "Siswati (ss)" },
635 { 0x6E, "Sesotho (st)" },
636 { 0x6F, "Sundanese (su)" },
637 { 0x70, "Swedish (sv)" },
638 { 0x71, "Swahili (sw)" },
639 { 0x72, "Tamil (ta)" },
640 { 0x73, "Telugu (te)" },
641 { 0x74, "Tajik (tg)" },
642 { 0x75, "Thai (th)" },
643 { 0x76, "Tigrinya (ti)" },
644 { 0x81, "Nauru (na)" },
645 { 0x82, "Faeroese (fo)" },
646 { 0x83, "Frisian (fy)" },
647 { 0x84, "Interlingua (ia)" },
648 { 0x8C, "Rhaeto-Romance (rm)" },
652 static const value_string vals_accept_ranges[] = {
658 #define NO_CACHE 0x00
659 #define NO_STORE 0x01
661 #define MAX_STALE 0x03
662 #define MIN_FRESH 0x04
663 #define ONLY_IF_CACHED 0x05
666 #define NO_TRANSFORM 0x08
667 #define MUST_REVALIDATE 0x09
668 #define PROXY_REVALIDATE 0x0A
669 #define S_MAXAGE 0x0B
671 static const value_string vals_cache_control[] = {
672 { NO_CACHE, "No-cache" },
673 { NO_STORE, "No-store" },
674 { MAX_AGE, "Max-age" },
675 { MAX_STALE, "Max-stale" },
676 { MIN_FRESH, "Min-fresh" },
677 { ONLY_IF_CACHED, "Only-if-cached" },
678 { PUBLIC, "Public" },
679 { PRIVATE, "Private" },
680 { NO_TRANSFORM, "No-transform" },
681 { MUST_REVALIDATE, "Must-revalidate" },
682 { PROXY_REVALIDATE, "Proxy-revalidate" },
683 { S_MAXAGE, "S-max-age" },
687 static const value_string vals_connection[] = {
692 static const value_string vals_transfer_encoding[] = {
700 #define PERMANENT_REDIRECT 0x80
701 #define REUSE_SECURITY_SESSION 0x40
704 * Redirect address flags and length.
706 #define BEARER_TYPE_INCLUDED 0x80
707 #define PORT_NUMBER_INCLUDED 0x40
708 #define ADDRESS_LEN 0x3f
710 static const true_false_string yes_no_truth = {
716 * Windows appears to define DELETE.
726 REDIRECT = 0x03, /* No sample data */
729 PUSH = 0x06, /* No sample data */
730 CONFIRMEDPUSH = 0x07, /* No sample data */
731 SUSPEND = 0x08, /* No sample data */
732 RESUME = 0x09, /* No sample data */
735 OPTIONS = 0x41, /* No sample data */
736 HEAD = 0x42, /* No sample data */
737 DELETE = 0x43, /* No sample data */
738 TRACE = 0x44, /* No sample data */
741 PUT = 0x61, /* No sample data */
746 VALUE_IS_TEXT_STRING,
750 static heur_dissector_list_t heur_subdissector_list;
752 static void add_uri (proto_tree *, frame_data *, tvbuff_t *, guint, guint);
753 static void add_headers (proto_tree *, tvbuff_t *);
754 static int add_well_known_header (proto_tree *, tvbuff_t *, int, guint8);
755 static int add_unknown_header (proto_tree *, tvbuff_t *, int, guint8);
756 static int add_application_header (proto_tree *, tvbuff_t *, int);
757 static void add_accept_header (proto_tree *, tvbuff_t *, int,
758 tvbuff_t *, value_type_t, int);
759 static void add_accept_xxx_header (proto_tree *, tvbuff_t *, int,
760 tvbuff_t *, value_type_t, int, int, int, const value_string *,
762 static void add_accept_ranges_header (proto_tree *, tvbuff_t *, int,
763 tvbuff_t *, value_type_t, int);
764 static void add_cache_control_header (proto_tree *, tvbuff_t *, int,
765 tvbuff_t *, value_type_t, int);
766 static int add_cache_control_field_name (proto_tree *, tvbuff_t *, int, guint);
767 static void add_connection_header (proto_tree *, tvbuff_t *, int,
768 tvbuff_t *, value_type_t, int);
769 static void add_content_type_value (proto_tree *, tvbuff_t *, int, int,
770 tvbuff_t *, value_type_t, int, int, int, guint *, const char **);
771 static guint add_content_type (proto_tree *, tvbuff_t *, guint, guint *,
773 static void add_wap_application_id_header (proto_tree *, tvbuff_t *, int,
774 tvbuff_t *, value_type_t, int);
775 static void add_integer_value_header (proto_tree *, tvbuff_t *, int,
776 tvbuff_t *, value_type_t, int, int, guint8);
777 static void add_string_value_header (proto_tree *, tvbuff_t *, int,
778 tvbuff_t *, value_type_t, int, int, guint8);
779 static void add_date_value_header (proto_tree *, tvbuff_t *, int,
780 tvbuff_t *, value_type_t, int, int, guint8);
781 static int add_parameter (proto_tree *, tvbuff_t *, int);
782 static void add_untyped_parameter (proto_tree *, tvbuff_t *, int, int);
783 static void add_parameter_charset (proto_tree *, tvbuff_t *, int, int);
784 static void add_parameter_type (proto_tree *, tvbuff_t *, int, int);
785 static void add_parameter_text (proto_tree *, tvbuff_t *, int, int, int,
786 const char *paramName);
787 static void add_post_data (proto_tree *, tvbuff_t *, guint, const char *);
788 static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
789 static void add_pragma_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
791 static void add_transfer_encoding_header (proto_tree *, tvbuff_t *, int,
792 tvbuff_t *, value_type_t, int);
793 static void add_warning_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
795 static void add_accept_application_header (proto_tree *, tvbuff_t *, int,
796 tvbuff_t *, value_type_t, int);
797 static void add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type);
798 static void add_capability_vals(tvbuff_t *tvb, gboolean add_string,
799 int offsetStr, guint length, guint capabilitiesStart, char *valString,
800 size_t valStringSize);
801 static value_type_t get_value_type_len (tvbuff_t *, int, guint *, int *, int *);
802 static guint get_uintvar (tvbuff_t *, guint, guint);
803 static gint get_integer (tvbuff_t *, guint, guint, value_type_t, guint *);
805 /* Code to actually dissect the packets */
807 dissect_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
808 proto_tree *tree, dissector_handle_t dissector_handle)
812 proto_tree *flags_tree;
814 guint8 address_flags_len;
816 proto_tree *atf_tree;
818 guint32 address_ipv4;
819 struct e_in6_addr address_ipv6;
820 address redir_address;
821 conversation_t *conv;
823 flags = tvb_get_guint8 (tvb, offset);
825 ti = proto_tree_add_uint (tree, hf_wsp_redirect_flags,
826 tvb, offset, 1, flags);
827 flags_tree = proto_item_add_subtree (ti, ett_redirect_flags);
828 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_permanent,
829 tvb, offset, 1, flags);
830 proto_tree_add_boolean (flags_tree, hf_wsp_redirect_reuse_security_session,
831 tvb, offset, 1, flags);
834 while (tvb_reported_length_remaining (tvb, offset) > 0) {
835 address_flags_len = tvb_get_guint8 (tvb, offset);
837 ti = proto_tree_add_uint (tree, hf_wsp_redirect_afl,
838 tvb, offset, 1, address_flags_len);
839 atf_tree = proto_item_add_subtree (ti, ett_redirect_afl);
840 proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_bearer_type_included,
841 tvb, offset, 1, address_flags_len);
842 proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_port_number_included,
843 tvb, offset, 1, address_flags_len);
844 proto_tree_add_uint (atf_tree, hf_wsp_redirect_afl_address_len,
845 tvb, offset, 1, address_flags_len);
848 if (address_flags_len & BEARER_TYPE_INCLUDED) {
849 bearer_type = tvb_get_guint8 (tvb, offset);
851 proto_tree_add_uint (tree, hf_wsp_redirect_bearer_type,
852 tvb, offset, 1, bearer_type);
856 bearer_type = 0x00; /* XXX */
857 if (address_flags_len & PORT_NUMBER_INCLUDED) {
858 port_num = tvb_get_ntohs (tvb, offset);
860 proto_tree_add_uint (tree, hf_wsp_redirect_port_num,
861 tvb, offset, 2, port_num);
866 * Redirecting to the same server port number as was
867 * being used, i.e. the source port number of this
870 port_num = pinfo->srcport;
872 address_len = address_flags_len & ADDRESS_LEN;
873 if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
875 * We don't have the bearer type in the message,
876 * so we don't know the address type.
877 * (It's the same bearer type as the original
880 goto unknown_address_type;
884 * We know the bearer type, so we know the address type.
886 switch (bearer_type) {
890 case BT_IS_95_PACKET_DATA:
891 case BT_ANSI_136_CSD:
892 case BT_ANSI_136_PACKET_DATA:
895 case BT_GSM_USSD_IPv4:
898 case BT_PDC_PACKET_DATA:
900 case BT_IDEN_PACKET_DATA:
902 case BT_TETRA_PACKET_DATA:
906 if (address_len != 4) {
910 goto unknown_address_type;
912 tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
914 proto_tree_add_ipv4 (tree,
915 hf_wsp_redirect_ipv4_addr,
916 tvb, offset, 4, address_ipv4);
920 * Create a conversation so that the
921 * redirected session will be dissected
924 redir_address.type = AT_IPv4;
925 redir_address.len = 4;
926 redir_address.data = (const guint8 *)&address_ipv4;
927 conv = find_conversation(&redir_address, &pinfo->dst,
928 PT_UDP, port_num, 0, NO_PORT_B);
930 conv = conversation_new(&redir_address,
931 &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
933 conversation_set_dissector(conv, dissector_handle);
940 if (address_len != 16) {
944 goto unknown_address_type;
946 tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
948 proto_tree_add_ipv6 (tree,
949 hf_wsp_redirect_ipv6_addr,
950 tvb, offset, 16, (guint8 *)&address_ipv6);
954 * Create a conversation so that the
955 * redirected session will be dissected
958 redir_address.type = AT_IPv6;
959 redir_address.len = 16;
960 redir_address.data = (const guint8 *)&address_ipv4;
961 conv = find_conversation(&redir_address, &pinfo->dst,
962 PT_UDP, port_num, 0, NO_PORT_B);
964 conv = conversation_new(&redir_address,
965 &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
967 conversation_set_dissector(conv, dissector_handle);
970 unknown_address_type:
972 if (address_len != 0) {
974 proto_tree_add_item (tree,
975 hf_wsp_redirect_addr,
976 tvb, offset, address_len,
982 offset += address_len;
987 dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
988 dissector_handle_t dissector_handle, gboolean is_connectionless)
990 frame_data *fdata = pinfo->fd;
998 guint capabilityLength = 0;
999 guint capabilityStart = 0;
1000 guint headersLength = 0;
1001 guint headerLength = 0;
1002 guint headerStart = 0;
1003 guint nextOffset = 0;
1004 guint contentTypeStart = 0;
1005 guint contentType = 0;
1006 const char *contentTypeStr;
1009 /* Set up structures we will need to add the protocol subtree and manage it */
1011 proto_tree *wsp_tree = NULL;
1012 /* proto_tree *wsp_header_fixed; */
1014 /* This field shows up as the "Info" column in the display; you should make
1015 it, if possible, summarize what's in the packet, so that a user looking
1016 at the list of packets can tell what type of packet it is. */
1018 /* Connection-less mode has a TID first */
1019 if (is_connectionless)
1024 /* Find the PDU type */
1025 pdut = tvb_get_guint8 (tvb, offset);
1027 /* Develop the string to put in the Info column */
1028 if (check_col(fdata, COL_INFO))
1030 col_append_fstr(fdata, COL_INFO, "WSP %s",
1031 val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"));
1034 /* In the interest of speed, if "tree" is NULL, don't do any work not
1035 necessary to generate protocol tree items. */
1037 ti = proto_tree_add_item(tree, proto_wsp, tvb, 0,
1038 tvb_length(tvb), bo_little_endian);
1039 wsp_tree = proto_item_add_subtree(ti, ett_wsp);
1041 /* Code to process the packet goes here */
1043 wsp_header_fixed = proto_item_add_subtree(ti, ett_header );
1046 /* Add common items: only TID and PDU Type */
1048 /* If this is connectionless, then the TID Field is always first */
1049 if (is_connectionless)
1051 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,tvb,
1052 0,1,bo_little_endian);
1055 ti = proto_tree_add_item(
1056 wsp_tree, /* tree */
1057 hf_wsp_header_pdu_type, /* id */
1059 offset, /* start of high light */
1060 1, /* length of high light */
1061 bo_little_endian /* value */
1072 if (pdut == CONNECT)
1074 ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,tvb,offset,1,bo_little_endian);
1075 ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,tvb,offset,1,bo_little_endian);
1078 count = 0; /* Initialise count */
1079 value = tvb_get_guintvar (tvb, offset, &count);
1080 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1083 capabilityStart = offset;
1084 count = 0; /* Initialise count */
1085 capabilityLength = tvb_get_guintvar (tvb, offset, &count);
1087 ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,tvb,capabilityStart,count,capabilityLength);
1091 count = 0; /* Initialise count */
1092 headerLength = tvb_get_guintvar (tvb, offset, &count);
1093 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headerLength);
1095 capabilityStart = offset;
1096 headerStart = capabilityStart + capabilityLength;
1098 /* Resume computes the headerlength by remaining bytes */
1099 capabilityStart = offset;
1100 headerStart = capabilityStart + capabilityLength;
1101 headerLength = tvb_reported_length_remaining (tvb, headerStart);
1103 if (capabilityLength > 0)
1105 tmp_tvb = tvb_new_subset (tvb, offset, capabilityLength, capabilityLength);
1106 add_capabilities (wsp_tree, tmp_tvb, pdut);
1107 offset += capabilityLength;
1110 if (headerLength > 0)
1112 tmp_tvb = tvb_new_subset (tvb, offset, headerLength, headerLength);
1113 add_headers (wsp_tree, tmp_tvb);
1120 dissect_redirect(tvb, offset, pinfo, wsp_tree,
1127 count = 0; /* Initialise count */
1128 value = tvb_get_guintvar (tvb, offset, &count);
1129 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
1134 count = 0; /* Initialise count */
1135 /* Length of URI and size of URILen field */
1136 value = tvb_get_guintvar (tvb, offset, &count);
1137 nextOffset = offset + count;
1138 add_uri (wsp_tree, fdata, tvb, offset, nextOffset);
1140 offset += (value+count); /* VERIFY */
1141 tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
1142 add_headers (wsp_tree, tmp_tvb);
1148 count = 0; /* Initialise count */
1149 uriLength = tvb_get_guintvar (tvb, offset, &count);
1150 headerStart = uriStart+count;
1151 count = 0; /* Initialise count */
1152 headersLength = tvb_get_guintvar (tvb, headerStart, &count);
1153 offset = headerStart + count;
1155 add_uri (wsp_tree, fdata, tvb, uriStart, offset);
1157 offset += uriLength;
1159 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,headersLength);
1161 if (headersLength == 0)
1164 contentTypeStart = offset;
1165 nextOffset = add_content_type (wsp_tree,
1166 tvb, offset, &contentType,
1169 /* Add headers subtree that will hold the headers fields */
1170 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1171 headerLength = headersLength-(nextOffset-contentTypeStart);
1172 if (headerLength > 0)
1174 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1175 add_headers (wsp_tree, tmp_tvb);
1178 /* TODO: Post DATA */
1179 /* Runs from start of headers+headerLength to end of frame */
1180 offset = nextOffset+headerLength;
1181 tmp_tvb = tvb_new_subset (tvb, offset, tvb_reported_length (tvb)-offset, tvb_reported_length (tvb)-offset);
1182 add_post_data (wsp_tree, tmp_tvb,
1183 contentType, contentTypeStr);
1185 if (tvb_reported_length_remaining(tvb, headerStart + count + uriLength + headersLength) > 0)
1187 tmp_tvb = tvb_new_subset (tvb, headerStart + count + uriLength + headersLength, -1, -1);
1188 dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
1193 count = 0; /* Initialise count */
1194 headersLength = tvb_get_guintvar (tvb, offset+1, &count);
1195 headerStart = offset + count + 1;
1197 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
1198 nextOffset = offset + 1 + count;
1199 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset+1,count,headersLength);
1201 if (headersLength == 0)
1204 contentTypeStart = nextOffset;
1205 nextOffset = add_content_type (wsp_tree,
1206 tvb, nextOffset, &contentType,
1209 /* Add headers subtree that will hold the headers fields */
1210 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1211 headerLength = headersLength-(nextOffset-contentTypeStart);
1212 if (headerLength > 0)
1214 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1215 add_headers (wsp_tree, tmp_tvb);
1217 offset += count+headersLength+1;
1219 /* TODO: Data - decode WMLC */
1220 /* Runs from offset+1+count+headerLength+1 to end of frame */
1221 if (tvb_reported_length_remaining (tvb, offset) > 0)
1223 ti = proto_tree_add_item (wsp_tree, hf_wsp_reply_data,tvb,offset,tvb_length_remaining(tvb, offset),bo_little_endian);
1226 if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1228 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1229 dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
1235 count = 0; /* Initialise count */
1236 headersLength = tvb_get_guintvar (tvb, offset, &count);
1237 headerStart = offset + count;
1240 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headersLength);
1242 if (headersLength == 0)
1246 contentTypeStart = offset;
1247 nextOffset = add_content_type (wsp_tree,
1248 tvb, offset, &contentType,
1251 /* Add headers subtree that will hold the headers fields */
1252 /* Runs from nextOffset for headersLength-(length of content-type field)*/
1253 headerLength = headersLength-(nextOffset-contentTypeStart);
1254 if (headerLength > 0)
1256 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
1257 add_headers (wsp_tree, tmp_tvb);
1259 offset += headersLength;
1262 if (tvb_reported_length_remaining (tvb, offset) > 0)
1264 ti = proto_tree_add_item (wsp_tree, hf_wsp_push_data,tvb,offset,tvb_length_remaining(tvb, offset),bo_little_endian);
1267 if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
1269 tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
1270 dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
1278 * Called directly from UDP.
1279 * Put "WSP" into the "Protocol" column.
1282 dissect_wsp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1284 if (check_col(pinfo->fd, COL_PROTOCOL))
1285 col_set_str(pinfo->fd, COL_PROTOCOL, "WSP" );
1286 if (check_col(pinfo->fd, COL_INFO))
1287 col_clear(pinfo->fd, COL_INFO);
1289 dissect_wsp_common(tvb, pinfo, tree, wsp_fromudp_handle, TRUE);
1293 * Called from a higher-level WAP dissector, in connection-oriented mode.
1294 * Leave the "Protocol" column alone - the dissector calling us should
1298 dissect_wsp_fromwap_co(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1301 * XXX - what about WTLS->WTP->WSP?
1303 dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, FALSE);
1307 * Called from a higher-level WAP dissector, in connectionless mode.
1308 * Leave the "Protocol" column alone - the dissector calling us should
1312 dissect_wsp_fromwap_cl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1315 * XXX - what about WTLS->WSP?
1317 if (check_col(pinfo->fd, COL_INFO))
1319 col_clear(pinfo->fd, COL_INFO);
1321 dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, TRUE);
1325 add_uri (proto_tree *tree, frame_data *fdata, tvbuff_t *tvb, guint URILenOffset, guint URIOffset)
1331 guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
1334 ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,tvb,URILenOffset,count,uriLen);
1336 newBuffer = g_malloc (uriLen+2);
1337 newBuffer[0] = ' '; /* This is for COL_INFO */
1338 strncpy (newBuffer+1, tvb_get_ptr (tvb, URIOffset, uriLen), uriLen);
1339 newBuffer[uriLen+1] = 0;
1341 ti = proto_tree_add_string (tree, hf_wsp_header_uri,tvb,URIOffset,uriLen,newBuffer+1);
1342 if (check_col(fdata, COL_INFO)) {
1343 col_append_str(fdata, COL_INFO, newBuffer);
1349 add_headers (proto_tree *tree, tvbuff_t *tvb)
1352 proto_tree *wsp_headers;
1354 guint headersLen = tvb_reported_length (tvb);
1355 guint headerStart = 0;
1360 fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, headersLen);
1364 if (headersLen <= 0)
1370 fprintf (stderr, "dissect_wsp: Headers to process\n");
1373 ti = proto_tree_add_item (tree, hf_wsp_headers_section,tvb,offset,headersLen,bo_little_endian);
1374 wsp_headers = proto_item_add_subtree( ti, ett_headers );
1378 while (offset < headersLen)
1380 /* Loop round each header */
1381 headerStart = offset;
1382 peek = tvb_get_guint8 (tvb, headerStart);
1384 if (peek < 32) /* Short-cut shift delimiter */
1387 proto_tree_add_uint (wsp_headers,
1388 hf_wsp_header_shift_code, tvb, offset, 1,
1393 else if (peek == 0x7F) /* Shift delimiter */
1395 pageCode = tvb_get_guint8(tvb, offset+1);
1396 proto_tree_add_uint (wsp_headers,
1397 hf_wsp_header_shift_code, tvb, offset, 2,
1402 else if (peek < 127)
1405 fprintf (stderr, "dissect_wsp: header: application-header start %d (0x%02X)\n", peek, peek);
1408 * Token-text, followed by Application-specific-value.
1410 offset = add_application_header (wsp_headers, tvb,
1413 else if (peek & 0x80)
1416 fprintf (stderr, "dissect_wsp: header: well-known %d (0x%02X)\n", peek, peek);
1419 * Well-known-header; the lower 7 bits of "peek"
1420 * are the header code.
1424 offset = add_well_known_header (wsp_headers,
1425 tvb, headerStart, peek & 0x7F);
1429 offset = add_unknown_header (wsp_headers,
1430 tvb, headerStart, peek & 0x7F);
1437 add_well_known_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1441 value_type_t valueType;
1445 tvbuff_t *header_buff;
1446 tvbuff_t *value_buff;
1449 fprintf (stderr, "dissect_wsp: Got header 0x%02x\n", headerType);
1451 headerStart = offset;
1454 * Skip the Short-Integer header type.
1459 * Get the value type and length (or, if the type is VALUE_IN_LEN,
1460 * meaning the value is a Short-integer, get the value type
1461 * and the value itself).
1463 valueType = get_value_type_len (tvb, offset, &valueLen,
1464 &valueStart, &offset);
1465 headerLen = offset - headerStart;
1468 * Get a tvbuff for the entire header.
1469 * XXX - cut the actual length short so that it doesn't run
1470 * past the actual length of tvb.
1472 header_buff = tvb_new_subset (tvb, headerStart, headerLen,
1476 * If the value wasn't in the length, get a tvbuff for the value.
1477 * XXX - can valueLen be 0?
1478 * XXX - cut the actual length short so that it doesn't run
1479 * past the actual length of tvb.
1481 if (valueType != VALUE_IN_LEN) {
1482 value_buff = tvb_new_subset (tvb, valueStart, valueLen,
1486 * XXX - when the last dissector is tvbuffified,
1487 * so that NULL is no longer a valid tvb pointer
1488 * value in "proto_tree_add" calls, just
1489 * set "value_buff" to NULL.
1491 * XXX - can we already do that? I.e., will that
1492 * cause us always to crash if we mistakenly try
1493 * to fetch the value of a VALUE_IN_LEN item?
1495 value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
1498 switch (headerType) {
1500 case FN_ACCEPT: /* Accept */
1501 add_accept_header (tree, header_buff, headerLen,
1502 value_buff, valueType, valueLen);
1505 case FN_ACCEPT_CHARSET_DEP: /* Accept-Charset */
1507 * XXX - should both encoding versions 1.1 and
1508 * 1.3 be handled this way?
1510 add_accept_xxx_header (tree, header_buff, headerLen,
1511 value_buff, valueType, valueLen,
1512 hf_wsp_header_accept_charset,
1513 hf_wsp_header_accept_charset_str,
1514 vals_character_sets, "Unknown charset (%u)");
1517 case FN_ACCEPT_LANGUAGE: /* Accept-Language */
1518 add_accept_xxx_header (tree, header_buff, headerLen,
1519 value_buff, valueType, valueLen,
1520 hf_wsp_header_accept_language,
1521 hf_wsp_header_accept_language_str,
1522 vals_languages, "Unknown language (%u)");
1525 case FN_ACCEPT_RANGES: /* Accept-Ranges */
1526 add_accept_ranges_header (tree, header_buff, headerLen,
1527 value_buff, valueType, valueLen);
1530 case FN_AGE: /* Age */
1531 add_integer_value_header (tree, header_buff, headerLen,
1532 value_buff, valueType, valueLen, hf_wsp_header_age,
1536 case FN_CACHE_CONTROL_DEP: /* Cache-Control */
1537 case FN_CACHE_CONTROL:
1538 case FN_CACHE_CONTROL14:
1540 * XXX - is the only difference in the three different
1541 * versions (1.1, 1.3, 1.4) really only S_MAXAGE?
1543 add_cache_control_header (tree, header_buff, headerLen,
1544 value_buff, valueType, valueLen);
1547 case FN_CONNECTION: /* Connection */
1548 add_connection_header (tree, header_buff, headerLen,
1549 value_buff, valueType, valueLen);
1552 case FN_CONTENT_LENGTH: /* Content-Length */
1553 add_integer_value_header (tree, header_buff, headerLen,
1554 value_buff, valueType, valueLen,
1555 hf_wsp_header_content_length,
1559 case FN_DATE: /* Date */
1560 add_date_value_header (tree, header_buff, headerLen,
1561 value_buff, valueType, valueLen,
1562 hf_wsp_header_date, headerType);
1565 case FN_ETAG: /* Etag */
1566 add_string_value_header (tree, header_buff, headerLen,
1567 value_buff, valueType, valueLen,
1568 hf_wsp_header_etag, headerType);
1571 case FN_EXPIRES: /* Expires */
1572 add_date_value_header (tree, header_buff, headerLen,
1573 value_buff, valueType, valueLen,
1574 hf_wsp_header_expires, headerType);
1577 case FN_IF_MODIFIED_SINCE: /* If-Modified-Since */
1578 add_date_value_header (tree, header_buff, headerLen,
1579 value_buff, valueType, valueLen,
1580 hf_wsp_header_if_modified_since, headerType);
1583 case FN_LOCATION: /* Location */
1584 add_string_value_header (tree, header_buff, headerLen,
1585 value_buff, valueType, valueLen,
1586 hf_wsp_header_location, headerType);
1589 case FN_LAST_MODIFIED: /* Last-Modified */
1590 add_date_value_header (tree, header_buff, headerLen,
1591 value_buff, valueType, valueLen,
1592 hf_wsp_header_last_modified, headerType);
1595 case FN_PRAGMA: /* Pragma */
1596 add_pragma_header (tree, header_buff, headerLen,
1597 value_buff, valueType, valueLen);
1600 case FN_SERVER: /* Server */
1601 add_string_value_header (tree, header_buff, headerLen,
1602 value_buff, valueType, valueLen,
1603 hf_wsp_header_server, headerType);
1606 case FN_TRANSFER_ENCODING: /* Transfer-Encoding */
1607 add_transfer_encoding_header (tree, header_buff, headerLen,
1608 value_buff, valueType, valueLen);
1611 case FN_USER_AGENT: /* User-Agent */
1612 add_string_value_header (tree, header_buff, headerLen,
1613 value_buff, valueType, valueLen,
1614 hf_wsp_header_user_agent, headerType);
1617 case FN_VIA: /* Via */
1618 add_string_value_header (tree, header_buff, headerLen,
1619 value_buff, valueType, valueLen,
1620 hf_wsp_header_via, headerType);
1623 case FN_WARNING: /* Warning */
1624 add_warning_header (tree, header_buff, headerLen,
1625 value_buff, valueType, valueLen);
1628 case FN_ACCEPT_APPLICATION: /* Accept-Application */
1629 add_accept_application_header (tree, header_buff, headerLen,
1630 value_buff, valueType, valueLen);
1633 case FN_BEARER_INDICATION: /* Bearer-Indication */
1634 add_integer_value_header (tree, header_buff, headerLen,
1635 value_buff, valueType, valueLen,
1636 hf_wsp_header_bearer_indication, headerType);
1639 case FN_PROFILE: /* Profile */
1640 add_string_value_header (tree, header_buff, headerLen,
1641 value_buff, valueType, valueLen,
1642 hf_wsp_header_profile, headerType);
1645 case FN_X_WAP_APPLICATION_ID: /* X-Wap-Application-Id */
1646 add_wap_application_id_header (tree, header_buff, headerLen,
1647 value_buff, valueType, valueLen);
1651 proto_tree_add_text (tree, header_buff, 0, headerLen,
1652 "Unsupported Header: %s",
1653 val_to_str (headerType, vals_field_names, "Unknown (0x%02X)"));
1660 add_unknown_header (proto_tree *tree, tvbuff_t *tvb, int offset,
1665 value_type_t valueType;
1670 headerStart = offset;
1673 * Skip the Short-Integer header type.
1677 valueStart = offset;
1680 * Get the value type and length (or, if the type is VALUE_IN_LEN,
1681 * meaning the value is a Short-integer, get the value type
1682 * and the value itself).
1684 valueType = get_value_type_len (tvb, valueStart, &valueLen,
1685 &valueOffset, &offset);
1686 headerLen = offset - headerStart;
1688 proto_tree_add_text (tree, tvb, headerStart, headerLen,
1689 "Unsupported Header (0x%02X)", headerType);
1694 add_application_header (proto_tree *tree, tvbuff_t *tvb, int offset)
1698 const guint8 *token;
1699 value_type_t valueType;
1707 startOffset = offset;
1708 tokenSize = tvb_strsize (tvb, startOffset);
1709 token = tvb_get_ptr (tvb, startOffset, tokenSize);
1710 offset += tokenSize;
1713 * Special case header "X-WAP.TOD" that is sometimes followed
1714 * by a 4-byte date value.
1716 * XXX - according to the 4-May-2000 WSP spec, X-Wap-Tod is
1717 * encoded as a well known header, with a code of 0x3F.
1719 if (tokenSize == 10 && strncasecmp ("x-wap.tod", token, 9) == 0)
1721 valueType = get_value_type_len (tvb, offset,
1722 &subvalueLen, &subvalueOffset, &offset);
1723 if (get_integer (tvb, subvalueOffset, subvalueLen,
1724 valueType, &secs) == 0)
1727 * Fill in the "struct timeval", and add it to the
1729 * Note: this will succeed even if it's a Short-integer.
1730 * A Short-integer would work, but, as the time values
1731 * are UNIX seconds-since-the-Epoch value, and as
1732 * there weren't WAP phones or Web servers back in
1733 * late 1969/early 1970, they're unlikely to be used.
1735 timeValue.secs = secs;
1736 timeValue.nsecs = 0;
1737 proto_tree_add_time (tree, hf_wsp_header_x_wap_tod,
1738 tvb, startOffset, offset - startOffset, &timeValue);
1742 proto_tree_add_text (tree, tvb, startOffset,
1743 offset - startOffset,
1744 "%s: invalid date value", token);
1750 stringSize = tvb_strsize (tvb, asvOffset);
1751 offset += stringSize;
1752 proto_tree_add_text (tree, tvb, startOffset,
1753 offset - startOffset,
1755 tvb_get_ptr (tvb, asvOffset, stringSize));
1761 add_accept_header (proto_tree *tree, tvbuff_t *header_buff,
1762 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1766 const char *contentTypeStr;
1768 add_content_type_value (tree, header_buff, 0, headerLen, value_buff,
1769 valueType, valueLen, hf_wsp_header_accept,
1770 hf_wsp_header_accept_str, &contentType, &contentTypeStr);
1774 add_accept_xxx_header (proto_tree *tree, tvbuff_t *header_buff,
1775 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1776 int valueLen, int hf_numeric, int hf_string,
1777 const value_string *vals, const char *unknown_tag)
1783 char valString[100];
1784 const char *valMatch;
1786 double q_value = 1.0;
1788 if (valueType == VALUE_IN_LEN)
1791 * Constrained-{charset,language} (Short-Integer).
1793 proto_tree_add_uint (tree, hf_numeric,
1794 header_buff, 0, headerLen,
1795 valueLen); /* valueLen is the value */
1798 if (valueType == VALUE_IS_TEXT_STRING)
1801 * Constrained-{charset,language} (text, i.e.
1804 proto_tree_add_string (tree, hf_string,
1805 header_buff, 0, headerLen,
1806 tvb_get_ptr (value_buff, 0, valueLen));
1811 * First byte had the 8th bit set.
1813 if (valueLen == 0) {
1815 * Any-{charset,language}.
1817 proto_tree_add_string (tree, hf_string,
1818 header_buff, 0, headerLen,
1824 * Accept-{charset,language}-general-form; Value-length, followed
1825 * by Well-known-{charset,language} or {Token-text,Text-string},
1826 * possibly followed by a Q-value.
1830 valueType = get_value_type_len (value_buff, 0, &subvalueLen,
1831 &subvalueOffset, &offset);
1832 if (valueType == VALUE_IS_TEXT_STRING)
1835 * {Token-text,Text-string}.
1838 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
1839 proto_tree_add_string (tree, hf_string,
1840 value_buff, 0, valueLen, valMatch);
1843 * Well-known-{charset,langugage}; starts with an
1846 if (get_integer (value_buff, subvalueOffset, subvalueLen,
1847 valueType, &value) < 0)
1849 valMatch = "Invalid integer";
1853 valMatch = val_to_str(value, vals, unknown_tag);
1857 /* Any remaining data relates to Q-value */
1858 if (offset < valueLen)
1860 peek = tvb_get_guintvar (value_buff, offset, NULL);
1862 peek = (peek - 1) * 10;
1867 q_value = peek/1000.0;
1870 /* Build string including Q-value if present */
1871 if (q_value == 1.0) /* Default */
1873 snprintf (valString, 100, "%s", valMatch);
1877 snprintf (valString, 100, "%s; Q=%5.3f", valMatch, q_value);
1879 /* Add string to tree */
1880 proto_tree_add_string (tree, hf_string,
1881 header_buff, 0, headerLen, valString);
1885 add_accept_ranges_header (proto_tree *tree, tvbuff_t *header_buff,
1886 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1889 if (valueType == VALUE_IN_LEN)
1892 * Must be 0 (None) or 1 (Bytes) (the 8th bit was stripped
1895 proto_tree_add_uint (tree, hf_wsp_header_accept_ranges,
1896 header_buff, 0, headerLen,
1897 valueLen); /* valueLen is the value */
1900 if (valueType == VALUE_IS_TEXT_STRING)
1905 proto_tree_add_string (tree, hf_wsp_header_accept_ranges_str,
1906 header_buff, 0, headerLen,
1907 tvb_get_ptr (value_buff, 0, valueLen));
1914 fprintf(stderr, "dissect_wsp: Accept-Ranges is neither None, Bytes, nor Token-text\n");
1919 add_cache_control_header (proto_tree *tree, tvbuff_t *header_buff,
1920 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
1928 proto_tree *parameter_tree;
1929 proto_tree *field_names_tree;
1932 if (valueType == VALUE_IN_LEN)
1935 * No-cache, No-store, Max-age, Max-stale, Min-fresh,
1936 * Only-if-cached, Public, Private, No-transform,
1937 * Must-revalidate, Proxy-revalidate, or S-maxage.
1939 proto_tree_add_uint (tree, hf_wsp_header_cache_control,
1940 header_buff, 0, headerLen,
1941 valueLen); /* valueLen is the value */
1944 if (valueType == VALUE_IS_TEXT_STRING)
1949 proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
1950 header_buff, 0, headerLen,
1951 tvb_get_ptr (value_buff, 0, valueLen));
1956 * Value-length Cache-directive.
1957 * Get first field of Cache-directive.
1959 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
1960 &subvalueOffset, &offset);
1961 if (valueType == VALUE_IS_TEXT_STRING)
1964 * Cache-extension Parameter.
1966 ti = proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
1967 header_buff, 0, headerLen,
1968 tvb_get_ptr (value_buff, 0, valueLen));
1969 parameter_tree = proto_item_add_subtree (ti,
1970 ett_header_cache_control_parameters);
1973 * Process the rest of the value as parameters.
1975 while (tvb_reported_length_remaining (value_buff, offset) > 0) {
1976 offset = add_parameter (parameter_tree, value_buff,
1981 if (get_integer (value_buff, subvalueOffset, subvalueLen, valueType,
1984 proto_tree_add_text (tree, header_buff, 0, headerLen,
1985 "Invalid Cache-Control Cache-directive value");
1994 * Loop, processing Field-names.
1996 ti = proto_tree_add_uint (tree,
1997 hf_wsp_header_cache_control,
1998 header_buff, 0, headerLen,
2000 field_names_tree = proto_item_add_subtree (ti,
2001 ett_header_cache_control_field_names);
2002 while (tvb_reported_length_remaining (value_buff, offset)
2004 offset = add_cache_control_field_name (tree,
2005 value_buff, offset, value);
2014 * Get Delta-second-value.
2016 valueType = get_value_type_len (value_buff, offset,
2017 &subvalueLen, &subvalueOffset, &offset);
2018 if (get_integer (value_buff, subvalueOffset,
2019 subvalueLen, valueType, &delta_secs) < 0)
2021 proto_tree_add_text (tree,
2022 header_buff, 0, headerLen,
2023 "Invalid Cache-Control %s Delta-second-value",
2024 match_strval (value, vals_cache_control));
2028 proto_tree_add_uint_format (tree,
2029 hf_wsp_header_cache_control,
2030 header_buff, 0, headerLen,
2032 "Cache-Control: %s %u secs",
2033 match_strval (value, vals_cache_control),
2040 * This should not happen, but handle it anyway.
2042 proto_tree_add_uint (tree,
2043 hf_wsp_header_cache_control,
2044 header_buff, 0, headerLen,
2052 add_cache_control_field_name (proto_tree *tree, tvbuff_t *value_buff,
2053 int offset, guint cache_control_value)
2055 value_type_t valueType;
2060 startOffset = offset;
2061 valueType = get_value_type_len (value_buff, offset,
2062 &subvalueLen, &subvalueOffset, &offset);
2063 if (valueType == VALUE_IS_TEXT_STRING)
2068 proto_tree_add_item (tree,
2069 hf_wsp_header_cache_control_field_name_str,
2070 value_buff, startOffset, offset - startOffset,
2073 else if (valueType == VALUE_IN_LEN)
2076 * Short-integer Field-name.
2078 proto_tree_add_uint (tree,
2079 hf_wsp_header_cache_control_field_name,
2080 value_buff, startOffset, offset - startOffset,
2086 * Long-integer - illegal.
2088 proto_tree_add_text (tree,
2089 value_buff, startOffset, offset - startOffset,
2090 "Invalid Cache-Control %s Field-name",
2091 match_strval (cache_control_value, vals_cache_control));
2097 add_connection_header (proto_tree *tree, tvbuff_t *header_buff,
2098 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2103 if (valueType == VALUE_LEN_SUPPLIED)
2108 proto_tree_add_text (tree, header_buff, 0, headerLen,
2109 "Invalid Connection value");
2112 if (valueType == VALUE_IS_TEXT_STRING)
2117 proto_tree_add_string (tree,
2118 hf_wsp_header_connection_str,
2119 header_buff, 0, headerLen,
2120 tvb_get_ptr (value_buff, 0, valueLen));
2125 * First byte had the 8th bit set.
2127 if (valueLen == 0) {
2131 proto_tree_add_uint (tree, hf_wsp_header_connection,
2132 header_buff, offset, headerLen, valueLen);
2139 proto_tree_add_text (tree, header_buff, 0, headerLen,
2140 "Invalid Connection value");
2144 add_pragma_header (proto_tree *tree, tvbuff_t *header_buff,
2145 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2152 if (valueType == VALUE_IN_LEN)
2157 proto_tree_add_text (tree, header_buff, 0, headerLen,
2161 if (valueType == VALUE_IS_TEXT_STRING)
2166 proto_tree_add_text (tree, header_buff, 0, headerLen,
2172 * First byte had the 8th bit set.
2174 if (valueLen == 0) {
2178 proto_tree_add_string (tree, hf_wsp_header_pragma,
2179 header_buff, 0, headerLen, "No-cache");
2184 * Value-length, followed by Parameter.
2188 valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2189 &subvalueOffset, &offset);
2190 if (valueType == VALUE_IS_TEXT_STRING)
2193 * Parameter - a text string.
2195 proto_tree_add_string (tree, hf_wsp_header_pragma,
2196 header_buff, 0, headerLen,
2197 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
2200 * Parameter - numeric; illegal?
2202 proto_tree_add_text (tree, header_buff, 0, headerLen,
2208 add_transfer_encoding_header (proto_tree *tree, tvbuff_t *header_buff,
2209 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2214 if (valueType == VALUE_LEN_SUPPLIED)
2219 proto_tree_add_text (tree, header_buff, 0, headerLen,
2220 "Invalid Transfer-Encoding value");
2223 if (valueType == VALUE_IS_TEXT_STRING)
2228 proto_tree_add_string (tree,
2229 hf_wsp_header_transfer_encoding_str,
2230 header_buff, 0, headerLen,
2231 tvb_get_ptr (value_buff, 0, valueLen));
2236 * First byte had the 8th bit set.
2238 if (valueLen == 0) {
2242 proto_tree_add_uint (tree, hf_wsp_header_transfer_encoding,
2243 header_buff, offset, headerLen, valueLen);
2250 proto_tree_add_text (tree, header_buff, 0, headerLen,
2251 "Invalid Transfer Encoding value");
2255 add_warning_header (proto_tree *tree, tvbuff_t *header_buff,
2256 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2261 proto_tree *warning_tree;
2266 * Put the items under a header.
2267 * XXX - make the text of the item summarize the elements.
2269 ti = proto_tree_add_item (tree, hf_wsp_header_warning,
2270 header_buff, 0, headerLen, bo_little_endian);
2271 warning_tree = proto_item_add_subtree(ti, ett_header_warning);
2273 if (valueType == VALUE_IN_LEN)
2276 * Warn-code (Short-integer).
2278 proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2279 header_buff, 0, headerLen,
2280 valueLen); /* valueLen is the value */
2283 if (valueType == VALUE_IS_TEXT_STRING)
2288 proto_tree_add_text (warning_tree, header_buff, 0, headerLen,
2289 "Invalid Warning (all text)");
2294 * Warning-value; Warn-code, followed by Warn-agent, followed by
2298 * Get Short-integer Warn-code.
2300 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2301 &subvalueOffset, &offset);
2302 if (valueType != VALUE_IN_LEN)
2305 * Not a Short-integer.
2307 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2308 subvalueLen, "Invalid Warn-code (not a Short-integer)");
2311 proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
2312 value_buff, subvalueOffset, 1,
2313 subvalueLen); /* subvalueLen is the value */
2316 * Warn-agent; must be text.
2318 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2319 &subvalueOffset, &offset);
2320 if (valueType != VALUE_IS_TEXT_STRING)
2325 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2326 subvalueLen, "Invalid Warn-agent (not a text string)");
2329 proto_tree_add_item (warning_tree,
2330 hf_wsp_header_warning_agent,
2331 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2334 * Warn-text; must be text.
2336 valueType = get_value_type_len (value_buff, offset, &subvalueLen,
2337 &subvalueOffset, &offset);
2338 if (valueType != VALUE_IS_TEXT_STRING)
2343 proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
2344 subvalueLen, "Invalid Warn-text (not a text string)");
2347 proto_tree_add_item (warning_tree,
2348 hf_wsp_header_warning_text,
2349 value_buff, subvalueOffset, subvalueLen, bo_little_endian);
2353 add_accept_application_header (proto_tree *tree, tvbuff_t *header_buff,
2354 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2359 if (valueType == VALUE_IN_LEN)
2362 * Application-id-value; numeric, so it's App-assigned-code.
2364 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2365 header_buff, 0, headerLen,
2366 valueLen); /* valueLen is the value */
2369 if (valueType == VALUE_IS_TEXT_STRING)
2374 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2375 header_buff, 0, headerLen,
2376 tvb_get_ptr (value_buff, 0, valueLen));
2381 * First byte had the 8th bit set.
2383 if (valueLen == 0) {
2387 proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
2388 header_buff, 0, headerLen,
2394 * Integer-value, hence App-assigned-code.
2396 if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
2398 proto_tree_add_text (tree, header_buff, 0, headerLen,
2399 "Invalid Accept-Application App-assigned-code");
2403 proto_tree_add_uint (tree, hf_wsp_header_accept_application,
2404 header_buff, 0, headerLen, value);
2409 add_wap_application_id_header (proto_tree *tree, tvbuff_t *header_buff,
2410 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2413 if (valueType == VALUE_IN_LEN)
2416 * Must application-id (the 8th bit was stripped off).
2418 proto_tree_add_uint (tree, hf_wsp_header_wap_application_id,
2419 header_buff, 0, headerLen,
2420 valueLen); /* valueLen is the value */
2423 if (valueType == VALUE_IS_TEXT_STRING)
2428 proto_tree_add_string (tree, hf_wsp_header_wap_application_id_str,
2429 header_buff, 0, headerLen,
2430 tvb_get_ptr (value_buff, 0, valueLen));
2437 fprintf(stderr, "dissect_wsp: Suprising format of X-Wap-Application-Id\n");
2442 add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type)
2445 proto_tree *wsp_capabilities;
2447 guint offsetStr = 0;
2448 guint capabilitiesLen = tvb_reported_length (tvb);
2449 guint capabilitiesStart = 0;
2455 char valString[200];
2458 fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, capabilitiesLen);
2462 if (capabilitiesLen <= 0)
2464 fprintf (stderr, "dissect_wsp: Capabilities = 0\n");
2469 fprintf (stderr, "dissect_wsp: capabilities to process\n");
2472 ti = proto_tree_add_item (tree, hf_wsp_capabilities_section,tvb,offset,capabilitiesLen,bo_little_endian);
2473 wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
2477 while (offset < capabilitiesLen)
2479 /* Loop round each header */
2480 capabilitiesStart = offset;
2481 length = tvb_get_guint8 (tvb, capabilitiesStart);
2483 if (length >= 127) /* length */
2486 fprintf (stderr, "dissect_wsp: capabilities length invalid %d\n",length);
2492 peek = tvb_get_guint8 (tvb, offset);
2494 switch (peek & 0x7f)
2496 case 0x00 : /* Client-SDU-Size */
2497 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
2498 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_client_SDU, tvb, capabilitiesStart, length+1, value);
2500 case 0x01 : /* Server-SDU-Size */
2501 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
2502 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_server_SDU, tvb, capabilitiesStart, length+1, value);
2504 case 0x02 : /* Protocol Options */
2505 value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
2510 ret = snprintf(valString+i,200-i,"%s","(Confirmed push facility) ");
2513 * Some versions of snprintf
2514 * return -1 if they'd
2515 * truncate the output.
2527 ret = snprintf(valString+i,200-i,"%s","(Push facility) ");
2530 * Some versions of snprintf
2531 * return -1 if they'd
2532 * truncate the output.
2544 ret = snprintf(valString+i,200-i,"%s","(Session resume facility) ");
2547 * Some versions of snprintf
2548 * return -1 if they'd
2549 * truncate the output.
2561 ret = snprintf(valString+i,200-i,"%s","(Acknowledgement headers) ");
2564 * Some versions of snprintf
2565 * return -1 if they'd
2566 * truncate the output.
2573 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_protocol_opt, tvb, capabilitiesStart, length+1, valString);
2575 case 0x03 : /* Method-MOR */
2576 value = tvb_get_guint8(tvb, offset);
2577 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_method_MOR, tvb, capabilitiesStart, length+1, value);
2579 case 0x04 : /* Push-MOR */
2580 value = tvb_get_guint8(tvb, offset);
2581 proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_push_MOR, tvb, capabilitiesStart, length+1, value);
2584 case 0x05 : /* Extended Methods */
2587 add_capability_vals(tvb, (type == CONNECT),
2588 offsetStr, length, capabilitiesStart,
2589 valString, sizeof valString);
2590 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_extended_methods, tvb, capabilitiesStart, length+1, valString);
2592 case 0x06 : /* Header Code Pages */
2595 add_capability_vals(tvb, (type == CONNECT),
2596 offsetStr, length, capabilitiesStart,
2597 valString, sizeof valString);
2598 proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_header_code_pages, tvb, capabilitiesStart, length+1, valString);
2600 case 0x07 : /* Aliases */
2603 proto_tree_add_text (wsp_capabilities, tvb , capabilitiesStart, length+1,
2604 "Unsupported Header (0x%02X)", peek & 0x7F);
2607 offset=capabilitiesStart+length+1;
2612 add_capability_vals(tvbuff_t *tvb, gboolean add_string, int offsetStr,
2613 guint length, guint capabilitiesStart, char *valString,
2614 size_t valStringSize)
2622 while ((offsetStr-capabilitiesStart) <= length)
2624 value = tvb_get_guint8(tvb, offsetStr);
2625 if (i >= valStringSize) {
2631 ret = snprintf(valString+i,valStringSize-i,
2636 ret = snprintf(valString+i,valStringSize-i,"(%d) ",
2641 * Some versions of snprintf return -1
2642 * if they'd truncate the output.
2650 for (;(c = tvb_get_guint8(tvb, offsetStr))
2651 && i < valStringSize - 1; i++,offsetStr++)
2654 if (i < valStringSize - 2) {
2655 valString[i++] = ')';
2656 valString[i++] = ' ';
2660 valString[i] = '\0';
2664 get_value_type_len (tvbuff_t *tvb, int offset, guint *valueLen,
2665 int *valueOffset, int *nextOffset)
2671 /* Get value part of header */
2672 peek = tvb_get_guint8 (tvb, offset);
2676 * The value follows "peek", and is "peek" octets long.
2679 fprintf (stderr, "dissect_wsp: Looking for %d octets\n", peek);
2682 *valueLen = len; /* Length of value */
2683 offset++; /* Skip the length */
2684 *valueOffset = offset; /* Offset of value */
2685 offset += len; /* Skip the value */
2686 *nextOffset = offset; /* Offset after value */
2687 return VALUE_LEN_SUPPLIED;
2689 else if (peek == 31)
2692 * A uintvar giving the length of the value follows
2693 * "peek", and the value follows that.
2696 fprintf (stderr, "dissect_wsp: Looking for uintvar octets\n");
2698 offset++; /* Skip the uintvar indicator */
2699 count = 0; /* Initialise count */
2700 len = tvb_get_guintvar (tvb, offset, &count);
2701 *valueLen = len; /* Length of value */
2702 offset += count; /* Skip the length */
2703 *valueOffset = offset; /* Offset of value */
2704 offset += len; /* Skip the value */
2705 *nextOffset = offset; /* Offset after value */
2706 return VALUE_LEN_SUPPLIED;
2708 else if (peek <= 127)
2711 * The value is a NUL-terminated string, and "peek"
2712 * is the first octet of the string.
2715 fprintf (stderr, "dissect_wsp: Looking for NUL-terminated string\n");
2717 len = tvb_strsize (tvb, offset);
2718 *valueLen = len; /* Length of value */
2719 *valueOffset = offset; /* Offset of value */
2720 offset += len; /* Skip the value */
2721 *nextOffset = offset; /* Offset after value */
2722 return VALUE_IS_TEXT_STRING;
2727 * "peek", with the 8th bit stripped off, is the value.
2730 fprintf (stderr, "dissect_wsp: Value is %d\n", (peek & 0x7F));
2732 *valueLen = peek & 0x7F; /* Return the value itself */
2733 *valueOffset = offset; /* Offset of value */
2734 offset++; /* Skip the value */
2735 *nextOffset = offset; /* Offset after value */
2736 return VALUE_IN_LEN;
2741 get_uintvar (tvbuff_t *tvb, guint offset, guint offsetEnd)
2748 octet = tvb_get_guint8 (tvb, offset);
2751 value += octet & 0x7f;
2753 while ((offsetEnd > offset) && (octet & 0x80));
2758 add_content_type_value (proto_tree *tree, tvbuff_t *header_buff,
2759 int headerOffset, int headerLen, tvbuff_t *value_buff,
2760 value_type_t valueType, int valueLen, int hf_numeric, int hf_string,
2761 guint *contentTypep, const char **contentTypeStrp)
2764 proto_tree *parameter_tree;
2765 const char *contentTypeStr;
2771 if (valueType == VALUE_IN_LEN)
2774 * Constrained-media (Short-Integer).
2776 proto_tree_add_uint (tree, hf_numeric,
2777 header_buff, headerOffset, headerLen,
2778 valueLen); /* valueLen is the value */
2781 * Return the numerical value, and a null string value
2782 * indicating that the value is numerical.
2784 *contentTypep = valueLen;
2785 *contentTypeStrp = NULL;
2788 if (valueType == VALUE_IS_TEXT_STRING)
2791 * Constrained-media (text, i.e. Extension-Media).
2793 contentTypeStr = tvb_get_ptr (value_buff, 0, valueLen);
2794 proto_tree_add_string (tree, hf_string,
2795 header_buff, headerOffset, headerLen,
2799 * Return the string value, and set the numerical value
2800 * to 0 (as it shouldn't be used).
2803 *contentTypeStrp = contentTypeStr;
2808 * Content-general-form; Value-length, followed by Media-range,
2809 * followed by optional Accept-parameters.
2813 valueType = get_value_type_len (value_buff, 0, &subvalueLen,
2814 &subvalueOffset, &offset);
2815 if (valueType == VALUE_IS_TEXT_STRING)
2818 * Extension-Media; value is a string.
2821 tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
2822 ti = proto_tree_add_string (tree, hf_string, header_buff,
2823 headerOffset, headerLen, contentTypeStr);
2826 * Return the string value, and set the numerical value
2827 * to 0 (as it shouldn't be used).
2830 *contentTypeStrp = contentTypeStr;
2835 * Well-known-media; value is an Integer.
2837 if (get_integer (value_buff, subvalueOffset, subvalueLen,
2838 valueType, &value) < 0)
2840 proto_tree_add_text (tree, header_buff,
2841 headerOffset, headerLen,
2842 "Invalid integer for Well-known-media");
2845 * Content type is invalid.
2846 * Don't try to parse the rest of the value.
2849 *contentTypeStrp = NULL;
2852 ti = proto_tree_add_uint (tree, hf_numeric,
2853 header_buff, headerOffset, headerLen, value);
2856 * Return the numerical value, and a null string value
2857 * indicating that the value is numerical.
2859 *contentTypep = value;
2860 *contentTypeStrp = NULL;
2864 * Process the rest of the value as parameters.
2866 parameter_tree = proto_item_add_subtree(ti,
2867 ett_content_type_parameters);
2868 while (tvb_reported_length_remaining (value_buff, offset) > 0)
2869 offset = add_parameter (parameter_tree, value_buff, offset);
2873 add_content_type (proto_tree *tree, tvbuff_t *tvb, guint offset,
2874 guint *contentTypep, const char **contentTypeStrp)
2877 value_type_t valueType;
2881 tvbuff_t *value_buff;
2883 valueStart = offset;
2886 * Get the value type and length (or, if the type is VALUE_IN_LEN,
2887 * meaning the value is a Short-integer, get the value type
2888 * and the value itself).
2890 valueType = get_value_type_len (tvb, valueStart, &valueLen,
2891 &valueOffset, &offset);
2892 valueTypeLen = offset - valueStart;
2895 * Get a tvbuff for the value.
2896 * XXX - can valueLen be 0?
2897 * XXX - cut the actual length short so that it doesn't run
2898 * past the actual length of tvb.
2900 if (valueType != VALUE_IN_LEN) {
2901 value_buff = tvb_new_subset (tvb, valueOffset, valueLen,
2905 * XXX - when the last dissector is tvbuffified,
2906 * so that NULL is no longer a valid tvb pointer
2907 * value in "proto_tree_add" calls, just
2908 * set "value_buff" to NULL.
2910 * XXX - can we already do that? I.e., will that
2911 * cause us always to crash if we mistakenly try
2912 * to fetch the value of a VALUE_IN_LEN item?
2914 value_buff = tvb_new_subset (tvb, valueStart, 0, 0);
2917 add_content_type_value (tree, tvb, valueStart, valueTypeLen, value_buff,
2918 valueType, valueLen, hf_wsp_content_type,
2919 hf_wsp_content_type_str, contentTypep, contentTypeStrp);
2925 add_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
2926 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2927 int valueLen, int hf_numeric, guint8 headerType)
2931 if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
2933 proto_tree_add_text (tree, header_buff, 0, headerLen,
2934 "Invalid %s integer value",
2935 match_strval (headerType, vals_field_names));
2939 proto_tree_add_uint (tree, hf_numeric,
2940 header_buff, 0, headerLen, value);
2945 add_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
2946 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2947 int valueLen, int hf_string, guint8 headerType)
2949 if (valueType != VALUE_IS_TEXT_STRING)
2951 proto_tree_add_text (tree, header_buff, 0, headerLen,
2952 "Invalid %s string value",
2953 match_strval (headerType, vals_field_names));
2957 proto_tree_add_string (tree, hf_string, header_buff,
2958 0, headerLen, tvb_get_ptr (value_buff, 0, valueLen));
2962 /* Utility function to add a date value to the protocol tree */
2964 add_date_value_header (proto_tree *tree, tvbuff_t *header_buff,
2965 int headerLen, tvbuff_t *value_buff, value_type_t valueType,
2966 int valueLen, int hf_time, guint8 headerType)
2971 /* Attempt to get the date value from the buffer */
2972 if (get_integer (value_buff, 0, valueLen, valueType, &secs) == 0)
2975 * Fill in the "struct timeval", and add it to the
2977 * Note: this will succeed even if it's a Short-integer.
2978 * A Short-integer would work, but, as the time values
2979 * are UNIX seconds-since-the-Epoch value, and as
2980 * there weren't WAP phones or Web servers back in
2981 * late 1969/early 1970, they're unlikely to be used.
2983 timeValue.secs = secs;
2984 timeValue.nsecs = 0;
2985 proto_tree_add_time (tree, hf_time, header_buff, 0,
2986 headerLen, &timeValue);
2990 proto_tree_add_text (tree, header_buff, 0, headerLen,
2991 "Invalid %s date value",
2992 match_strval (headerType, vals_field_names));
2997 add_parameter (proto_tree *tree, tvbuff_t *value_buff, int offset)
3000 value_type_t valueType;
3005 startOffset = offset;
3006 valueType = get_value_type_len (value_buff, offset,
3007 &subvalueLen, &subvalueOffset, &offset);
3008 if (valueType == VALUE_IS_TEXT_STRING)
3011 * Untyped-parameter.
3013 add_untyped_parameter (tree, value_buff, startOffset, offset);
3018 * Well-known-parameter-token.
3020 if (get_integer (value_buff, subvalueOffset,
3021 subvalueLen, valueType, &value) < 0)
3023 proto_tree_add_text (tree, value_buff, startOffset,
3024 offset - startOffset,
3025 "Invalid Well-known-parameter-token");
3031 case 0x01: /* Charset */
3032 add_parameter_charset (tree, value_buff, startOffset, offset);
3035 case 0x03: /* Type */
3036 add_parameter_type (tree, value_buff, startOffset, offset);
3039 case 0x05: /* Name */
3040 add_parameter_text (tree, value_buff, startOffset, offset,
3041 hf_wsp_parameter_name, "Name");
3044 case 0x06: /* Filename */
3045 add_parameter_text (tree, value_buff, startOffset, offset,
3046 hf_wsp_parameter_filename, "Filename");
3049 case 0x0A: /* Start */
3050 add_parameter_text (tree, value_buff, startOffset, offset,
3051 hf_wsp_parameter_start, "Start");
3054 case 0x0B: /* Start-info */
3055 add_parameter_text (tree, value_buff, startOffset, offset,
3056 hf_wsp_parameter_start_info, "Start-info");
3059 case 0x0C: /* Comment */
3060 add_parameter_text (tree, value_buff, startOffset, offset,
3061 hf_wsp_parameter_comment, "Comment");
3064 case 0x0D: /* Domain */
3065 add_parameter_text (tree, value_buff, startOffset, offset,
3066 hf_wsp_parameter_domain, "Domain");
3069 case 0x0F: /* Path */
3070 add_parameter_text (tree, value_buff, startOffset, offset,
3071 hf_wsp_parameter_path, "Path");
3075 case 0x02: /* Level */
3076 case 0x07: /* Differences */
3077 case 0x08: /* Padding */
3078 case 0x09: /* Type (special) */
3079 case 0x0E: /* Max-Age */
3080 case 0x10: /* Secure */
3089 add_untyped_parameter (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3094 const guint8 *token;
3095 value_type_t valueType;
3102 tokenOffset = offset;
3103 tokenSize = tvb_strsize (value_buff, tokenOffset);
3104 token = tvb_get_ptr (value_buff, tokenOffset, tokenSize);
3105 offset += tokenSize;
3108 * Now an Untyped-value; either an Integer-value or a Text-value.
3110 valueType = get_value_type_len (value_buff, offset,
3111 &subvalueLen, &subvalueOffset, &offset);
3112 if (valueType == VALUE_IS_TEXT_STRING)
3117 textvOffset = offset;
3118 stringSize = tvb_strsize (value_buff, textvOffset);
3119 if (stringSize == 1) {
3121 * No-value. (stringSize includes the terminating
3122 * null byte, so an empty string has a size of 1.)
3124 proto_tree_add_text (tree, value_buff, startOffset,
3125 offset - startOffset,
3129 offset += stringSize;
3130 proto_tree_add_text (tree, value_buff, startOffset,
3131 offset - startOffset,
3133 tvb_get_ptr (value_buff, textvOffset, stringSize));
3140 if (get_integer (value_buff, subvalueOffset, subvalueLen,
3141 valueType, &value) == 0)
3143 proto_tree_add_text (tree, value_buff, startOffset,
3144 offset - startOffset,
3145 "%s: %u", token, value);
3149 proto_tree_add_text (tree, value_buff, startOffset,
3150 offset - startOffset,
3151 "%s: Invalid Integer-value", token);
3157 add_parameter_charset (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3160 value_type_t valueType;
3165 valueType = get_value_type_len (value_buff, offset,
3166 &subvalueLen, &subvalueOffset, &offset);
3167 if (valueType == VALUE_IN_LEN)
3172 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3173 value_buff, startOffset, offset - startOffset,
3174 subvalueLen); /* subvalueLen is the value */
3177 if (valueType == VALUE_IS_TEXT_STRING)
3182 proto_tree_add_text (tree, value_buff, startOffset,
3183 offset - startOffset, "Invalid Well-known charset");
3188 * First byte had the 8th bit set.
3190 if (subvalueLen == 0) {
3193 * XXX - add this as a field?
3195 proto_tree_add_text (tree, value_buff, startOffset,
3196 offset- startOffset, "*");
3200 if (get_integer(value_buff, subvalueOffset, subvalueLen,
3201 valueType, &value) == -1) {
3202 proto_tree_add_text (tree, value_buff, startOffset,
3203 offset - startOffset, "Length %u not handled in Well-known charset",
3206 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
3207 value_buff, startOffset, offset - startOffset, value);
3212 add_parameter_type (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3215 value_type_t valueType;
3220 valueType = get_value_type_len (value_buff, offset,
3221 &subvalueLen, &subvalueOffset, &offset);
3222 if (get_integer(value_buff, subvalueOffset, subvalueLen,
3223 valueType, &value) == -1) {
3224 proto_tree_add_text (tree, value_buff, startOffset,
3225 offset - startOffset, "Invalid type");
3227 proto_tree_add_uint (tree, hf_wsp_parameter_type, value_buff,
3228 startOffset, offset - startOffset, value);
3233 add_parameter_text (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
3234 int offset, int hf_string, const char *paramName)
3236 value_type_t valueType;
3240 valueType = get_value_type_len (value_buff, offset,
3241 &subvalueLen, &subvalueOffset, &offset);
3242 if (valueType != VALUE_IS_TEXT_STRING) {
3243 proto_tree_add_text (tree, value_buff, startOffset,
3244 offset - startOffset, "Invalid %s", paramName);
3246 proto_tree_add_item (tree, hf_string, value_buff,
3247 startOffset, offset - startOffset, bo_little_endian);
3252 add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType,
3253 const char *contentTypeStr)
3256 guint variableStart = 0;
3257 guint variableEnd = 0;
3258 guint valueStart = 0;
3263 /* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,tvb_length_remaining(tvb, offset),bo_little_endian); */
3264 ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,tvb_reported_length(tvb),bo_little_endian);
3266 if (contentTypeStr == NULL && contentType == 0x12)
3270 * Iterate through post data.
3272 for (offset = 0; offset < tvb_reported_length (tvb); offset++)
3274 peek = tvb_get_guint8 (tvb, offset);
3277 variableEnd = offset;
3278 valueStart = offset+1;
3280 else if (peek == '&')
3282 if (variableEnd > 0)
3284 add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
3286 variableStart = offset+1;
3293 /* See if there's outstanding data */
3294 if (variableEnd > 0)
3296 add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
3302 add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
3304 int variableLength = variableEnd-variableStart;
3305 int valueLength = 0;
3306 char *variableBuffer;
3309 variableBuffer = g_malloc (variableLength+1);
3310 strncpy (variableBuffer, tvb_get_ptr (tvb, variableStart, variableLength), variableLength);
3311 variableBuffer[variableLength] = 0;
3313 if (valueEnd < valueStart)
3315 valueBuffer = g_malloc (1);
3317 valueEnd = valueStart;
3321 valueLength = valueEnd-valueStart;
3322 valueBuffer = g_malloc (valueLength+1);
3323 strncpy (valueBuffer, tvb_get_ptr (tvb, valueStart, valueLength), valueLength);
3324 valueBuffer[valueLength] = 0;
3327 /* Check for variables with no value */
3328 if (valueStart >= tvb_reported_length (tvb))
3330 valueStart = tvb_reported_length (tvb);
3331 valueEnd = valueStart;
3333 valueLength = valueEnd-valueStart;
3335 proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
3337 g_free (variableBuffer);
3338 g_free (valueBuffer);
3342 get_integer (tvbuff_t *tvb, guint offset, guint valueLength,
3343 value_type_t valueType, guint *value)
3345 if (valueType == VALUE_IS_TEXT_STRING) {
3352 if (valueType == VALUE_IN_LEN) {
3356 *value = valueLength;
3363 switch (valueLength)
3366 *value = tvb_get_guint8(tvb, offset);
3369 *value = tvb_get_ntohs(tvb, offset);
3372 *value = tvb_get_ntoh24(tvb, offset);
3375 *value = tvb_get_ntohl(tvb, offset);
3378 /* TODO: Need to read peek octets */
3380 fprintf (stderr, "dissect_wsp: get_integer size %u NYI\n", valueLength);
3386 /* Register the protocol with Ethereal */
3388 proto_register_wsp(void)
3391 /* Setup list of header fields */
3392 static hf_register_info hf[] = {
3393 { &hf_wsp_header_tid,
3394 { "Transmission ID",
3396 FT_UINT8, BASE_HEX, NULL, 0x00,
3397 "Transmission ID", HFILL
3400 { &hf_wsp_header_pdu_type,
3403 FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
3407 { &hf_wsp_version_major,
3408 { "Version (Major)",
3409 "wsp.version.major",
3410 FT_UINT8, BASE_DEC, NULL, 0xF0,
3411 "Version (Major)", HFILL
3414 { &hf_wsp_version_minor,
3415 { "Version (Minor)",
3416 "wsp.version.minor",
3417 FT_UINT8, BASE_DEC, NULL, 0x0F,
3418 "Version (Minor)", HFILL
3421 { &hf_wsp_capability_length,
3422 { "Capability Length",
3423 "wsp.capability.length",
3424 FT_UINT32, BASE_DEC, NULL, 0x00,
3425 "Capability Length", HFILL
3428 { &hf_wsp_header_length,
3430 "wsp.headers_length",
3431 FT_UINT32, BASE_DEC, NULL, 0x00,
3432 "Headers Length", HFILL
3435 { &hf_wsp_capabilities_section,
3438 FT_NONE, BASE_DEC, NULL, 0x00,
3439 "Capabilities", HFILL
3442 { &hf_wsp_headers_section,
3445 FT_NONE, BASE_DEC, NULL, 0x00,
3451 "wsp.headers.header",
3452 FT_NONE, BASE_DEC, NULL, 0x00,
3456 { &hf_wsp_header_uri_len,
3459 FT_UINT32, BASE_DEC, NULL, 0x00,
3463 { &hf_wsp_header_uri,
3466 FT_STRING, BASE_NONE, NULL, 0x00,
3470 { &hf_wsp_server_session_id,
3471 { "Server Session ID",
3472 "wsp.server.session_id",
3473 FT_UINT32, BASE_DEC, NULL, 0x00,
3474 "Server Session ID", HFILL
3477 { &hf_wsp_header_status,
3480 FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
3484 { &hf_wsp_content_type,
3486 "wsp.content_type.type",
3487 FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
3488 "Content Type", HFILL
3491 { &hf_wsp_content_type_str,
3493 "wsp.content_type.type.string",
3494 FT_STRING, BASE_NONE, NULL, 0x00,
3495 "Content Type", HFILL
3498 { &hf_wsp_parameter_well_known_charset,
3500 "wsp.content_type.parameter.charset",
3501 FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
3505 { &hf_wsp_parameter_type,
3507 "wsp.content_type.parameter.type",
3508 FT_UINT32, BASE_DEC, NULL, 0x00,
3512 { &hf_wsp_parameter_name,
3514 "wsp.content_type.parameter.name",
3515 FT_STRING, BASE_NONE, NULL, 0x00,
3519 { &hf_wsp_parameter_filename,
3521 "wsp.content_type.parameter.filename",
3522 FT_STRING, BASE_NONE, NULL, 0x00,
3526 { &hf_wsp_parameter_start,
3528 "wsp.content_type.parameter.start",
3529 FT_STRING, BASE_NONE, NULL, 0x00,
3533 { &hf_wsp_parameter_start_info,
3535 "wsp.content_type.parameter.start_info",
3536 FT_STRING, BASE_NONE, NULL, 0x00,
3540 { &hf_wsp_parameter_comment,
3542 "wsp.content_type.parameter.comment",
3543 FT_STRING, BASE_NONE, NULL, 0x00,
3547 { &hf_wsp_parameter_domain,
3549 "wsp.content_type.parameter.domain",
3550 FT_STRING, BASE_NONE, NULL, 0x00,
3554 { &hf_wsp_parameter_path,
3556 "wsp.content_type.parameter.path",
3557 FT_STRING, BASE_NONE, NULL, 0x00,
3561 { &hf_wsp_reply_data,
3564 FT_NONE, BASE_NONE, NULL, 0x00,
3568 { &hf_wsp_header_shift_code,
3571 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3572 FT_UINT8, BASE_HEX, NULL, 0x00,
3576 { &hf_wsp_header_accept,
3578 "wsp.header.accept",
3579 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3580 FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
3584 { &hf_wsp_header_accept_str,
3586 "wsp.header.accept.string",
3587 FT_STRING, BASE_NONE, NULL, 0x00,
3591 { &hf_wsp_header_accept_application,
3592 { "Accept-Application",
3593 "wsp.header.accept_application",
3594 FT_UINT32, BASE_HEX, NULL, 0x00,
3595 "Accept-Application", HFILL
3598 { &hf_wsp_header_accept_application_str,
3599 { "Accept-Application",
3600 "wsp.header.accept_application.string",
3601 FT_STRING, BASE_NONE, NULL, 0x00,
3602 "Accept-Application", HFILL
3605 { &hf_wsp_header_accept_charset,
3607 "wsp.header.accept_charset",
3608 FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
3609 "Accept-Charset", HFILL
3612 { &hf_wsp_header_accept_charset_str,
3614 "wsp.header.accept_charset.string",
3615 FT_STRING, BASE_NONE, NULL, 0x00,
3616 "Accept-Charset", HFILL
3619 { &hf_wsp_header_accept_language,
3620 { "Accept-Language",
3621 "wsp.header.accept_language",
3622 FT_UINT8, BASE_HEX, VALS ( vals_languages ), 0x00,
3623 "Accept-Language", HFILL
3626 { &hf_wsp_header_accept_language_str,
3627 { "Accept-Language",
3628 "wsp.header.accept_language.string",
3629 FT_STRING, BASE_NONE, NULL, 0x00,
3630 "Accept-Language", HFILL
3633 { &hf_wsp_header_accept_ranges,
3635 "wsp.header.accept_ranges",
3636 FT_UINT8, BASE_HEX, VALS ( vals_accept_ranges ), 0x00,
3637 "Accept-Ranges", HFILL
3640 { &hf_wsp_header_accept_ranges_str,
3642 "wsp.header.accept_ranges.string",
3643 FT_STRING, BASE_NONE, NULL, 0x00,
3644 "Accept-Ranges", HFILL
3647 { &hf_wsp_header_age,
3650 FT_UINT32, BASE_DEC, NULL, 0x00,
3654 { &hf_wsp_header_bearer_indication,
3656 * XXX - I'm assuming that the bearer indication is
3657 * just a bearer type.
3659 { "Bearer-indication",
3660 "wsp.header.bearer_indication",
3661 FT_UINT32, BASE_HEX, VALS(vals_bearer_types), 0x00,
3662 "Bearer-indication", HFILL
3665 { &hf_wsp_header_cache_control,
3667 "wsp.header.cache_control",
3668 FT_UINT8, BASE_HEX, VALS ( vals_cache_control ), 0x00,
3669 "Cache-Control", HFILL
3672 { &hf_wsp_header_cache_control_str,
3674 "wsp.header.cache_control.string",
3675 FT_STRING, BASE_NONE, NULL, 0x00,
3676 "Cache-Control", HFILL
3679 { &hf_wsp_header_cache_control_field_name,
3681 "wsp.header.cache_control.field_name",
3682 FT_UINT8, BASE_HEX, VALS ( vals_field_names ), 0x00,
3683 "Cache-Control field name", HFILL
3686 { &hf_wsp_header_cache_control_field_name_str,
3688 "wsp.header.cache_control.field_name.str",
3689 FT_STRING, BASE_NONE, NULL, 0x00,
3690 "Cache-Control field name", HFILL
3693 { &hf_wsp_header_connection,
3695 "wsp.header.connection",
3696 FT_UINT8, BASE_HEX, VALS ( vals_connection ), 0x00,
3700 { &hf_wsp_header_connection_str,
3702 "wsp.header.connection_str",
3703 FT_STRING, BASE_NONE, NULL, 0x00,
3707 { &hf_wsp_header_content_length,
3709 "wsp.header.content_length",
3710 FT_UINT32, BASE_DEC, NULL, 0x00,
3711 "Content-Length", HFILL
3714 { &hf_wsp_header_date,
3717 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3721 { &hf_wsp_header_etag,
3724 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3725 FT_STRING, BASE_NONE, NULL, 0x00,
3729 { &hf_wsp_header_expires,
3731 "wsp.header.expires",
3732 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3736 { &hf_wsp_header_last_modified,
3738 "wsp.header.last_modified",
3739 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3740 "Last-Modified", HFILL
3743 { &hf_wsp_header_location,
3745 "wsp.header.location",
3746 FT_STRING, BASE_NONE, NULL, 0x00,
3750 { &hf_wsp_header_if_modified_since,
3751 { "If-Modified-Since",
3752 "wsp.header.if_modified_since",
3753 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3754 "If-Modified-Since", HFILL
3757 { &hf_wsp_header_pragma,
3759 "wsp.header.pragma",
3760 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3761 FT_STRING, BASE_NONE, NULL, 0x00,
3765 { &hf_wsp_header_profile,
3767 "wsp.header.profile",
3768 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3769 FT_STRING, BASE_NONE, NULL, 0x00,
3773 { &hf_wsp_header_server,
3775 "wsp.header.server",
3776 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3777 FT_STRING, BASE_NONE, NULL, 0x00,
3781 { &hf_wsp_header_transfer_encoding,
3782 { "Transfer Encoding",
3783 "wsp.header.transfer_enc",
3784 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3785 FT_UINT8, BASE_HEX, VALS ( vals_transfer_encoding ), 0x00,
3786 "Transfer Encoding", HFILL
3789 { &hf_wsp_header_transfer_encoding_str,
3790 { "Transfer Encoding",
3791 "wsp.header.transfer_enc_str",
3792 FT_STRING, BASE_NONE, NULL, 0x00,
3793 "Transfer Encoding", HFILL
3796 { &hf_wsp_header_user_agent,
3798 "wsp.header.user_agent",
3799 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
3800 FT_STRING, BASE_NONE, NULL, 0x00,
3804 { &hf_wsp_header_via,
3807 FT_STRING, BASE_NONE, NULL, 0x00,
3811 { &hf_wsp_header_wap_application_id,
3812 { "X-Wap-Application-Id",
3813 "wsp.header.wap_application_id",
3814 FT_UINT8, BASE_HEX, NULL, 0x00,
3815 "WAP application id", HFILL
3818 { &hf_wsp_header_wap_application_id_str,
3819 { "X-Wap-Application-Id",
3820 "wsp.header.wap_application_id.string",
3821 FT_STRING, BASE_NONE, NULL, 0x00,
3822 "WAP application id", HFILL
3825 { &hf_wsp_header_warning,
3827 "wsp.header.warning",
3828 FT_NONE, BASE_NONE, NULL, 0x00,
3832 { &hf_wsp_header_warning_code,
3834 "wsp.header.warning.code",
3835 FT_UINT32, BASE_DEC, NULL, 0x00,
3836 "Warning Code", HFILL
3839 { &hf_wsp_header_warning_agent,
3841 "wsp.header.warning.agent",
3842 FT_STRING, BASE_NONE, NULL, 0x00,
3843 "Warning Agent", HFILL
3846 { &hf_wsp_header_warning_text,
3848 "wsp.header.warning.text",
3849 FT_STRING, BASE_NONE, NULL, 0x00,
3850 "Warning Text", HFILL
3853 { &hf_wsp_header_application_header,
3854 { "Application Header",
3855 "wsp.header.application_header",
3856 FT_STRING, BASE_NONE, NULL, 0x00,
3857 "Application Header", HFILL
3860 { &hf_wsp_header_application_value,
3861 { "Application Header Value",
3862 "wsp.header.application_header.value",
3863 FT_STRING, BASE_NONE, NULL, 0x00,
3864 "Application Header Value", HFILL
3867 { &hf_wsp_header_x_wap_tod,
3869 "wsp.header.x_wap_tod",
3870 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
3874 { &hf_wsp_capabilities_client_SDU,
3876 "wsp.capabilities.client_SDU",
3877 FT_UINT8, BASE_DEC, NULL, 0x00,
3881 { &hf_wsp_capabilities_server_SDU,
3883 "wsp.capabilities.server_SDU",
3884 FT_UINT8, BASE_DEC, NULL, 0x00,
3888 { &hf_wsp_capabilities_protocol_opt,
3889 { "Protocol Options",
3890 "wsp.capabilities.protocol_opt",
3891 FT_STRING, BASE_HEX, NULL, 0x00,
3892 "Protocol Options", HFILL
3895 { &hf_wsp_capabilities_method_MOR,
3897 "wsp.capabilities.method_mor",
3898 FT_UINT8, BASE_DEC, NULL, 0x00,
3902 { &hf_wsp_capabilities_push_MOR,
3904 "wsp.capabilities.push_mor",
3905 FT_UINT8, BASE_DEC, NULL, 0x00,
3909 { &hf_wsp_capabilities_extended_methods,
3910 { "Extended Methods",
3911 "wsp.capabilities.extend_methods",
3912 FT_STRING, BASE_HEX, NULL, 0x00,
3913 "Extended Methods", HFILL
3916 { &hf_wsp_capabilities_header_code_pages,
3917 { "Header Code Pages",
3918 "wsp.capabilities.code_pages",
3919 FT_STRING, BASE_HEX, NULL, 0x00,
3920 "Header Code Pages", HFILL
3923 { &hf_wsp_capabilities_aliases,
3925 "wsp.capabilities.aliases",
3926 FT_UINT8, BASE_HEX, NULL, 0x00,
3930 { &hf_wsp_post_data,
3933 FT_NONE, BASE_NONE, NULL, 0x00,
3937 { &hf_wsp_push_data,
3940 FT_NONE, BASE_NONE, NULL, 0x00,
3944 { &hf_wsp_redirect_flags,
3946 "wsp.redirect_flags",
3947 FT_UINT8, BASE_HEX, NULL, 0x00,
3948 "Redirect Flags", HFILL
3951 { &hf_wsp_redirect_permanent,
3952 { "Permanent Redirect",
3953 "wsp.redirect_flags.permanent",
3954 FT_BOOLEAN, 8, TFS(&yes_no_truth), PERMANENT_REDIRECT,
3955 "Permanent Redirect", HFILL
3958 { &hf_wsp_redirect_reuse_security_session,
3959 { "Reuse Security Session",
3960 "wsp.redirect_flags.reuse_security_session",
3961 FT_BOOLEAN, 8, TFS(&yes_no_truth), REUSE_SECURITY_SESSION,
3962 "Permanent Redirect", HFILL
3965 { &hf_wsp_redirect_afl,
3968 FT_UINT8, BASE_HEX, NULL, 0x00,
3969 "Redirect Address Flags/Length", HFILL
3972 { &hf_wsp_redirect_afl_bearer_type_included,
3973 { "Bearer Type Included",
3974 "wsp.redirect_afl.bearer_type_included",
3975 FT_BOOLEAN, 8, TFS(&yes_no_truth), BEARER_TYPE_INCLUDED,
3976 "Redirect Address bearer type included", HFILL
3979 { &hf_wsp_redirect_afl_port_number_included,
3980 { "Port Number Included",
3981 "wsp.redirect_afl.port_number_included",
3982 FT_BOOLEAN, 8, TFS(&yes_no_truth), PORT_NUMBER_INCLUDED,
3983 "Redirect Address port number included", HFILL
3986 { &hf_wsp_redirect_afl_address_len,
3988 "wsp.redirect_afl.address_len",
3989 FT_UINT8, BASE_DEC, NULL, ADDRESS_LEN,
3990 "Redirect Address Length", HFILL
3993 { &hf_wsp_redirect_bearer_type,
3995 "wsp.redirect_bearer_type",
3996 FT_UINT8, BASE_HEX, VALS(vals_bearer_types), 0x0,
3997 "Redirect Bearer Type", HFILL
4000 { &hf_wsp_redirect_port_num,
4002 "wsp.redirect_port_num",
4003 FT_UINT16, BASE_DEC, NULL, 0x0,
4004 "Redirect Port Number", HFILL
4007 { &hf_wsp_redirect_ipv4_addr,
4009 "wsp.redirect_ipv4_addr",
4010 FT_IPv4, BASE_NONE, NULL, 0x0,
4011 "Redirect Address (IP)", HFILL
4014 { &hf_wsp_redirect_ipv6_addr,
4016 "wsp.redirect_ipv6_addr",
4017 FT_IPv6, BASE_NONE, NULL, 0x0,
4018 "Redirect Address (IPv6)", HFILL
4021 { &hf_wsp_redirect_addr,
4023 "wsp.redirect_addr",
4024 FT_BYTES, BASE_NONE, NULL, 0x0,
4025 "Redirect Address", HFILL
4030 /* Setup protocol subtree array */
4031 static gint *ett[] = {
4033 &ett_content_type_parameters,
4036 &ett_header_warning,
4037 &ett_header_cache_control_parameters,
4038 &ett_header_cache_control_field_names,
4041 &ett_redirect_flags,
4045 /* Register the protocol name and description */
4046 proto_wsp = proto_register_protocol(
4047 "Wireless Session Protocol", /* protocol name for use by ethereal */
4048 "WSP", /* short version of name */
4049 "wap-wsp" /* Abbreviated protocol name, should Match IANA
4050 < URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
4054 /* Required function calls to register the header fields and subtrees used */
4055 proto_register_field_array(proto_wsp, hf, array_length(hf));
4056 proto_register_subtree_array(ett, array_length(ett));
4058 register_dissector("wsp-co", dissect_wsp_fromwap_co, proto_wsp);
4059 register_dissector("wsp-cl", dissect_wsp_fromwap_cl, proto_wsp);
4060 register_heur_dissector_list("wsp", &heur_subdissector_list);
4062 wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
4067 proto_reg_handoff_wsp(void)
4070 * Get a handle for the WMLC dissector.
4072 wmlc_handle = find_dissector("wmlc"); /* Coming soon :) */
4075 * And get a handle for the WTP-over-UDP dissector.
4077 wtp_fromudp_handle = find_dissector("wtp-udp");
4079 /* Only connection-less WSP has no previous handler */
4080 dissector_add("udp.port", UDP_PORT_WSP, dissect_wsp_fromudp, proto_wsp);
4081 dissector_add("udp.port", UDP_PORT_WSP_PUSH, dissect_wsp_fromudp, proto_wsp);
4083 /* This dissector is also called from the WTP and WTLS dissectors */