3 * Routines to dissect WSP component of WAP traffic.
5 * $Id: packet-wsp.c,v 1.19 2001/02/19 21:02:33 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Didier Jorand
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 "packet-wap.h"
58 #include "packet-wsp.h"
60 /* File scoped variables for the protocol and registered fields */
61 static int proto_wsp = HF_EMPTY;
63 /* These fields used by fixed part of header */
64 static int hf_wsp_header_tid = HF_EMPTY;
65 static int hf_wsp_header_pdu_type = HF_EMPTY;
66 static int hf_wsp_version_major = HF_EMPTY;
67 static int hf_wsp_version_minor = HF_EMPTY;
68 static int hf_wsp_capability_length = HF_EMPTY;
69 static int hf_wsp_capabilities_section = HF_EMPTY;
70 static int hf_wsp_header_uri_len = HF_EMPTY;
71 static int hf_wsp_header_uri = HF_EMPTY;
72 static int hf_wsp_server_session_id = HF_EMPTY;
73 static int hf_wsp_header_status = HF_EMPTY;
74 static int hf_wsp_header_length = HF_EMPTY;
75 static int hf_wsp_headers_section = HF_EMPTY;
76 static int hf_wsp_header = HF_EMPTY;
77 static int hf_wsp_content_type = HF_EMPTY;
78 static int hf_wsp_parameter_well_known_charset = HF_EMPTY;
79 static int hf_wsp_reply_data = HF_EMPTY;
80 static int hf_wsp_post_data = HF_EMPTY;
82 static int hf_wsp_header_accept = HF_EMPTY;
83 static int hf_wsp_header_accept_str = HF_EMPTY;
84 static int hf_wsp_header_accept_charset = HF_EMPTY;
85 static int hf_wsp_header_accept_charset_str = HF_EMPTY;
86 static int hf_wsp_header_accept_language = HF_EMPTY;
87 static int hf_wsp_header_accept_language_str = HF_EMPTY;
88 static int hf_wsp_header_accept_ranges = HF_EMPTY;
89 static int hf_wsp_header_cache_control = HF_EMPTY;
90 static int hf_wsp_header_content_length = HF_EMPTY;
91 static int hf_wsp_header_age = HF_EMPTY;
92 static int hf_wsp_header_date = HF_EMPTY;
93 static int hf_wsp_header_etag = HF_EMPTY;
94 static int hf_wsp_header_expires = HF_EMPTY;
95 static int hf_wsp_header_last_modified = HF_EMPTY;
96 static int hf_wsp_header_location = HF_EMPTY;
97 static int hf_wsp_header_if_modified_since = HF_EMPTY;
98 static int hf_wsp_header_server = HF_EMPTY;
99 static int hf_wsp_header_user_agent = HF_EMPTY;
100 static int hf_wsp_header_application_header = HF_EMPTY;
101 static int hf_wsp_header_application_value = HF_EMPTY;
102 static int hf_wsp_header_x_wap_tod = HF_EMPTY;
103 static int hf_wsp_header_transfer_encoding = HF_EMPTY;
104 static int hf_wsp_header_transfer_encoding_str = HF_EMPTY;
105 static int hf_wsp_header_via = HF_EMPTY;
107 /* Initialize the subtree pointers */
108 static gint ett_wsp = ETT_EMPTY;
109 static gint ett_header = ETT_EMPTY;
110 static gint ett_headers = ETT_EMPTY;
111 static gint ett_capabilities = ETT_EMPTY;
112 static gint ett_content_type = ETT_EMPTY;
114 /* Handle for WMLC dissector */
115 static dissector_handle_t wmlc_handle;
117 static const value_string vals_pdu_type[] = {
118 { 0x00, "Reserved" },
120 { 0x02, "ConnectReply" },
121 { 0x03, "Redirect" },
123 { 0x05, "Disconnect" },
125 { 0x07, "ConfirmedPush" },
129 /* 0x10 - 0x3F Unassigned */
137 /* 0x45 - 0x4F Unassigned (Get PDU) */
138 /* 0x50 - 0x5F Extended method (Get PDU) */
143 /* 0x62 - 0x6F Unassigned (Post PDU) */
144 /* 0x70 - 0x7F Extended method (Post PDU) */
145 /* 0x80 - 0xFF Reserved */
151 static const value_string vals_status[] = {
152 /* 0x00 - 0x0F Reserved */
154 { 0x10, "Continue" },
155 { 0x11, "Switching Protocols" },
159 { 0x22, "Accepted" },
160 { 0x23, "Non-Authoritative Information" },
161 { 0x24, "No Content" },
162 { 0x25, "Reset Content" },
163 { 0x26, "Partial Content" },
165 { 0x30, "Multiple Choices" },
166 { 0x31, "Moved Permanently" },
167 { 0x32, "Moved Temporarily" },
168 { 0x33, "See Other" },
169 { 0x34, "Not Modified" },
170 { 0x35, "Use Proxy" },
172 { 0x40, "Bad Request" },
173 { 0x41, "Unauthorised" },
174 { 0x42, "Payment Required" },
175 { 0x43, "Forbidden" },
176 { 0x44, "Not Found" },
177 { 0x45, "Method Not Allowed" },
178 { 0x46, "Not Acceptable" },
179 { 0x47, "Proxy Authentication Required" },
180 { 0x48, "Request Timeout" },
181 { 0x49, "Conflict" },
183 { 0x4B, "Length Required" },
184 { 0x4C, "Precondition Failed" },
185 { 0x4D, "Request Entity Too Large" },
186 { 0x4E, "Request-URI Too Large" },
187 { 0x4F, "Unsupported Media Type" },
189 { 0x60, "Internal Server Error" },
190 { 0x61, "Not Implemented" },
191 { 0x62, "Bad Gateway" },
192 { 0x63, "Service Unavailable" },
193 { 0x64, "Gateway Timeout" },
194 { 0x65, "HTTP Version Not Supported" },
198 static const value_string vals_content_types[] = {
201 { 0x02, "text/html" },
202 { 0x03, "text/plain" },
203 { 0x04, "text/x-hdml" },
204 { 0x05, "text/x-ttml" },
205 { 0x06, "text/x-vCalendar" },
206 { 0x07, "text/x-vCard" },
207 { 0x08, "text/vnd.wap.wml" },
208 { 0x09, "text/vnd.wap.wmlscript" },
209 { 0x0A, "text/vnd.wap.channel" },
210 { 0x0B, "Multipart/*" },
211 { 0x0C, "Multipart/mixed" },
212 { 0x0D, "Multipart/form-data" },
213 { 0x0E, "Multipart/byteranges" },
214 { 0x0F, "Multipart/alternative" },
215 { 0x10, "application/*" },
216 { 0x11, "application/java-vm" },
217 { 0x12, "application/x-www-form-urlencoded" },
218 { 0x13, "application/x-hdmlc" },
219 { 0x14, "application/vnd.wap.wmlc" },
220 { 0x15, "application/vnd.wap.wmlscriptc" },
221 { 0x16, "application/vnd.wap.channelc" },
222 { 0x17, "application/vnd.wap.uaprof" },
223 { 0x18, "application/vnd.wap.wtls-ca-certificate" },
224 { 0x19, "application/vnd.wap.wtls-user-certificate" },
225 { 0x1A, "application/x-x509-ca-cert" },
226 { 0x1B, "application/x-x509-user-cert" },
228 { 0x1D, "image/gif" },
229 { 0x1E, "image/jpeg" },
230 { 0x1F, "image/tiff" },
231 { 0x20, "image/png" },
232 { 0x21, "image/vnd.wap.wbmp" },
233 { 0x22, "application/vnd.wap.multipart.*" },
234 { 0x23, "application/vnd.wap.multipart.mixed" },
235 { 0x24, "application/vnd.wap.multipart.form-data" },
236 { 0x25, "application/vnd.wap.multipart.byteranges" },
237 { 0x26, "application/vnd.wap.multipart.alternative" },
238 { 0x27, "application/xml" },
239 { 0x28, "text/xml" },
240 { 0x29, "application/vnd.wap.wbxml" },
241 { 0x2A, "application/x-x968-cross-cert" },
242 { 0x2B, "application/x-x968-ca-cert" },
243 { 0x2C, "application/x-x968-user-cert" },
244 { 0x2D, "text/vnd.wap.si" },
245 { 0x2E, "application/vnd.wap.sic" },
246 { 0x2F, "text/vnd.wap.sl" },
247 { 0x30, "application/vnd.wap.slc" },
248 { 0x31, "text/vnd.wap.co" },
249 { 0x32, "application/vnd.wap.coc" },
250 { 0x33, "application/vnd.wap.multipart.related" },
251 { 0x34, "application/vnd.wap.sia" },
255 static const value_string vals_languages[] = {
256 { 0x01, "Afar (aa)" },
257 { 0x02, "Abkhazian (ab)" },
258 { 0x03, "Afrikaans (af)" },
259 { 0x04, "Amharic (am)" },
260 { 0x05, "Arabic (ar)" },
261 { 0x06, "Assamese (as)" },
262 { 0x07, "Aymara (ay)" },
263 { 0x08, "Azerbaijani (az)" },
264 { 0x09, "Bashkir (ba)" },
265 { 0x0A, "Byelorussian (be)" },
266 { 0x0B, "Bulgarian (bg)" },
267 { 0x0C, "Bihari (bh)" },
268 { 0x0D, "Bislama (bi)" },
269 { 0x0E, "Bengali; Bangla (bn)" },
270 { 0x0F, "Tibetan (bo)" },
271 { 0x10, "Breton (br)" },
272 { 0x11, "Catalan (ca)" },
273 { 0x12, "Corsican (co)" },
274 { 0x13, "Czech (cs)" },
275 { 0x14, "Welsh (cy)" },
276 { 0x15, "Danish (da)" },
277 { 0x16, "German (de)" },
278 { 0x17, "Bhutani (dz)" },
279 { 0x18, "Greek (el)" },
280 { 0x19, "English (en)" },
281 { 0x1A, "Esperanto (eo)" },
282 { 0x1B, "Spanish (es)" },
283 { 0x1C, "Estonian (et)" },
284 { 0x1D, "Basque (eu)" },
285 { 0x1E, "Persian (fa)" },
286 { 0x1F, "Finnish (fi)" },
287 { 0x20, "Fiji (fj)" },
288 { 0x22, "French (fr)" },
289 { 0x24, "Irish (ga)" },
290 { 0x25, "Scots Gaelic (gd)" },
291 { 0x26, "Galician (gl)" },
292 { 0x27, "Guarani (gn)" },
293 { 0x28, "Gujarati (gu)" },
294 { 0x29, "Hausa (ha)" },
295 { 0x2A, "Hebrew (formerly iw) (he)" },
296 { 0x2B, "Hindi (hi)" },
297 { 0x2C, "Croatian (hr)" },
298 { 0x2D, "Hungarian (hu)" },
299 { 0x2E, "Armenian (hy)" },
300 { 0x30, "Indonesian (formerly in) (id)" },
301 { 0x47, "Maori (mi)" },
302 { 0x48, "Macedonian (mk)" },
303 { 0x49, "Malayalam (ml)" },
304 { 0x4A, "Mongolian (mn)" },
305 { 0x4B, "Moldavian (mo)" },
306 { 0x4C, "Marathi (mr)" },
307 { 0x4D, "Malay (ms)" },
308 { 0x4E, "Maltese (mt)" },
309 { 0x4F, "Burmese (my)" },
310 { 0x51, "Nepali (ne)" },
311 { 0x52, "Dutch (nl)" },
312 { 0x53, "Norwegian (no)" },
313 { 0x54, "Occitan (oc)" },
314 { 0x55, "(Afan) Oromo (om)" },
315 { 0x56, "Oriya (or)" },
316 { 0x57, "Punjabi (pa)" },
317 { 0x58, "Polish (po)" },
318 { 0x59, "Pashto, Pushto (ps)" },
319 { 0x5A, "Portuguese (pt)" },
320 { 0x5B, "Quechua (qu)" },
321 { 0x5D, "Kirundi (rn)" },
322 { 0x5E, "Romanian (ro)" },
323 { 0x5F, "Russian (ru)" },
324 { 0x60, "Kinyarwanda (rw)" },
325 { 0x61, "Sanskrit (sa)" },
326 { 0x62, "Sindhi (sd)" },
327 { 0x63, "Sangho (sg)" },
328 { 0x64, "Serbo-Croatian (sh)" },
329 { 0x65, "Sinhalese (si)" },
330 { 0x66, "Slovak (sk)" },
331 { 0x67, "Slovenian (sl)" },
332 { 0x68, "Samoan (sm)" },
333 { 0x69, "Shona (sn)" },
334 { 0x6A, "Somali (so)" },
335 { 0x6B, "Albanian (sq)" },
336 { 0x6C, "Serbian (sr)" },
337 { 0x6D, "Siswati (ss)" },
338 { 0x6E, "Sesotho (st)" },
339 { 0x6F, "Sundanese (su)" },
340 { 0x70, "Swedish (sv)" },
341 { 0x71, "Swahili (sw)" },
342 { 0x72, "Tamil (ta)" },
343 { 0x73, "Telugu (te)" },
344 { 0x74, "Tajik (tg)" },
345 { 0x75, "Thai (th)" },
346 { 0x76, "Tigrinya (ti)" },
347 { 0x81, "Nauru (na)" },
348 { 0x82, "Faeroese (fo)" },
349 { 0x83, "Frisian (fy)" },
350 { 0x84, "Interlingua (ia)" },
351 { 0x8C, "Rhaeto-Romance (rm)" },
355 static const value_string vals_accept_ranges[] = {
361 static const value_string vals_cache_control[] = {
362 { 0x80, "No-cache" },
363 { 0x81, "No-store" },
365 { 0x83, "Max-stale" },
366 { 0x84, "Min-fresh" },
367 { 0x85, "Only-if-cached" },
370 { 0x88, "No-transform" },
371 { 0x89, "Must-revalidate" },
372 { 0x8A, "Proxy-revalidate" },
376 static const value_string vals_transfer_encoding[] = {
382 * Windows appears to define DELETE.
392 REDIRECT = 0x03, /* No sample data */
395 PUSH = 0x06, /* No sample data */
396 CONFIRMEDPUSH = 0x07, /* No sample data */
397 SUSPEND = 0x08, /* No sample data */
398 RESUME = 0x09, /* No sample data */
401 OPTIONS = 0x41, /* No sample data */
402 HEAD = 0x42, /* No sample data */
403 DELETE = 0x43, /* No sample data */
404 TRACE = 0x44, /* No sample data */
407 PUT = 0x61, /* No sample data */
410 static void add_uri (proto_tree *, tvbuff_t *, guint, guint);
411 static void add_headers (proto_tree *, tvbuff_t *);
412 static void add_header (proto_tree *, tvbuff_t *, tvbuff_t *);
413 static guint get_value_length (tvbuff_t *, guint, guint *);
414 static guint add_content_type (proto_tree *, tvbuff_t *, guint, guint *);
415 static gint get_date_value (tvbuff_t * ,guint ,struct timeval *);
416 static void add_date_value (tvbuff_t * ,guint ,proto_tree * ,int ,
417 tvbuff_t * ,guint ,guint ,struct timeval *, const char *);
418 static guint add_parameter (proto_tree *, tvbuff_t *, guint);
419 static guint add_parameter_charset (proto_tree *, tvbuff_t *, guint, guint);
420 static void add_post_data (proto_tree *, tvbuff_t *, guint);
421 static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
423 /* Code to actually dissect the packets */
425 dissect_wsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
427 frame_data *fdata = pinfo->fd;
435 guint capabilityLength = 0;
436 guint capabilityStart = 0;
437 guint headersLength = 0;
438 guint headerLength = 0;
439 guint headerStart = 0;
440 guint nextOffset = 0;
441 guint contentTypeStart = 0;
442 guint contentType = 0;
445 /* Set up structures we will need to add the protocol subtree and manage it */
447 proto_tree *wsp_tree;
448 /* proto_tree *wsp_header_fixed; */
449 proto_tree *wsp_capabilities;
451 /* This field shows up as the "Info" column in the display; you should make
452 it, if possible, summarize what's in the packet, so that a user looking
453 at the list of packets can tell what type of packet it is. */
455 /* Display protocol type depending on the port */
456 if (check_col(fdata, COL_PROTOCOL))
458 switch ( pinfo->match_port )
461 col_set_str(fdata, COL_PROTOCOL, "WSP" );
463 case UDP_PORT_WTLS_WSP:
464 col_set_str(fdata, COL_PROTOCOL, "WTLS+WSP" );
469 /* Clear the Info column before we fetch anything from the packet */
470 if (check_col(fdata, COL_INFO))
472 col_clear(fdata, COL_INFO);
475 /* Connection-less mode has a TID first */
476 if ( (pinfo->match_port == UDP_PORT_WSP) ||
477 (pinfo->match_port == UDP_PORT_WTLS_WSP))
482 /* Find the PDU type */
483 pdut = tvb_get_guint8 (tvb, offset);
485 /* Develop the string to put in the Info column */
486 if (check_col(fdata, COL_INFO))
488 col_add_fstr(fdata, COL_INFO, "WSP %s",
489 val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"));
492 /* In the interest of speed, if "tree" is NULL, don't do any work not
493 necessary to generate protocol tree items. */
495 ti = proto_tree_add_item(tree, proto_wsp, tvb, 0,
496 tvb_length(tvb), bo_little_endian);
497 wsp_tree = proto_item_add_subtree(ti, ett_wsp);
499 /* Code to process the packet goes here */
501 wsp_header_fixed = proto_item_add_subtree(ti, ett_header );
504 /* Add common items: only TID and PDU Type */
506 /* If this is connectionless, then the TID Field is always first */
507 if ( (pinfo->match_port == UDP_PORT_WSP) ||
508 (pinfo->match_port == UDP_PORT_WTLS_WSP))
510 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,tvb,
511 0,1,bo_little_endian);
514 ti = proto_tree_add_item(
516 hf_wsp_header_pdu_type, /* id */
518 offset++, /* start of high light */
519 1, /* length of high light */
520 bo_little_endian /* value */
526 ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,tvb,offset,1,bo_little_endian);
527 ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,tvb,offset,1,bo_little_endian);
529 capabilityStart = offset;
530 count = 0; /* Initialise count */
531 capabilityLength = tvb_get_guintvar (tvb, offset, &count);
533 ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,tvb,capabilityStart,count,capabilityLength);
535 headerStart = offset;
536 count = 0; /* Initialise count */
537 headerLength = tvb_get_guintvar (tvb, offset, &count);
539 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,headerLength);
540 if (capabilityLength > 0)
542 ti = proto_tree_add_item (wsp_tree, hf_wsp_capabilities_section,tvb,offset,capabilityLength,bo_little_endian);
543 wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
544 offset += capabilityLength;
547 if (headerLength > 0)
549 tmp_tvb = tvb_new_subset (tvb, offset, headerLength, headerLength);
550 add_headers (wsp_tree, tmp_tvb);
556 count = 0; /* Initialise count */
557 value = tvb_get_guintvar (tvb, offset, &count);
558 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
561 capabilityStart = offset;
562 count = 0; /* Initialise count */
563 capabilityLength = tvb_get_guintvar (tvb, offset, &count);
565 ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,tvb,capabilityStart,count,capabilityLength);
567 headerStart = offset;
568 count = 0; /* Initialise count */
569 headerLength = tvb_get_guintvar (tvb, offset, &count);
571 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,headerLength);
572 if (capabilityLength > 0)
574 ti = proto_tree_add_item (wsp_tree, hf_wsp_capabilities_section,tvb,offset,capabilityLength,bo_little_endian);
575 wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
576 offset += capabilityLength;
579 if (headerLength > 0)
583 ti = proto_tree_add_item (wsp_tree, hf_wsp_headers_section,tvb,offset,headerLength,bo_little_endian);
584 wsp_headers = proto_item_add_subtree( ti, ett_headers );
586 tmp_tvb = tvb_new_subset (tvb, offset, headerLength, headerLength);
587 add_headers (wsp_tree, tmp_tvb);
593 count = 0; /* Initialise count */
594 value = tvb_get_guintvar (tvb, offset, &count);
595 ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
599 count = 0; /* Initialise count */
600 /* Length of URI and size of URILen field */
601 value = tvb_get_guintvar (tvb, offset, &count);
602 nextOffset = offset + count;
603 add_uri (wsp_tree, tvb, offset, nextOffset);
604 offset += (value+count); /* VERIFY */
605 tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
606 add_headers (wsp_tree, tmp_tvb);
611 count = 0; /* Initialise count */
612 uriLength = tvb_get_guintvar (tvb, offset, &count);
613 headerStart = uriStart+count;
614 count = 0; /* Initialise count */
615 headersLength = tvb_get_guintvar (tvb, headerStart, &count);
616 offset = headerStart + count;
618 add_uri (wsp_tree, tvb, uriStart, offset);
621 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,bo_little_endian);
623 contentTypeStart = offset;
624 nextOffset = add_content_type (wsp_tree, tvb, offset, &contentType);
626 /* Add headers subtree that will hold the headers fields */
627 /* Runs from nextOffset for value-(length of content-type field)*/
628 headerLength = headersLength-(nextOffset-contentTypeStart);
629 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
630 add_headers (wsp_tree, tmp_tvb);
632 /* TODO: Post DATA */
633 /* Runs from start of headers+headerLength to END_OF_FRAME */
634 offset = nextOffset+headerLength;
635 tmp_tvb = tvb_new_subset (tvb, offset, tvb_reported_length (tvb)-offset, tvb_reported_length (tvb)-offset);
636 add_post_data (wsp_tree, tmp_tvb, contentType);
640 ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
641 count = 0; /* Initialise count */
642 value = tvb_get_guintvar (tvb, offset+1, &count);
643 nextOffset = offset + 1 + count;
644 ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset+1,count,value);
646 contentTypeStart = nextOffset;
647 nextOffset = add_content_type (wsp_tree, tvb, nextOffset, &contentType);
649 /* Add headers subtree that will hold the headers fields */
650 /* Runs from nextOffset for value-(length of content-type field)*/
651 headerLength = value-(nextOffset-contentTypeStart);
652 tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
653 add_headers (wsp_tree, tmp_tvb);
654 offset += count+value+1;
656 /* TODO: Data - decode WMLC */
657 /* Runs from offset+1+count+value+1 to END_OF_FRAME */
658 if (offset < tvb_reported_length (tvb))
660 ti = proto_tree_add_item (wsp_tree, hf_wsp_reply_data,tvb,offset,END_OF_FRAME,bo_little_endian);
668 add_uri (proto_tree *tree, tvbuff_t *tvb, guint URILenOffset, guint URIOffset)
671 guint8 terminator = 0;
675 guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
677 ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,tvb,URILenOffset,count,uriLen);
679 /* If string doesn't end with a 0x00, we need to add one to be on the safe side */
680 terminator = tvb_get_guint8 (tvb, URIOffset+uriLen-1);
683 newBuffer = g_malloc (uriLen+1);
684 strncpy (newBuffer, tvb_get_ptr (tvb, URIOffset, uriLen), uriLen);
685 newBuffer[uriLen] = 0;
686 ti = proto_tree_add_string (tree, hf_wsp_header_uri,tvb,URIOffset,uriLen,newBuffer);
691 ti = proto_tree_add_item (tree, hf_wsp_header_uri,tvb,URIOffset,uriLen,bo_little_endian);
696 add_headers (proto_tree *tree, tvbuff_t *tvb)
699 proto_tree *wsp_headers;
701 guint headersLen = tvb_reported_length (tvb);
702 guint8 headerStart = 0;
704 tvbuff_t *header_buff;
705 tvbuff_t *value_buff;
707 guint valueStart = 0;
711 fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, headersLen);
721 fprintf (stderr, "dissect_wsp: Headers to process\n");
724 ti = proto_tree_add_item (tree, hf_wsp_headers_section,tvb,offset,headersLen,bo_little_endian);
725 wsp_headers = proto_item_add_subtree( ti, ett_headers );
729 while (offset < headersLen)
731 /* Loop round each header */
732 headerStart = offset;
733 peek = tvb_get_guint8 (tvb, headerStart);
735 if (peek < 32) /* Short-cut shift delimeter */
737 fprintf (stderr, "dissect_wsp: header: short-cut shift %d (0x%02X)\n", peek, peek);
740 else if (peek == 0x7F) /* Shift delimeter */
742 fprintf (stderr, "dissect_wsp: header: shift delimeter %d (0x%02X)\n", peek, peek);
748 fprintf (stderr, "dissect_wsp: header: application-header start %d (0x%02X)\n", peek, peek);
750 while (tvb_get_guint8 (tvb, offset++)) { /* Do nothing, just look for NULL */ }
752 else if (peek & 0x80) /* Well-known header */
755 fprintf (stderr, "dissect_wsp: header: well-known %d (0x%02X)\n", peek, peek);
760 /* Get value part of header */
762 peek = tvb_get_guint8 (tvb, valueStart);
766 fprintf (stderr, "dissect_wsp: Looking for %d octets\n", peek);
768 /* VERIFY: valueStart++; */
769 valueEnd = offset+1+peek;
775 fprintf (stderr, "dissect_wsp: Looking for uintvar octets\n");
777 count = 0; /* Initialise count */
778 tvb_get_guintvar (tvb, valueStart, &count);
779 valueEnd = offset+1+count;
782 else if (peek <= 127)
785 fprintf (stderr, "dissect_wsp: Looking for NULL-terminated string\n");
787 valueEnd = valueStart+1;
788 while (tvb_get_guint8 (tvb, valueEnd++)) { /* Do nothing, just look for NULL */ }
794 fprintf (stderr, "dissect_wsp: Value is %d\n", (peek & 0x7F));
800 fprintf (stderr, "dissect_wsp: Creating value buffer from offset %d, size=%d\n", headerStart, (offset-headerStart));
803 header_buff = tvb_new_subset (tvb, headerStart, (offset-headerStart), (offset-headerStart));
804 value_buff = tvb_new_subset (tvb, valueStart, (valueEnd-valueStart), (valueEnd-valueStart));
806 add_header (wsp_headers, header_buff, value_buff);
811 add_header (proto_tree *tree, tvbuff_t *header_buff, tvbuff_t *value_buff)
814 guint valueStart = 0;
815 guint8 headerType = 0;
817 guint headerLen = tvb_reported_length (header_buff);
818 guint valueLen = tvb_reported_length (value_buff);
820 struct timeval timeValue;
822 guint valueLength = 0;
824 char *valMatch = NULL;
825 double q_value = 1.0;
827 /* Initialise time values */
829 timeValue.tv_usec = 0;
831 headerType = tvb_get_guint8 (header_buff, 0);
832 peek = tvb_get_guint8 (value_buff, 0);
834 fprintf (stderr, "dissect_wsp: Got header 0x%02x\n", headerType);
835 fprintf (stderr, "dissect_wsp: First value octet is 0x%02x\n", peek);
838 if (headerType == 0x7F)
841 else if (headerType < 0x1F)
844 else if (headerType & 0x80)
846 headerType = headerType & 0x7F;
849 case 0x00: /* Accept */
852 proto_tree_add_uint (tree, hf_wsp_header_accept, header_buff, offset, headerLen, (peek & 0x7F));
856 proto_tree_add_string (tree, hf_wsp_header_accept_str,header_buff,offset,headerLen,tvb_get_ptr (value_buff, 0, valueLen));
860 case 0x01: /* Accept-Charset */
861 if (peek <= 31) /* Accept-charset-general-form */
863 /* Get Value-Length */
864 valueLength = get_value_length (value_buff, offset,
868 peek = tvb_get_guint8 (value_buff, offset);
869 if ((peek >= 0x80) || (peek <= 30)) /* Well-known-charset */
871 if (peek == 0x80) /* Any */
876 else if (peek & 0x80) /* Short-Integer */
881 else if (peek <= 30) /* Long-Integer */
888 value = tvb_get_guint8 (value_buff, offset);
891 value = tvb_get_ntohs (value_buff, offset);
894 value = tvb_get_ntoh24 (value_buff, offset);
897 value = tvb_get_ntohl (value_buff, offset);
900 /* TODO: Need to read peek octets */
902 fprintf (stderr, "dissect_wsp: accept-charset size %d NYI\n", peek);
907 valMatch = match_strval(value, vals_character_sets);
909 else /* Assume Token-text */
911 fprintf (stderr, "dissect_wsp: Accept-Charset Token-text NYI\n");
914 /* Any remaining data relates to Q-Value */
915 if (offset < valueLen)
917 peek = tvb_get_guintvar (value_buff, offset, NULL);
919 peek = (peek - 1) * 10;
924 q_value = peek/1000.0;
927 /* Build string including Q values if present */
928 if (q_value == 1.0) /* Default */
930 if (valMatch == NULL)
932 snprintf (valString, 100, "Unknown (%X)", peek);
936 snprintf (valString, 100, "%s", valMatch);
941 if (valMatch == NULL)
943 snprintf (valString, 100, "Unknown (%X); Q=%5.3f", peek,q_value);
947 snprintf (valString, 100, "%s; Q=%5.3f", valMatch,q_value);
951 /* Add string to tree */
952 proto_tree_add_string (tree, hf_wsp_header_accept_charset_str,
953 header_buff, 0, headerLen, valString);
955 else /* Constrained-charset */
957 if (peek == 0x80) /* Any-charset */
959 proto_tree_add_string (tree, hf_wsp_header_accept_charset,
960 header_buff, offset, headerLen,
963 else if (peek & 0x80) /* Short-Integer */
965 proto_tree_add_uint (tree, hf_wsp_header_accept_charset,
966 header_buff, offset, headerLen, (peek & 0x7F) );
968 else /* Assume *TEXT */
970 proto_tree_add_string (tree, hf_wsp_header_accept_charset,
971 header_buff, offset, headerLen,
972 tvb_get_ptr (value_buff, 0, valueLen));
977 case 0x03: /* Accept-Language */
980 /* Peek contains the number of octets to follow */
984 proto_tree_add_uint (tree, hf_wsp_header_accept_language, header_buff, offset,
985 headerLen, tvb_get_guint8 (value_buff, 1) );
988 proto_tree_add_uint (tree, hf_wsp_header_accept_language, header_buff, offset,
989 headerLen, tvb_get_ntohs (value_buff, 1) );
992 proto_tree_add_uint (tree, hf_wsp_header_accept_language, header_buff, offset,
993 headerLen, tvb_get_ntohl (value_buff, 1) );
996 fprintf (stderr, "dissect_wsp: accept-language size %d NYI\n", peek);
999 else if (peek & 0x80)
1001 proto_tree_add_uint (tree, hf_wsp_header_accept_language, header_buff, offset, headerLen, (peek & 0x7F) );
1005 proto_tree_add_string (tree, hf_wsp_header_accept_language_str, header_buff, offset,headerLen,
1006 tvb_get_ptr (value_buff, 0, valueLen));
1010 case 0x04: /* Accept-Ranges */
1011 if ((peek == 128) || (peek == 129))
1013 proto_tree_add_uint (tree, hf_wsp_header_accept_ranges, header_buff, offset, headerLen, peek);
1017 fprintf (stderr, "dissect_wsp: accept-ranges NYI\n");
1022 case 0x05: /* Age */
1026 proto_tree_add_uint (tree, hf_wsp_header_age, header_buff, offset, headerLen, tvb_get_guint8 (value_buff, 0));
1029 proto_tree_add_uint (tree, hf_wsp_header_age, header_buff, offset, headerLen, tvb_get_ntohs (value_buff, 0));
1032 proto_tree_add_uint (tree, hf_wsp_header_age, header_buff, offset, headerLen, tvb_get_ntoh24 (value_buff, 0));
1035 proto_tree_add_uint (tree, hf_wsp_header_age, header_buff, offset, headerLen, tvb_get_ntohl (value_buff, 0));
1040 case 0x08: /* Cache-Control */
1043 if (valueLen == 1) /* Well-known value */
1045 proto_tree_add_uint (tree, hf_wsp_header_cache_control, header_buff, offset, headerLen, peek);
1049 if ((peek == 0x82) || (peek == 0x83) || (peek == 0x84)) /* Delta seconds value to follow */
1051 value = tvb_get_guint8 (value_buff, 1);
1054 proto_tree_add_text (tree, header_buff, 0,
1055 headerLen, "Cache-Control: %s %d (0x%02X)",
1056 val_to_str (peek, vals_cache_control,
1057 "Unknown (0x%02x)"),
1058 (value & 0x7F), peek);
1062 fprintf (stderr, "dissect_wsp: Cache-Control integer value Delta seconds NYI\n");
1065 else if ((peek == 0x80) || (peek == 0x87)) /* Fields to follow */
1067 fprintf (stderr, "dissect_wsp: Cache-Control field values NYI\n");
1071 fprintf (stderr, "dissect_wsp: Cache-Control cache extension NYI\n");
1077 fprintf (stderr, "dissect_wsp: Cache-Control cache extension NYI\n");
1081 case 0x0D: /* Content-Length */
1087 proto_tree_add_uint (tree,
1088 hf_wsp_header_content_length, header_buff, offset,
1089 headerLen, tvb_get_guint8 (value_buff, 1) );
1092 proto_tree_add_uint (tree,
1093 hf_wsp_header_content_length, header_buff, offset,
1094 headerLen, tvb_get_ntohs (value_buff, 1) );
1097 proto_tree_add_uint (tree,
1098 hf_wsp_header_content_length, header_buff, offset,
1099 headerLen, (tvb_get_ntohs (value_buff, 1) << 8) +
1100 tvb_get_guint8 (value_buff, 3) );
1103 proto_tree_add_uint (tree,
1104 hf_wsp_header_content_length, header_buff, offset,
1105 headerLen, tvb_get_ntohl (value_buff, 1) );
1108 fprintf (stderr, "dissect_wsp: accept-charset size %d NYI\n", peek);
1111 else if (peek & 0x80)
1113 proto_tree_add_uint (tree, hf_wsp_header_content_length, header_buff, offset, headerLen, (peek & 0x7F));
1117 fprintf (stderr, "dissect_wsp: Content-Length long-integer size NYI\n");
1121 case 0x12: /* Date */
1122 add_date_value (value_buff, 0, tree,
1123 hf_wsp_header_date, header_buff, offset,
1124 headerLen, &timeValue, "Date");
1127 case 0x13: /* Etag */
1128 ti = proto_tree_add_string (tree, hf_wsp_header_etag,header_buff,offset,headerLen,tvb_get_ptr (value_buff, 0, valueLen));
1131 case 0x14: /* Expires */
1132 add_date_value (value_buff, 0, tree,
1133 hf_wsp_header_expires, header_buff, offset,
1134 headerLen, &timeValue, "Expires");
1137 case 0x17: /* If-Modified-Since */
1138 add_date_value (value_buff, 0, tree,
1139 hf_wsp_header_if_modified_since, header_buff, offset,
1140 headerLen, &timeValue, "If-Modified-Since");
1143 case 0x1C: /* Location */
1144 ti = proto_tree_add_string (tree, hf_wsp_header_location,header_buff,offset,headerLen,tvb_get_ptr (value_buff, 0, valueLen));
1147 case 0x1D: /* Last-Modified */
1148 add_date_value (value_buff, 0, tree,
1149 hf_wsp_header_last_modified, header_buff, offset,
1150 headerLen, &timeValue, "Last-Modified");
1153 case 0x1F: /* Pragma */
1156 proto_tree_add_text (tree, header_buff, 0, headerLen, "Pragma: No-cache");
1160 proto_tree_add_text (tree, header_buff, 0, headerLen, "Unsupported Header (0x%02X)", (tvb_get_guint8 (header_buff, 0) & 0x7F));
1164 case 0x26: /* Server */
1165 ti = proto_tree_add_string (tree, hf_wsp_header_server,header_buff,offset,headerLen,tvb_get_ptr (value_buff, 0, valueLen));
1168 case 0x27: /* Transfer encoding */
1171 proto_tree_add_uint (tree, hf_wsp_header_transfer_encoding,
1172 header_buff, offset, headerLen, peek);
1176 proto_tree_add_string (tree,
1177 hf_wsp_header_transfer_encoding_str, header_buff, offset,
1178 headerLen,tvb_get_ptr (value_buff, 0, valueLen));
1182 case 0x29: /* User-Agent */
1183 ti = proto_tree_add_string (tree, hf_wsp_header_user_agent,header_buff,offset,headerLen,tvb_get_ptr (value_buff, 0, valueLen));
1186 case 0x2B: /* Via */
1187 ti = proto_tree_add_string (tree, hf_wsp_header_via, header_buff,
1188 offset, headerLen, tvb_get_ptr (value_buff, 0, valueLen));
1192 ti = proto_tree_add_text (tree, header_buff, 0, headerLen, "Unsupported Header (0x%02X)", (tvb_get_guint8 (header_buff, 0) & 0x7F));
1198 /* Special case header X-WAP.TOD that is sometimes followed
1199 * by a 4-byte date value */
1200 if (strncasecmp ("x-wap.tod", tvb_get_ptr (header_buff, 0, headerLen), 9) == 0)
1202 peek = tvb_get_guint8 (value_buff,offset);
1205 timeValue.tv_usec = 0;
1209 timeValue.tv_sec = tvb_get_guint8 (value_buff, 1);
1212 timeValue.tv_sec = tvb_get_ntohs (value_buff, 1);
1215 timeValue.tv_sec = tvb_get_ntoh24 (value_buff, 1);
1218 timeValue.tv_sec = tvb_get_ntohl (value_buff, 1);
1221 timeValue.tv_sec = 0;
1222 fprintf (stderr, "dissect_wsp: X-WAP.TOD NYI\n");
1225 ti = proto_tree_add_time (tree, hf_wsp_header_x_wap_tod, header_buff, offset, headerLen, &timeValue);
1229 fprintf (stderr, "dissect_wsp: X-WAP.TOD peek %X NYI\n",peek);
1234 ti = proto_tree_add_text (tree, header_buff, 0, headerLen, "%s: %s", tvb_get_ptr (header_buff, 0, headerLen), tvb_get_ptr (value_buff, 0, valueLen));
1241 get_value_length (tvbuff_t *tvb, guint offset, guint *nextOffset)
1245 guint octet = tvb_get_guint8 (tvb, offset);
1247 if (octet <= 30) /* Short length */
1250 *nextOffset = offset+1;
1252 else if (octet == 31)
1254 value = tvb_get_guintvar (tvb, offset+1, &count);
1255 *nextOffset = offset+1+count;
1259 fprintf (stderr, "dissect_wsp: get_value_length: case NYI\n");
1266 add_content_type (proto_tree *tree, tvbuff_t *tvb, guint offset, guint *contentType)
1268 proto_tree *contentTypeTree;
1269 guint nextOffset = offset;
1270 guint fieldLength = 0;
1271 guint octet = tvb_get_guint8 (tvb, offset);
1272 guint totalSizeOfField = 0;
1276 fieldLength = get_value_length (tvb, offset, &nextOffset);
1277 totalSizeOfField = (nextOffset-offset)+fieldLength;
1279 else if (octet & 0x80)
1282 totalSizeOfField = 1;
1286 fprintf (stderr, "dissect-wsp: Content-type is un-supported\n");
1289 *contentType = (tvb_get_guint8 (tvb, nextOffset) & 0x7F);
1290 contentTypeTree = proto_tree_add_uint (tree, hf_wsp_content_type, tvb, offset, totalSizeOfField, (tvb_get_guint8(tvb,nextOffset++) & 0x7F));
1292 while (nextOffset < (offset+totalSizeOfField))
1295 nextOffset = add_parameter (contentTypeTree, tvb, nextOffset);
1298 return (offset+totalSizeOfField);
1301 /* Utility function to extract date values from the packet */
1303 get_date_value (tvbuff_t *buffer, guint offset, struct timeval *timeValue)
1305 guint ShortLength = 0;
1307 /* Initialise time values */
1308 timeValue->tv_sec=0;
1309 timeValue->tv_usec = 0;
1311 /* Date values are encoded as: Short-length Multi-octet-integer
1312 * Where Short-length = 0-30
1314 ShortLength = tvb_get_guint8 (buffer, offset++);
1315 if (ShortLength > 30)
1317 fprintf (stderr, "dissect_wsp: Invalid Date-value (Short-length=%d)\n",
1322 switch (ShortLength)
1325 timeValue->tv_sec = tvb_get_guint8 (buffer, offset);
1328 timeValue->tv_sec = tvb_get_ntohs (buffer, offset);
1331 timeValue->tv_sec = tvb_get_ntoh24 (buffer, offset);
1334 timeValue->tv_sec = tvb_get_ntohl (buffer, offset);
1337 fprintf (stderr, "dissect_wsp: Date-value Short-length of %d NYI\n",
1346 /* Utility function to add a date value to the protocol tree */
1348 add_date_value (tvbuff_t *buffer, guint offset, proto_tree *tree,
1349 int header, tvbuff_t *headerBuffer, guint headerOffset,
1350 guint headerLen, struct timeval *timeValue, const char *fieldName)
1352 /* Attempt to get the date value from the buffer */
1353 if (get_date_value (buffer, offset, timeValue) == 0)
1355 /* If successful, add it to the protocol tree */
1356 proto_tree_add_time (tree, header, headerBuffer, headerOffset,
1357 headerLen, timeValue);
1361 fprintf (stderr, "dissect_wsp: Invalid %s value\n", fieldName);
1366 add_parameter (proto_tree *tree, tvbuff_t *tvb, guint offset)
1368 guint octet = tvb_get_guint8 (tvb, offset);
1369 if (octet & 0x80) /* Short integer */
1372 octet = octet & 0x7F;
1376 offset = add_parameter_charset (tree, tvb, offset, offset-1);
1380 fprintf (stderr, "dissect-wsp: add_parameter octet=0x%02x\n", octet);
1385 fprintf (stderr, "dissect-wsp: add_parameter octet=0x%02x\n", octet);
1392 add_parameter_charset (proto_tree *tree, tvbuff_t *tvb, guint offset, guint startOffset)
1394 guint octet = tvb_get_guint8 (tvb, offset);
1398 proto_tree_add_item (tree, hf_wsp_parameter_well_known_charset, tvb, startOffset+1, octet, bo_big_endian);
1400 else if (octet & 0x80)
1403 proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset, tvb, startOffset, offset-startOffset, (octet & 0x7F));
1410 add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType)
1413 guint variableStart = 0;
1414 guint variableEnd = 0;
1415 guint valueStart = 0;
1420 /* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,END_OF_FRAME,bo_little_endian); */
1421 ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,tvb_reported_length(tvb),bo_little_endian);
1423 if (contentType == 0x12) /* URL Encoded data */
1425 /* Iterate through post data */
1426 for (offset = 0; offset < tvb_reported_length (tvb); offset++)
1428 peek = tvb_get_guint8 (tvb, offset);
1431 variableEnd = offset;
1432 valueStart = offset+1;
1434 else if (peek == '&')
1436 if (variableEnd > 0)
1438 add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
1440 variableStart = offset+1;
1447 /* See if there's outstanding data */
1448 if (variableEnd > 0)
1450 add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
1456 add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
1458 int variableLength = variableEnd-variableStart;
1459 int valueLength = 0;
1460 char *variableBuffer;
1463 variableBuffer = g_malloc (variableLength+1);
1464 strncpy (variableBuffer, tvb_get_ptr (tvb, variableStart, variableLength), variableLength);
1465 variableBuffer[variableLength] = 0;
1467 if (valueEnd < valueStart)
1469 valueBuffer = g_malloc (1);
1471 valueEnd = valueStart;
1475 valueLength = valueEnd-valueStart;
1476 valueBuffer = g_malloc (valueLength+1);
1477 strncpy (valueBuffer, tvb_get_ptr (tvb, valueStart, valueLength), valueLength);
1478 valueBuffer[valueLength] = 0;
1481 /* Check for variables with no value */
1482 if (valueStart >= tvb_reported_length (tvb))
1484 valueStart = tvb_reported_length (tvb);
1485 valueEnd = valueStart;
1487 valueLength = valueEnd-valueStart;
1489 proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
1491 g_free (variableBuffer);
1492 g_free (valueBuffer);
1495 /* Register the protocol with Ethereal */
1497 proto_register_wsp(void)
1500 /* Setup list of header fields */
1501 static hf_register_info hf[] = {
1502 { &hf_wsp_header_tid,
1503 { "Transmission ID",
1505 FT_UINT8, BASE_HEX, NULL, 0x00,
1509 { &hf_wsp_header_pdu_type,
1512 FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
1516 { &hf_wsp_version_major,
1517 { "Version (Major)",
1518 "wsp.version.major",
1519 FT_UINT8, BASE_DEC, NULL, 0xF0,
1523 { &hf_wsp_version_minor,
1524 { "Version (Minor)",
1525 "wsp.version.minor",
1526 FT_UINT8, BASE_DEC, NULL, 0x0F,
1530 { &hf_wsp_capability_length,
1531 { "Capability Length",
1532 "wsp.capability.length",
1533 FT_UINT32, BASE_DEC, NULL, 0x00,
1537 { &hf_wsp_header_length,
1539 "wsp.headers_length",
1540 FT_UINT32, BASE_DEC, NULL, 0x00,
1544 { &hf_wsp_capabilities_section,
1547 FT_NONE, BASE_DEC, NULL, 0x00,
1551 { &hf_wsp_headers_section,
1554 FT_NONE, BASE_DEC, NULL, 0x00,
1560 "wsp.headers.header",
1561 FT_NONE, BASE_DEC, NULL, 0x00,
1565 { &hf_wsp_header_uri_len,
1568 FT_UINT32, BASE_DEC, NULL, 0x00,
1572 { &hf_wsp_header_uri,
1575 FT_STRING, BASE_NONE, NULL, 0x00,
1579 { &hf_wsp_server_session_id,
1580 { "Server Session ID",
1581 "wsp.server.session_id",
1582 FT_UINT32, BASE_DEC, NULL, 0x00,
1586 { &hf_wsp_header_status,
1589 FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
1593 { &hf_wsp_content_type,
1595 "wsp.content_type.type",
1596 FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
1600 { &hf_wsp_parameter_well_known_charset,
1602 "wsp.content_type.parameter.charset",
1603 FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
1607 { &hf_wsp_reply_data,
1610 FT_NONE, BASE_NONE, NULL, 0x00,
1614 { &hf_wsp_header_accept,
1616 "wsp.header.accept",
1617 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
1618 FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
1622 { &hf_wsp_header_accept_str,
1624 "wsp.header.accept.string",
1625 FT_STRING, BASE_NONE, NULL, 0x00,
1629 { &hf_wsp_header_accept_charset,
1631 "wsp.header.accept_charset",
1632 FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
1636 { &hf_wsp_header_accept_charset_str,
1638 "wsp.header.accept_charset.string",
1639 FT_STRING, BASE_NONE, NULL, 0x00,
1643 { &hf_wsp_header_accept_language,
1644 { "Accept-Language",
1645 "wsp.header.accept_language",
1646 FT_UINT8, BASE_HEX, VALS ( vals_languages ), 0x00,
1650 { &hf_wsp_header_accept_language_str,
1651 { "Accept-Language",
1652 "wsp.header.accept_language.string",
1653 FT_STRING, BASE_NONE, NULL, 0x00,
1657 { &hf_wsp_header_accept_ranges,
1659 "wsp.header.accept_ranges",
1660 FT_UINT8, BASE_HEX, VALS ( vals_accept_ranges ), 0x00,
1664 { &hf_wsp_header_age,
1667 FT_UINT32, BASE_DEC, NULL, 0x00,
1671 { &hf_wsp_header_cache_control,
1673 "wsp.header.cache_control",
1674 FT_UINT8, BASE_HEX, VALS ( vals_cache_control ), 0x00,
1678 { &hf_wsp_header_content_length,
1680 "wsp.header.content_length",
1681 FT_UINT32, BASE_DEC, NULL, 0x00,
1685 { &hf_wsp_header_date,
1688 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1692 { &hf_wsp_header_etag,
1695 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
1696 FT_STRING, BASE_NONE, NULL, 0x00,
1700 { &hf_wsp_header_expires,
1702 "wsp.header.expires",
1703 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1707 { &hf_wsp_header_last_modified,
1709 "wsp.header.last_modified",
1710 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1714 { &hf_wsp_header_location,
1716 "wsp.header.location",
1717 FT_STRING, BASE_NONE, NULL, 0x00,
1721 { &hf_wsp_header_if_modified_since,
1722 { "If-Modified-Since",
1723 "wsp.header.if_modified_since",
1724 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1728 { &hf_wsp_header_server,
1730 "wsp.header.server",
1731 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
1732 FT_STRING, BASE_NONE, NULL, 0x00,
1736 { &hf_wsp_header_transfer_encoding,
1737 { "Transfer Encoding",
1738 "wsp.header.transfer_enc",
1739 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
1740 FT_UINT8, BASE_HEX, VALS ( vals_transfer_encoding ), 0x00,
1744 { &hf_wsp_header_transfer_encoding_str,
1745 { "Transfer Encoding",
1746 "wsp.header.transfer_enc_str",
1747 FT_STRING, BASE_NONE, NULL, 0x00,
1751 { &hf_wsp_header_user_agent,
1753 "wsp.header.user_agent",
1754 /*FT_NONE, BASE_DEC, NULL, 0x00,*/
1755 FT_STRING, BASE_NONE, NULL, 0x00,
1759 { &hf_wsp_header_via,
1762 FT_STRING, BASE_NONE, NULL, 0x00,
1766 { &hf_wsp_header_application_header,
1767 { "Application Header",
1768 "wsp.header.application_header",
1769 FT_STRING, BASE_NONE, NULL, 0x00,
1770 "Application Header"
1773 { &hf_wsp_header_application_value,
1774 { "Application Header Value",
1775 "wsp.header.application_header.value",
1776 FT_STRING, BASE_NONE, NULL, 0x00,
1777 "Application Header Value"
1780 { &hf_wsp_header_x_wap_tod,
1782 "wsp.header.x_wap_tod",
1783 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
1787 { &hf_wsp_post_data,
1790 FT_NONE, BASE_NONE, NULL, 0x00,
1796 /* Setup protocol subtree array */
1797 static gint *ett[] = {
1805 /* Register the protocol name and description */
1806 proto_wsp = proto_register_protocol(
1807 "Wireless Session Protocol", /* protocol name for use by ethereal */
1808 "WSP", /* short version of name */
1809 "wap-wsp" /* Abbreviated protocol name, should Match IANA
1810 < URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
1814 /* Required function calls to register the header fields and subtrees used */
1815 proto_register_field_array(proto_wsp, hf, array_length(hf));
1816 proto_register_subtree_array(ett, array_length(ett));
1818 register_dissector("wsp", dissect_wsp, proto_wsp);
1822 proto_reg_handoff_wsp(void)
1825 * Get a handle for the WMLC dissector
1827 wmlc_handle = find_dissector("wmlc"); /* Coming soon :) */
1829 /* Only connection-less WSP has no previous handler */
1830 dissector_add("udp.port", UDP_PORT_WSP, dissect_wsp, proto_wsp);
1832 /* This dissector is also called from the WTP and WTLS dissectors */