![Guy Harris](/assets/img/avatar_default.png)
rather than extracting a string and adding that explicitly (which runs the risk of leaking memory if the "tvb_get_ptr()" throws an exception). Use "tvb_format_text()" when adding the string to the Info column, so that non-printable characters are displayed as escapes. svn path=/trunk/; revision=5283
4947 lines
140 KiB
C
4947 lines
140 KiB
C
/* packet-wsp.c
|
|
*
|
|
* Routines to dissect WSP component of WAP traffic.
|
|
*
|
|
* $Id: packet-wsp.c,v 1.56 2002/04/29 00:33:30 guy Exp $
|
|
*
|
|
* Ethereal - Network traffic analyzer
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* WAP dissector based on original work by Ben Fowler
|
|
* Updated by Neil Hunter <neil.hunter@energis-squared.com>
|
|
* WTLS support by Alexandre P. Ferreira (Splice IP)
|
|
* Openwave header support by Dermot Bradley <dermot.bradley@openwave.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
# include <sys/types.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
# include <netinet/in.h>
|
|
#endif
|
|
|
|
#ifdef NEED_SNPRINTF_H
|
|
# ifdef HAVE_STDARG_H
|
|
# include <stdarg.h>
|
|
# else
|
|
# include <varargs.h>
|
|
# endif
|
|
# include "snprintf.h"
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <glib.h>
|
|
#include <epan/packet.h>
|
|
#include <epan/ipv6-utils.h>
|
|
#include <epan/conversation.h>
|
|
#include "packet-wap.h"
|
|
#include "packet-wsp.h"
|
|
|
|
/* File scoped variables for the protocol and registered fields */
|
|
static int proto_wsp = HF_EMPTY;
|
|
|
|
/* These fields used by fixed part of header */
|
|
static int hf_wsp_header_tid = HF_EMPTY;
|
|
static int hf_wsp_header_pdu_type = HF_EMPTY;
|
|
static int hf_wsp_version_major = HF_EMPTY;
|
|
static int hf_wsp_version_minor = HF_EMPTY;
|
|
static int hf_wsp_capability_length = HF_EMPTY;
|
|
static int hf_wsp_capabilities_section = HF_EMPTY;
|
|
static int hf_wsp_capabilities_client_SDU = HF_EMPTY;
|
|
static int hf_wsp_capabilities_server_SDU = HF_EMPTY;
|
|
static int hf_wsp_capabilities_protocol_opt = HF_EMPTY;
|
|
static int hf_wsp_capabilities_method_MOR = HF_EMPTY;
|
|
static int hf_wsp_capabilities_push_MOR = HF_EMPTY;
|
|
static int hf_wsp_capabilities_extended_methods = HF_EMPTY;
|
|
static int hf_wsp_capabilities_header_code_pages = HF_EMPTY;
|
|
static int hf_wsp_capabilities_aliases = HF_EMPTY;
|
|
static int hf_wsp_header_uri_len = HF_EMPTY;
|
|
static int hf_wsp_header_uri = HF_EMPTY;
|
|
static int hf_wsp_server_session_id = HF_EMPTY;
|
|
static int hf_wsp_header_status = HF_EMPTY;
|
|
static int hf_wsp_header_length = HF_EMPTY;
|
|
static int hf_wsp_headers_section = HF_EMPTY;
|
|
static int hf_wsp_header = HF_EMPTY;
|
|
static int hf_wsp_content_type = HF_EMPTY;
|
|
static int hf_wsp_content_type_str = HF_EMPTY;
|
|
static int hf_wsp_parameter_well_known_charset = HF_EMPTY;
|
|
static int hf_wsp_parameter_type = HF_EMPTY;
|
|
static int hf_wsp_parameter_name = HF_EMPTY;
|
|
static int hf_wsp_parameter_filename = HF_EMPTY;
|
|
static int hf_wsp_parameter_start = HF_EMPTY;
|
|
static int hf_wsp_parameter_start_info = HF_EMPTY;
|
|
static int hf_wsp_parameter_comment = HF_EMPTY;
|
|
static int hf_wsp_parameter_domain = HF_EMPTY;
|
|
static int hf_wsp_parameter_path = HF_EMPTY;
|
|
static int hf_wsp_parameter_upart_type = HF_EMPTY;
|
|
static int hf_wsp_parameter_upart_type_value = HF_EMPTY;
|
|
static int hf_wsp_reply_data = HF_EMPTY;
|
|
static int hf_wsp_post_data = HF_EMPTY;
|
|
static int hf_wsp_push_data = HF_EMPTY;
|
|
static int hf_wsp_multipart_data = HF_EMPTY;
|
|
static int hf_wsp_mpart = HF_EMPTY;
|
|
|
|
static int hf_wsp_header_shift_code = HF_EMPTY;
|
|
static int hf_wsp_header_accept = HF_EMPTY;
|
|
static int hf_wsp_header_accept_str = HF_EMPTY;
|
|
static int hf_wsp_header_accept_application = HF_EMPTY;
|
|
static int hf_wsp_header_accept_application_str = HF_EMPTY;
|
|
static int hf_wsp_header_accept_charset = HF_EMPTY;
|
|
static int hf_wsp_header_accept_charset_str = HF_EMPTY;
|
|
static int hf_wsp_header_accept_language = HF_EMPTY;
|
|
static int hf_wsp_header_accept_language_str = HF_EMPTY;
|
|
static int hf_wsp_header_accept_ranges = HF_EMPTY;
|
|
static int hf_wsp_header_accept_ranges_str = HF_EMPTY;
|
|
static int hf_wsp_header_cache_control = HF_EMPTY;
|
|
static int hf_wsp_header_cache_control_str = HF_EMPTY;
|
|
static int hf_wsp_header_cache_control_field_name = HF_EMPTY;
|
|
static int hf_wsp_header_connection = HF_EMPTY;
|
|
static int hf_wsp_header_connection_str = HF_EMPTY;
|
|
static int hf_wsp_header_cache_control_field_name_str = HF_EMPTY;
|
|
static int hf_wsp_header_content_length = HF_EMPTY;
|
|
static int hf_wsp_header_age = HF_EMPTY;
|
|
static int hf_wsp_header_bearer_indication = HF_EMPTY;
|
|
static int hf_wsp_header_date = HF_EMPTY;
|
|
static int hf_wsp_header_etag = HF_EMPTY;
|
|
static int hf_wsp_header_expires = HF_EMPTY;
|
|
static int hf_wsp_header_last_modified = HF_EMPTY;
|
|
static int hf_wsp_header_location = HF_EMPTY;
|
|
static int hf_wsp_header_if_modified_since = HF_EMPTY;
|
|
static int hf_wsp_header_profile = HF_EMPTY;
|
|
static int hf_wsp_header_pragma = HF_EMPTY;
|
|
static int hf_wsp_header_server = HF_EMPTY;
|
|
static int hf_wsp_header_user_agent = HF_EMPTY;
|
|
static int hf_wsp_header_warning = HF_EMPTY;
|
|
static int hf_wsp_header_warning_code = HF_EMPTY;
|
|
static int hf_wsp_header_warning_agent = HF_EMPTY;
|
|
static int hf_wsp_header_warning_text = HF_EMPTY;
|
|
static int hf_wsp_header_application_header = HF_EMPTY;
|
|
static int hf_wsp_header_application_value = HF_EMPTY;
|
|
static int hf_wsp_header_x_wap_tod = HF_EMPTY;
|
|
static int hf_wsp_header_content_ID = HF_EMPTY;
|
|
static int hf_wsp_header_transfer_encoding = HF_EMPTY;
|
|
static int hf_wsp_header_transfer_encoding_str = HF_EMPTY;
|
|
static int hf_wsp_header_via = HF_EMPTY;
|
|
static int hf_wsp_header_wap_application_id = HF_EMPTY;
|
|
static int hf_wsp_header_wap_application_id_str = HF_EMPTY;
|
|
|
|
|
|
/* Openwave-specific WSP headers */
|
|
static int hf_wsp_header_openwave_proxy_push_addr = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_push_accept = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_push_seq = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_notify = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_operator_domain = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_home_page = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_has_color = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_num_softkeys = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_softkey_size = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_screen_chars = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_screen_pixels = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_em_size = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_screen_depth = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_immed_alert = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_net_ask = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_uplink_version = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_tod = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_ba_enable = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_ba_realm = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_redirect_enable = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_request_uri = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_redirect_status = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_trans_charset = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_trans_charset_str = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_linger = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_client_id = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_enable_trust = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_trust_old = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_trust = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_proxy_bookmark = HF_EMPTY;
|
|
static int hf_wsp_header_openwave_devcap_gui = HF_EMPTY;
|
|
|
|
|
|
static int hf_wsp_redirect_flags = HF_EMPTY;
|
|
static int hf_wsp_redirect_permanent = HF_EMPTY;
|
|
static int hf_wsp_redirect_reuse_security_session = HF_EMPTY;
|
|
static int hf_wsp_redirect_afl = HF_EMPTY;
|
|
static int hf_wsp_redirect_afl_bearer_type_included = HF_EMPTY;
|
|
static int hf_wsp_redirect_afl_port_number_included = HF_EMPTY;
|
|
static int hf_wsp_redirect_afl_address_len = HF_EMPTY;
|
|
static int hf_wsp_redirect_bearer_type = HF_EMPTY;
|
|
static int hf_wsp_redirect_port_num = HF_EMPTY;
|
|
static int hf_wsp_redirect_ipv4_addr = HF_EMPTY;
|
|
static int hf_wsp_redirect_ipv6_addr = HF_EMPTY;
|
|
static int hf_wsp_redirect_addr = HF_EMPTY;
|
|
|
|
/* Initialize the subtree pointers */
|
|
static gint ett_wsp = ETT_EMPTY;
|
|
static gint ett_content_type_parameters = ETT_EMPTY;
|
|
static gint ett_header = ETT_EMPTY;
|
|
static gint ett_headers = ETT_EMPTY;
|
|
static gint ett_header_warning = ETT_EMPTY;
|
|
static gint ett_header_cache_control_parameters = ETT_EMPTY;
|
|
static gint ett_header_cache_control_field_names = ETT_EMPTY;
|
|
static gint ett_capabilities = ETT_EMPTY;
|
|
static gint ett_content_type = ETT_EMPTY;
|
|
static gint ett_redirect_flags = ETT_EMPTY;
|
|
static gint ett_redirect_afl = ETT_EMPTY;
|
|
static gint ett_multiparts = ETT_EMPTY;
|
|
static gint ett_mpartlist = ETT_EMPTY;
|
|
|
|
/* Handle for WSP-over-UDP dissector */
|
|
static dissector_handle_t wsp_fromudp_handle;
|
|
|
|
/* Handle for WTP-over-UDP dissector */
|
|
static dissector_handle_t wtp_fromudp_handle;
|
|
|
|
/* Handle for WMLC dissector */
|
|
static dissector_handle_t wmlc_handle;
|
|
|
|
static const value_string vals_pdu_type[] = {
|
|
{ 0x00, "Reserved" },
|
|
{ 0x01, "Connect" },
|
|
{ 0x02, "ConnectReply" },
|
|
{ 0x03, "Redirect" },
|
|
{ 0x04, "Reply" },
|
|
{ 0x05, "Disconnect" },
|
|
{ 0x06, "Push" },
|
|
{ 0x07, "ConfirmedPush" },
|
|
{ 0x08, "Suspend" },
|
|
{ 0x09, "Resume" },
|
|
|
|
/* 0x10 - 0x3F Unassigned */
|
|
|
|
{ 0x40, "Get" },
|
|
{ 0x41, "Options" },
|
|
{ 0x42, "Head" },
|
|
{ 0x43, "Delete" },
|
|
{ 0x44, "Trace" },
|
|
|
|
/* 0x45 - 0x4F Unassigned (Get PDU) */
|
|
/* 0x50 - 0x5F Extended method (Get PDU) */
|
|
|
|
{ 0x60, "Post" },
|
|
{ 0x61, "Put" },
|
|
|
|
/* 0x62 - 0x6F Unassigned (Post PDU) */
|
|
/* 0x70 - 0x7F Extended method (Post PDU) */
|
|
/* 0x80 - 0xFF Reserved */
|
|
|
|
{ 0x00, NULL }
|
|
|
|
};
|
|
|
|
static const value_string vals_status[] = {
|
|
/* 0x00 - 0x0F Reserved */
|
|
|
|
{ 0x10, "Continue" },
|
|
{ 0x11, "Switching Protocols" },
|
|
|
|
{ 0x20, "OK" },
|
|
{ 0x21, "Created" },
|
|
{ 0x22, "Accepted" },
|
|
{ 0x23, "Non-Authoritative Information" },
|
|
{ 0x24, "No Content" },
|
|
{ 0x25, "Reset Content" },
|
|
{ 0x26, "Partial Content" },
|
|
|
|
{ 0x30, "Multiple Choices" },
|
|
{ 0x31, "Moved Permanently" },
|
|
{ 0x32, "Moved Temporarily" },
|
|
{ 0x33, "See Other" },
|
|
{ 0x34, "Not Modified" },
|
|
{ 0x35, "Use Proxy" },
|
|
{ 0x37, "Temporary Redirect" },
|
|
|
|
{ 0x40, "Bad Request" },
|
|
{ 0x41, "Unauthorised" },
|
|
{ 0x42, "Payment Required" },
|
|
{ 0x43, "Forbidden" },
|
|
{ 0x44, "Not Found" },
|
|
{ 0x45, "Method Not Allowed" },
|
|
{ 0x46, "Not Acceptable" },
|
|
{ 0x47, "Proxy Authentication Required" },
|
|
{ 0x48, "Request Timeout" },
|
|
{ 0x49, "Conflict" },
|
|
{ 0x4A, "Gone" },
|
|
{ 0x4B, "Length Required" },
|
|
{ 0x4C, "Precondition Failed" },
|
|
{ 0x4D, "Request Entity Too Large" },
|
|
{ 0x4E, "Request-URI Too Large" },
|
|
{ 0x4F, "Unsupported Media Type" },
|
|
{ 0x50, "Requested Range Not Satisfiable" },
|
|
{ 0x51, "Expectation Failed" },
|
|
|
|
{ 0x60, "Internal Server Error" },
|
|
{ 0x61, "Not Implemented" },
|
|
{ 0x62, "Bad Gateway" },
|
|
{ 0x63, "Service Unavailable" },
|
|
{ 0x64, "Gateway Timeout" },
|
|
{ 0x65, "HTTP Version Not Supported" },
|
|
{ 0x00, NULL }
|
|
};
|
|
|
|
/*
|
|
* Field names.
|
|
*/
|
|
#define FN_ACCEPT 0x00
|
|
#define FN_ACCEPT_CHARSET_DEP 0x01 /* encoding version 1.1, deprecated */
|
|
#define FN_ACCEPT_ENCODING_DEP 0x02 /* encoding version 1.1, deprecated */
|
|
#define FN_ACCEPT_LANGUAGE 0x03
|
|
#define FN_ACCEPT_RANGES 0x04
|
|
#define FN_AGE 0x05
|
|
#define FN_ALLOW 0x06
|
|
#define FN_AUTHORIZATION 0x07
|
|
#define FN_CACHE_CONTROL_DEP 0x08 /* encoding version 1.1, deprecated */
|
|
#define FN_CONNECTION 0x09
|
|
#define FN_CONTENT_BASE 0x0A
|
|
#define FN_CONTENT_ENCODING 0x0B
|
|
#define FN_CONTENT_LANGUAGE 0x0C
|
|
#define FN_CONTENT_LENGTH 0x0D
|
|
#define FN_CONTENT_LOCATION 0x0E
|
|
#define FN_CONTENT_MD5 0x0F
|
|
#define FN_CONTENT_RANGE_DEP 0x10 /* encoding version 1.1, deprecated */
|
|
#define FN_CONTENT_TYPE 0x11
|
|
#define FN_DATE 0x12
|
|
#define FN_ETAG 0x13
|
|
#define FN_EXPIRES 0x14
|
|
#define FN_FROM 0x15
|
|
#define FN_HOST 0x16
|
|
#define FN_IF_MODIFIED_SINCE 0x17
|
|
#define FN_IF_MATCH 0x18
|
|
#define FN_IF_NONE_MATCH 0x19
|
|
#define FN_IF_RANGE 0x1A
|
|
#define FN_IF_UNMODIFIED_SINCE 0x1B
|
|
#define FN_LOCATION 0x1C
|
|
#define FN_LAST_MODIFIED 0x1D
|
|
#define FN_MAX_FORWARDS 0x1E
|
|
#define FN_PRAGMA 0x1F
|
|
#define FN_PROXY_AUTHENTICATE 0x20
|
|
#define FN_PROXY_AUTHORIZATION 0x21
|
|
#define FN_PUBLIC 0x22
|
|
#define FN_RANGE 0x23
|
|
#define FN_REFERER 0x24
|
|
#define FN_RETRY_AFTER 0x25
|
|
#define FN_SERVER 0x26
|
|
#define FN_TRANSFER_ENCODING 0x27
|
|
#define FN_UPGRADE 0x28
|
|
#define FN_USER_AGENT 0x29
|
|
#define FN_VARY 0x2A
|
|
#define FN_VIA 0x2B
|
|
#define FN_WARNING 0x2C
|
|
#define FN_WWW_AUTHENTICATE 0x2D
|
|
#define FN_CONTENT_DISPOSITION 0x2E
|
|
#define FN_X_WAP_APPLICATION_ID 0x2F
|
|
#define FN_X_WAP_CONTENT_URI 0x30
|
|
#define FN_X_WAP_INITIATOR_URI 0x31
|
|
#define FN_ACCEPT_APPLICATION 0x32
|
|
#define FN_BEARER_INDICATION 0x33
|
|
#define FN_PUSH_FLAG 0x34
|
|
#define FN_PROFILE 0x35
|
|
#define FN_PROFILE_DIFF 0x36
|
|
#define FN_PROFILE_WARNING 0x37
|
|
#define FN_EXPECT 0x38
|
|
#define FN_TE 0x39
|
|
#define FN_TRAILER 0x3A
|
|
#define FN_ACCEPT_CHARSET 0x3B /* encoding version 1.3 */
|
|
#define FN_ACCEPT_ENCODING 0x3C /* encoding version 1.3 */
|
|
#define FN_CACHE_CONTROL 0x3D /* encoding version 1.3 */
|
|
#define FN_CONTENT_RANGE 0x3E /* encoding version 1.3 */
|
|
#define FN_X_WAP_TOD 0x3F
|
|
#define FN_CONTENT_ID 0x40
|
|
#define FN_SET_COOKIE 0x41
|
|
#define FN_COOKIE 0x42
|
|
#define FN_ENCODING_VERSION 0x43
|
|
#define FN_PROFILE_WARNING14 0x44 /* encoding version 1.4 */
|
|
#define FN_CONTENT_DISPOSITION14 0x45 /* encoding version 1.4 */
|
|
#define FN_X_WAP_SECURITY 0x46
|
|
#define FN_CACHE_CONTROL14 0x47 /* encoding version 1.4 */
|
|
|
|
|
|
/*
|
|
* Openwave field names.
|
|
*/
|
|
#define FN_OPENWAVE_PROXY_PUSH_ADDR 0x00
|
|
#define FN_OPENWAVE_PROXY_PUSH_ACCEPT 0x01
|
|
#define FN_OPENWAVE_PROXY_PUSH_SEQ 0x02
|
|
#define FN_OPENWAVE_PROXY_NOTIFY 0x03
|
|
#define FN_OPENWAVE_PROXY_OPERATOR_DOMAIN 0x04
|
|
#define FN_OPENWAVE_PROXY_HOME_PAGE 0x05
|
|
#define FN_OPENWAVE_DEVCAP_HAS_COLOR 0x06
|
|
#define FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS 0x07
|
|
#define FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE 0x08
|
|
#define FN_OPENWAVE_DEVCAP_SCREEN_CHARS 0x09
|
|
#define FN_OPENWAVE_DEVCAP_SCREEN_PIXELS 0x0A
|
|
#define FN_OPENWAVE_DEVCAP_EM_SIZE 0x0B
|
|
#define FN_OPENWAVE_DEVCAP_SCREEN_DEPTH 0x0C
|
|
#define FN_OPENWAVE_DEVCAP_IMMED_ALERT 0x0D
|
|
#define FN_OPENWAVE_PROXY_NET_ASK 0x0E
|
|
#define FN_OPENWAVE_PROXY_UPLINK_VERSION 0x0F
|
|
#define FN_OPENWAVE_PROXY_TOD 0x10
|
|
#define FN_OPENWAVE_PROXY_BA_ENABLE 0x11
|
|
#define FN_OPENWAVE_PROXY_BA_REALM 0x12
|
|
#define FN_OPENWAVE_PROXY_REDIRECT_ENABLE 0x13
|
|
#define FN_OPENWAVE_PROXY_REQUEST_URI 0x14
|
|
#define FN_OPENWAVE_PROXY_REDIRECT_STATUS 0x15
|
|
#define FN_OPENWAVE_PROXY_TRANS_CHARSET 0x16
|
|
#define FN_OPENWAVE_PROXY_LINGER 0x17
|
|
#define FN_OPENWAVE_PROXY_CLIENT_ID 0x18
|
|
#define FN_OPENWAVE_PROXY_ENABLE_TRUST 0x19
|
|
#define FN_OPENWAVE_PROXY_TRUST_OLD 0x1A
|
|
#define FN_OPENWAVE_PROXY_TRUST 0x20
|
|
#define FN_OPENWAVE_PROXY_BOOKMARK 0x21
|
|
#define FN_OPENWAVE_DEVCAP_GUI 0x22
|
|
|
|
static const value_string vals_openwave_field_names[] = {
|
|
{ FN_OPENWAVE_PROXY_PUSH_ADDR, "x-up-proxy-push-addr" },
|
|
{ FN_OPENWAVE_PROXY_PUSH_ACCEPT, "x-up-proxy-push-accept" },
|
|
{ FN_OPENWAVE_PROXY_PUSH_SEQ, "x-up-proxy-seq" },
|
|
{ FN_OPENWAVE_PROXY_NOTIFY, "x-up-proxy-notify" },
|
|
{ FN_OPENWAVE_PROXY_OPERATOR_DOMAIN, "x-up-proxy-operator-domain" },
|
|
{ FN_OPENWAVE_PROXY_HOME_PAGE, "x-up-proxy-home-page" },
|
|
{ FN_OPENWAVE_DEVCAP_HAS_COLOR, "x-up-devcap-has-color" },
|
|
{ FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS, "x-up-devcap-num-softkeys" },
|
|
{ FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE, "x-up-devcap-softkey-size" },
|
|
{ FN_OPENWAVE_DEVCAP_SCREEN_CHARS, "x-up-devcap-screen-chars" },
|
|
{ FN_OPENWAVE_DEVCAP_SCREEN_PIXELS, "x-up-devcap-screen-pixels" },
|
|
{ FN_OPENWAVE_DEVCAP_EM_SIZE, "x-up-devcap-em-size" },
|
|
{ FN_OPENWAVE_DEVCAP_SCREEN_DEPTH, "x-up-devcap-screen-depth" },
|
|
{ FN_OPENWAVE_DEVCAP_IMMED_ALERT, "x-up-devcap-immed-alert" },
|
|
{ FN_OPENWAVE_PROXY_NET_ASK, "x-up-proxy-net-ask" },
|
|
{ FN_OPENWAVE_PROXY_UPLINK_VERSION, "x-up-proxy-uplink-version" },
|
|
{ FN_OPENWAVE_PROXY_TOD, "x-up-proxy-tod" },
|
|
{ FN_OPENWAVE_PROXY_BA_ENABLE, "x-up-proxy-ba-enable" },
|
|
{ FN_OPENWAVE_PROXY_BA_REALM, "x-up-proxy-ba-realm" },
|
|
{ FN_OPENWAVE_PROXY_REDIRECT_ENABLE, "x-up-proxy-redirect-enable" },
|
|
{ FN_OPENWAVE_PROXY_REQUEST_URI, "x-up-proxy-request-uri" },
|
|
{ FN_OPENWAVE_PROXY_REDIRECT_STATUS, "x-up-proxy-redirect-status" },
|
|
{ FN_OPENWAVE_PROXY_TRANS_CHARSET, "x-up-proxy-trans-charset" },
|
|
{ FN_OPENWAVE_PROXY_LINGER, "x-up-proxy-linger" },
|
|
{ FN_OPENWAVE_PROXY_CLIENT_ID, "x-up-proxy-client-id" },
|
|
{ FN_OPENWAVE_PROXY_ENABLE_TRUST, "x-up-proxy-enable-trust" },
|
|
{ FN_OPENWAVE_PROXY_TRUST_OLD, "x-up-proxy-trust-old" },
|
|
{ FN_OPENWAVE_PROXY_TRUST, "x-up-proxy-trust" },
|
|
{ FN_OPENWAVE_PROXY_BOOKMARK, "x-up-proxy-bookmark" },
|
|
{ FN_OPENWAVE_DEVCAP_GUI, "x-up-devcap-gui" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
|
|
static const value_string vals_field_names[] = {
|
|
{ FN_ACCEPT, "Accept" },
|
|
{ FN_ACCEPT_CHARSET_DEP, "Accept-Charset (encoding 1.1)" },
|
|
{ FN_ACCEPT_ENCODING_DEP, "Accept-Encoding (encoding 1.1)" },
|
|
{ FN_ACCEPT_LANGUAGE, "Accept-Language" },
|
|
{ FN_ACCEPT_RANGES, "Accept-Ranges" },
|
|
{ FN_AGE, "Age" },
|
|
{ FN_ALLOW, "Allow" },
|
|
{ FN_AUTHORIZATION, "Authorization" },
|
|
{ FN_CACHE_CONTROL_DEP, "Cache-Control (encoding 1.1)" },
|
|
{ FN_CONNECTION, "Connection" },
|
|
{ FN_CONTENT_BASE, "Content-Base" },
|
|
{ FN_CONTENT_ENCODING, "Content-Encoding" },
|
|
{ FN_CONTENT_LANGUAGE, "Content-Language" },
|
|
{ FN_CONTENT_LENGTH, "Content-Length" },
|
|
{ FN_CONTENT_LOCATION, "Content-Location" },
|
|
{ FN_CONTENT_MD5, "Content-MD5" },
|
|
{ FN_CONTENT_RANGE_DEP, "Content-Range (encoding 1.1)" },
|
|
{ FN_CONTENT_TYPE, "Content-Type" },
|
|
{ FN_DATE, "Date" },
|
|
{ FN_ETAG, "Etag" },
|
|
{ FN_EXPIRES, "Expires" },
|
|
{ FN_FROM, "From" },
|
|
{ FN_HOST, "Host" },
|
|
{ FN_IF_MODIFIED_SINCE, "If-Modified-Since" },
|
|
{ FN_IF_MATCH, "If-Match" },
|
|
{ FN_IF_NONE_MATCH, "If-None-Match" },
|
|
{ FN_IF_RANGE, "If-Range" },
|
|
{ FN_IF_UNMODIFIED_SINCE, "If-Unmodified-Since" },
|
|
{ FN_LOCATION, "Location" },
|
|
{ FN_LAST_MODIFIED, "Last-Modified" },
|
|
{ FN_MAX_FORWARDS, "Max-Forwards" },
|
|
{ FN_PRAGMA, "Pragma" },
|
|
{ FN_PROXY_AUTHENTICATE, "Proxy-Authenticate" },
|
|
{ FN_PROXY_AUTHORIZATION, "Proxy-Authorization" },
|
|
{ FN_PUBLIC, "Public" },
|
|
{ FN_RANGE, "Range" },
|
|
{ FN_REFERER, "Referer" },
|
|
{ FN_RETRY_AFTER, "Retry-After" },
|
|
{ FN_SERVER, "Server" },
|
|
{ FN_TRANSFER_ENCODING, "Transfer-Encoding" },
|
|
{ FN_UPGRADE, "Upgrade" },
|
|
{ FN_USER_AGENT, "User-Agent" },
|
|
{ FN_VARY, "Vary" },
|
|
{ FN_VIA, "Via" },
|
|
{ FN_WARNING, "Warning" },
|
|
{ FN_WWW_AUTHENTICATE, "WWW-Authenticate" },
|
|
{ FN_CONTENT_DISPOSITION, "Content-Disposition" },
|
|
{ FN_X_WAP_APPLICATION_ID, "X-Wap-Application-ID" },
|
|
{ FN_X_WAP_CONTENT_URI, "X-Wap-Content-URI" },
|
|
{ FN_X_WAP_INITIATOR_URI, "X-Wap-Initiator-URI" },
|
|
{ FN_ACCEPT_APPLICATION, "Accept-Application" },
|
|
{ FN_BEARER_INDICATION, "Bearer-Indication" },
|
|
{ FN_PUSH_FLAG, "Push-Flag" },
|
|
{ FN_PROFILE, "Profile" },
|
|
{ FN_PROFILE_DIFF, "Profile-Diff" },
|
|
{ FN_PROFILE_WARNING, "Profile-Warning" },
|
|
{ FN_EXPECT, "Expect" },
|
|
{ FN_TE, "TE" },
|
|
{ FN_TRAILER, "Trailer" },
|
|
{ FN_ACCEPT_CHARSET, "Accept-Charset" },
|
|
{ FN_ACCEPT_ENCODING, "Accept-Encoding" },
|
|
{ FN_CACHE_CONTROL, "Cache-Control" },
|
|
{ FN_CONTENT_RANGE, "Content-Range" },
|
|
{ FN_X_WAP_TOD, "X-Wap-Tod" },
|
|
{ FN_CONTENT_ID, "Content-ID" },
|
|
{ FN_SET_COOKIE, "Set-Cookie" },
|
|
{ FN_COOKIE, "Cookie" },
|
|
{ FN_ENCODING_VERSION, "Encoding-Version" },
|
|
{ FN_PROFILE_WARNING14, "Profile-Warning (encoding 1.4)" },
|
|
{ FN_CONTENT_DISPOSITION14,"Content-Disposition (encoding 1.4)" },
|
|
{ FN_X_WAP_SECURITY, "X-WAP-Security" },
|
|
{ FN_CACHE_CONTROL14, "Cache-Control (encoding 1.4)" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/*
|
|
* Bearer types (from the WDP specification).
|
|
*/
|
|
#define BT_IPv4 0x00
|
|
#define BT_IPv6 0x01
|
|
#define BT_GSM_USSD 0x02
|
|
#define BT_GSM_SMS 0x03
|
|
#define BT_ANSI_136_GUTS 0x04
|
|
#define BT_IS_95_SMS 0x05
|
|
#define BT_IS_95_CSD 0x06
|
|
#define BT_IS_95_PACKET_DATA 0x07
|
|
#define BT_ANSI_136_CSD 0x08
|
|
#define BT_ANSI_136_PACKET_DATA 0x09
|
|
#define BT_GSM_CSD 0x0A
|
|
#define BT_GSM_GPRS 0x0B
|
|
#define BT_GSM_USSD_IPv4 0x0C
|
|
#define BT_AMPS_CDPD 0x0D
|
|
#define BT_PDC_CSD 0x0E
|
|
#define BT_PDC_PACKET_DATA 0x0F
|
|
#define BT_IDEN_SMS 0x10
|
|
#define BT_IDEN_CSD 0x11
|
|
#define BT_IDEN_PACKET_DATA 0x12
|
|
#define BT_PAGING_FLEX 0x13
|
|
#define BT_PHS_SMS 0x14
|
|
#define BT_PHS_CSD 0x15
|
|
#define BT_GSM_USSD_GSM_SC 0x16
|
|
#define BT_TETRA_SDS_ITSI 0x17
|
|
#define BT_TETRA_SDS_MSISDN 0x18
|
|
#define BT_TETRA_PACKET_DATA 0x19
|
|
#define BT_PAGING_REFLEX 0x1A
|
|
#define BT_GSM_USSD_MSISDN 0x1B
|
|
#define BT_MOBITEX_MPAK 0x1C
|
|
#define BT_ANSI_136_GHOST 0x1D
|
|
|
|
static const value_string vals_bearer_types[] = {
|
|
{ BT_IPv4, "IPv4" },
|
|
{ BT_IPv6, "IPv6" },
|
|
{ BT_GSM_USSD, "GSM USSD" },
|
|
{ BT_GSM_SMS, "GSM SMS" },
|
|
{ BT_ANSI_136_GUTS, "ANSI-136 GUTS/R-Data" },
|
|
{ BT_IS_95_SMS, "IS-95 CDMA SMS" },
|
|
{ BT_IS_95_CSD, "IS-95 CDMA CSD" },
|
|
{ BT_IS_95_PACKET_DATA, "IS-95 CDMA Packet data" },
|
|
{ BT_ANSI_136_CSD, "ANSI-136 CSD" },
|
|
{ BT_ANSI_136_PACKET_DATA, "ANSI-136 Packet data" },
|
|
{ BT_GSM_CSD, "GSM CSD" },
|
|
{ BT_GSM_GPRS, "GSM GPRS" },
|
|
{ BT_GSM_USSD_IPv4, "GSM USSD (IPv4 addresses)" },
|
|
{ BT_AMPS_CDPD, "AMPS CDPD" },
|
|
{ BT_PDC_CSD, "PDC CSD" },
|
|
{ BT_PDC_PACKET_DATA, "PDC Packet data" },
|
|
{ BT_IDEN_SMS, "IDEN SMS" },
|
|
{ BT_IDEN_CSD, "IDEN CSD" },
|
|
{ BT_IDEN_PACKET_DATA, "IDEN Packet data" },
|
|
{ BT_PAGING_FLEX, "Paging network FLEX(TM)" },
|
|
{ BT_PHS_SMS, "PHS SMS" },
|
|
{ BT_PHS_CSD, "PHS CSD" },
|
|
{ BT_GSM_USSD_GSM_SC, "GSM USSD (GSM Service Code addresses)" },
|
|
{ BT_TETRA_SDS_ITSI, "TETRA SDS (ITSI addresses)" },
|
|
{ BT_TETRA_SDS_MSISDN, "TETRA SDS (MSISDN addresses)" },
|
|
{ BT_TETRA_PACKET_DATA, "TETRA Packet data" },
|
|
{ BT_PAGING_REFLEX, "Paging network ReFLEX(TM)" },
|
|
{ BT_GSM_USSD_MSISDN, "GSM USSD (MSISDN addresses)" },
|
|
{ BT_MOBITEX_MPAK, "Mobitex MPAK" },
|
|
{ BT_ANSI_136_GHOST, "ANSI-136 GHOST/R-Data" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string vals_content_types[] = {
|
|
{ 0x00, "*/*" },
|
|
{ 0x01, "text/*" },
|
|
{ 0x02, "text/html" },
|
|
{ 0x03, "text/plain" },
|
|
{ 0x04, "text/x-hdml" },
|
|
{ 0x05, "text/x-ttml" },
|
|
{ 0x06, "text/x-vCalendar" },
|
|
{ 0x07, "text/x-vCard" },
|
|
{ 0x08, "text/vnd.wap.wml" },
|
|
{ 0x09, "text/vnd.wap.wmlscript" },
|
|
{ 0x0A, "text/vnd.wap.channel" },
|
|
{ 0x0B, "Multipart/*" },
|
|
{ 0x0C, "Multipart/mixed" },
|
|
{ 0x0D, "Multipart/form-data" },
|
|
{ 0x0E, "Multipart/byteranges" },
|
|
{ 0x0F, "Multipart/alternative" },
|
|
{ 0x10, "application/*" },
|
|
{ 0x11, "application/java-vm" },
|
|
{ 0x12, "application/x-www-form-urlencoded" },
|
|
{ 0x13, "application/x-hdmlc" },
|
|
{ 0x14, "application/vnd.wap.wmlc" },
|
|
{ 0x15, "application/vnd.wap.wmlscriptc" },
|
|
{ 0x16, "application/vnd.wap.channelc" },
|
|
{ 0x17, "application/vnd.wap.uaprof" },
|
|
{ 0x18, "application/vnd.wap.wtls-ca-certificate" },
|
|
{ 0x19, "application/vnd.wap.wtls-user-certificate" },
|
|
{ 0x1A, "application/x-x509-ca-cert" },
|
|
{ 0x1B, "application/x-x509-user-cert" },
|
|
{ 0x1C, "image/*" },
|
|
{ 0x1D, "image/gif" },
|
|
{ 0x1E, "image/jpeg" },
|
|
{ 0x1F, "image/tiff" },
|
|
{ 0x20, "image/png" },
|
|
{ 0x21, "image/vnd.wap.wbmp" },
|
|
{ 0x22, "application/vnd.wap.multipart.*" },
|
|
{ 0x23, "application/vnd.wap.multipart.mixed" },
|
|
{ 0x24, "application/vnd.wap.multipart.form-data" },
|
|
{ 0x25, "application/vnd.wap.multipart.byteranges" },
|
|
{ 0x26, "application/vnd.wap.multipart.alternative" },
|
|
{ 0x27, "application/xml" },
|
|
{ 0x28, "text/xml" },
|
|
{ 0x29, "application/vnd.wap.wbxml" },
|
|
{ 0x2A, "application/x-x968-cross-cert" },
|
|
{ 0x2B, "application/x-x968-ca-cert" },
|
|
{ 0x2C, "application/x-x968-user-cert" },
|
|
{ 0x2D, "text/vnd.wap.si" },
|
|
{ 0x2E, "application/vnd.wap.sic" },
|
|
{ 0x2F, "text/vnd.wap.sl" },
|
|
{ 0x30, "application/vnd.wap.slc" },
|
|
{ 0x31, "text/vnd.wap.co" },
|
|
{ 0x32, "application/vnd.wap.coc" },
|
|
{ 0x33, "application/vnd.wap.multipart.related" },
|
|
{ 0x34, "application/vnd.wap.sia" },
|
|
{ 0x35, "text/vnd.wap.connectivity-xml" },
|
|
{ 0x36, "application/vnd.wap.connectivity-wbxml" },
|
|
{ 0x37, "application/pkcs7-mime" },
|
|
{ 0x38, "application/vnd.wap.hashed-certificate" },
|
|
{ 0x39, "application/vnd.wap.signed-certificate" },
|
|
{ 0x3A, "application/vnd.wap.cert-response" },
|
|
{ 0x3B, "application/xhtml+xml" },
|
|
{ 0x3C, "application/wml+xml" },
|
|
{ 0x3D, "text/css" },
|
|
{ 0x3E, "application/vnd.wap.mms-message" },
|
|
{ 0x3F, "application/vnd.wap.rollover-certificate" },
|
|
{ 0x201, "application/vnd.uplanet.cachop-wbxml" },
|
|
{ 0x202, "application/vnd.uplanet.signal" },
|
|
{ 0x203, "application/vnd.uplanet.alert-wbxml" },
|
|
{ 0x204, "application/vnd.uplanet.list-wbxml" },
|
|
{ 0x205, "application/vnd.uplanet.listcmd-wbxml" },
|
|
{ 0x206, "application/vnd.uplanet.channel-wbxml" },
|
|
{ 0x207, "application/vnd.uplanet.provisioning-status-uri" },
|
|
{ 0x208, "x-wap.multipart/vnd.uplanet.header-set" },
|
|
{ 0x209, "application/vnd.uplanet.bearer-choice-wbxml" },
|
|
{ 0x20A, "application/vnd.phonecom.mmc-wbxml" },
|
|
{ 0x20B, "application/vnd.nokia.syncset+wbxml" },
|
|
{ 0x00, NULL }
|
|
};
|
|
|
|
static const value_string vals_languages[] = {
|
|
{ 0x01, "Afar (aa)" },
|
|
{ 0x02, "Abkhazian (ab)" },
|
|
{ 0x03, "Afrikaans (af)" },
|
|
{ 0x04, "Amharic (am)" },
|
|
{ 0x05, "Arabic (ar)" },
|
|
{ 0x06, "Assamese (as)" },
|
|
{ 0x07, "Aymara (ay)" },
|
|
{ 0x08, "Azerbaijani (az)" },
|
|
{ 0x09, "Bashkir (ba)" },
|
|
{ 0x0A, "Byelorussian (be)" },
|
|
{ 0x0B, "Bulgarian (bg)" },
|
|
{ 0x0C, "Bihari (bh)" },
|
|
{ 0x0D, "Bislama (bi)" },
|
|
{ 0x0E, "Bengali; Bangla (bn)" },
|
|
{ 0x0F, "Tibetan (bo)" },
|
|
{ 0x10, "Breton (br)" },
|
|
{ 0x11, "Catalan (ca)" },
|
|
{ 0x12, "Corsican (co)" },
|
|
{ 0x13, "Czech (cs)" },
|
|
{ 0x14, "Welsh (cy)" },
|
|
{ 0x15, "Danish (da)" },
|
|
{ 0x16, "German (de)" },
|
|
{ 0x17, "Bhutani (dz)" },
|
|
{ 0x18, "Greek (el)" },
|
|
{ 0x19, "English (en)" },
|
|
{ 0x1A, "Esperanto (eo)" },
|
|
{ 0x1B, "Spanish (es)" },
|
|
{ 0x1C, "Estonian (et)" },
|
|
{ 0x1D, "Basque (eu)" },
|
|
{ 0x1E, "Persian (fa)" },
|
|
{ 0x1F, "Finnish (fi)" },
|
|
{ 0x20, "Fiji (fj)" },
|
|
{ 0x21, "Urdu (ur)" },
|
|
{ 0x22, "French (fr)" },
|
|
{ 0x23, "Uzbek (uz)" },
|
|
{ 0x24, "Irish (ga)" },
|
|
{ 0x25, "Scots Gaelic (gd)" },
|
|
{ 0x26, "Galician (gl)" },
|
|
{ 0x27, "Guarani (gn)" },
|
|
{ 0x28, "Gujarati (gu)" },
|
|
{ 0x29, "Hausa (ha)" },
|
|
{ 0x2A, "Hebrew (formerly iw) (he)" },
|
|
{ 0x2B, "Hindi (hi)" },
|
|
{ 0x2C, "Croatian (hr)" },
|
|
{ 0x2D, "Hungarian (hu)" },
|
|
{ 0x2E, "Armenian (hy)" },
|
|
{ 0x2F, "Vietnamese (vi)" },
|
|
{ 0x30, "Indonesian (formerly in) (id)" },
|
|
{ 0x31, "Wolof (wo)" },
|
|
{ 0x32, "Xhosa (xh)" },
|
|
{ 0x33, "Icelandic (is)" },
|
|
{ 0x34, "Italian (it)" },
|
|
{ 0x35, "Yoruba (yo)" },
|
|
{ 0x36, "Japanese (ja)" },
|
|
{ 0x37, "Javanese (jw)" },
|
|
{ 0x38, "Georgian (ka)" },
|
|
{ 0x39, "Kazakh (kk)" },
|
|
{ 0x3A, "Zhuang (za)" },
|
|
{ 0x3B, "Cambodian (km)" },
|
|
{ 0x3C, "Kannada (kn)" },
|
|
{ 0x3D, "Korean (ko)" },
|
|
{ 0x3E, "Kashmiri (ks)" },
|
|
{ 0x3F, "Kurdish (ku)" },
|
|
{ 0x40, "Kirghiz (ky)" },
|
|
{ 0x41, "Chinese (zh)" },
|
|
{ 0x42, "Lingala (ln)" },
|
|
{ 0x43, "Laothian (lo)" },
|
|
{ 0x44, "Lithuanian (lt)" },
|
|
{ 0x45, "Latvian, Lettish (lv)" },
|
|
{ 0x46, "Malagasy (mg)" },
|
|
{ 0x47, "Maori (mi)" },
|
|
{ 0x48, "Macedonian (mk)" },
|
|
{ 0x49, "Malayalam (ml)" },
|
|
{ 0x4A, "Mongolian (mn)" },
|
|
{ 0x4B, "Moldavian (mo)" },
|
|
{ 0x4C, "Marathi (mr)" },
|
|
{ 0x4D, "Malay (ms)" },
|
|
{ 0x4E, "Maltese (mt)" },
|
|
{ 0x4F, "Burmese (my)" },
|
|
{ 0x50, "Ukrainian (uk)" },
|
|
{ 0x51, "Nepali (ne)" },
|
|
{ 0x52, "Dutch (nl)" },
|
|
{ 0x53, "Norwegian (no)" },
|
|
{ 0x54, "Occitan (oc)" },
|
|
{ 0x55, "(Afan) Oromo (om)" },
|
|
{ 0x56, "Oriya (or)" },
|
|
{ 0x57, "Punjabi (pa)" },
|
|
{ 0x58, "Polish (po)" },
|
|
{ 0x59, "Pashto, Pushto (ps)" },
|
|
{ 0x5A, "Portuguese (pt)" },
|
|
{ 0x5B, "Quechua (qu)" },
|
|
{ 0x5C, "Zulu (zu)" },
|
|
{ 0x5D, "Kirundi (rn)" },
|
|
{ 0x5E, "Romanian (ro)" },
|
|
{ 0x5F, "Russian (ru)" },
|
|
{ 0x60, "Kinyarwanda (rw)" },
|
|
{ 0x61, "Sanskrit (sa)" },
|
|
{ 0x62, "Sindhi (sd)" },
|
|
{ 0x63, "Sangho (sg)" },
|
|
{ 0x64, "Serbo-Croatian (sh)" },
|
|
{ 0x65, "Sinhalese (si)" },
|
|
{ 0x66, "Slovak (sk)" },
|
|
{ 0x67, "Slovenian (sl)" },
|
|
{ 0x68, "Samoan (sm)" },
|
|
{ 0x69, "Shona (sn)" },
|
|
{ 0x6A, "Somali (so)" },
|
|
{ 0x6B, "Albanian (sq)" },
|
|
{ 0x6C, "Serbian (sr)" },
|
|
{ 0x6D, "Siswati (ss)" },
|
|
{ 0x6E, "Sesotho (st)" },
|
|
{ 0x6F, "Sundanese (su)" },
|
|
{ 0x70, "Swedish (sv)" },
|
|
{ 0x71, "Swahili (sw)" },
|
|
{ 0x72, "Tamil (ta)" },
|
|
{ 0x73, "Telugu (te)" },
|
|
{ 0x74, "Tajik (tg)" },
|
|
{ 0x75, "Thai (th)" },
|
|
{ 0x76, "Tigrinya (ti)" },
|
|
{ 0x77, "Turkmen (tk)" },
|
|
{ 0x78, "Tagalog (tl)" },
|
|
{ 0x79, "Setswana (tn)" },
|
|
{ 0x7A, "Tonga (to)" },
|
|
{ 0x7B, "Turkish (tr)" },
|
|
{ 0x7C, "Tsonga (ts)" },
|
|
{ 0x7D, "Tatar (tt)" },
|
|
{ 0x7E, "Twi (tw)" },
|
|
{ 0x7F, "Uighur (ug)" },
|
|
{ 0x81, "Nauru (na)" },
|
|
{ 0x82, "Faeroese (fo)" },
|
|
{ 0x83, "Frisian (fy)" },
|
|
{ 0x84, "Interlingua (ia)" },
|
|
{ 0x85, "Volapuk (vo)" },
|
|
{ 0x86, "Interlingue (ie)" },
|
|
{ 0x87, "Inupiak (ik)" },
|
|
{ 0x88, "Yiddish (formerly ji) (yi)" },
|
|
{ 0x89, "Inuktitut (iu)" },
|
|
{ 0x8A, "Greenlandic (kl)" },
|
|
{ 0x8B, "Latin (la)" },
|
|
{ 0x8C, "Rhaeto-Romance (rm)" },
|
|
{ 0x00, NULL }
|
|
};
|
|
|
|
static const value_string vals_accept_ranges[] = {
|
|
{ 0x00, "None" },
|
|
{ 0x01, "Bytes" },
|
|
{ 0x00, NULL }
|
|
};
|
|
|
|
#define NO_CACHE 0x00
|
|
#define NO_STORE 0x01
|
|
#define MAX_AGE 0x02
|
|
#define MAX_STALE 0x03
|
|
#define MIN_FRESH 0x04
|
|
#define ONLY_IF_CACHED 0x05
|
|
#define PUBLIC 0x06
|
|
#define PRIVATE 0x07
|
|
#define NO_TRANSFORM 0x08
|
|
#define MUST_REVALIDATE 0x09
|
|
#define PROXY_REVALIDATE 0x0A
|
|
#define S_MAXAGE 0x0B
|
|
|
|
static const value_string vals_cache_control[] = {
|
|
{ NO_CACHE, "No-cache" },
|
|
{ NO_STORE, "No-store" },
|
|
{ MAX_AGE, "Max-age" },
|
|
{ MAX_STALE, "Max-stale" },
|
|
{ MIN_FRESH, "Min-fresh" },
|
|
{ ONLY_IF_CACHED, "Only-if-cached" },
|
|
{ PUBLIC, "Public" },
|
|
{ PRIVATE, "Private" },
|
|
{ NO_TRANSFORM, "No-transform" },
|
|
{ MUST_REVALIDATE, "Must-revalidate" },
|
|
{ PROXY_REVALIDATE, "Proxy-revalidate" },
|
|
{ S_MAXAGE, "S-max-age" },
|
|
{ 0x00, NULL }
|
|
};
|
|
|
|
static const value_string vals_connection[] = {
|
|
{ 0x00, "Close" },
|
|
{ 0x00, NULL }
|
|
};
|
|
|
|
static const value_string vals_transfer_encoding[] = {
|
|
{ 0x00, "Chunked" },
|
|
{ 0x00, NULL }
|
|
};
|
|
|
|
/*
|
|
* Redirect flags.
|
|
*/
|
|
#define PERMANENT_REDIRECT 0x80
|
|
#define REUSE_SECURITY_SESSION 0x40
|
|
|
|
/*
|
|
* Redirect address flags and length.
|
|
*/
|
|
#define BEARER_TYPE_INCLUDED 0x80
|
|
#define PORT_NUMBER_INCLUDED 0x40
|
|
#define ADDRESS_LEN 0x3f
|
|
|
|
static const true_false_string yes_no_truth = {
|
|
"Yes" ,
|
|
"No"
|
|
};
|
|
|
|
/*
|
|
* Windows appears to define DELETE.
|
|
*/
|
|
#ifdef DELETE
|
|
#undef DELETE
|
|
#endif
|
|
|
|
enum {
|
|
RESERVED = 0x00,
|
|
CONNECT = 0x01,
|
|
CONNECTREPLY = 0x02,
|
|
REDIRECT = 0x03, /* No sample data */
|
|
REPLY = 0x04,
|
|
DISCONNECT = 0x05,
|
|
PUSH = 0x06, /* No sample data */
|
|
CONFIRMEDPUSH = 0x07, /* No sample data */
|
|
SUSPEND = 0x08, /* No sample data */
|
|
RESUME = 0x09, /* No sample data */
|
|
|
|
GET = 0x40,
|
|
OPTIONS = 0x41, /* No sample data */
|
|
HEAD = 0x42, /* No sample data */
|
|
DELETE = 0x43, /* No sample data */
|
|
TRACE = 0x44, /* No sample data */
|
|
|
|
POST = 0x60,
|
|
PUT = 0x61, /* No sample data */
|
|
};
|
|
|
|
typedef enum {
|
|
VALUE_LEN_SUPPLIED,
|
|
VALUE_IS_TEXT_STRING,
|
|
VALUE_IN_LEN,
|
|
} value_type_t;
|
|
|
|
static dissector_table_t wsp_dissector_table;
|
|
static heur_dissector_list_t heur_subdissector_list;
|
|
|
|
static void add_uri (proto_tree *, packet_info *, tvbuff_t *, guint, guint);
|
|
static void add_headers (proto_tree *, tvbuff_t *);
|
|
static int add_well_known_header (proto_tree *, tvbuff_t *, int, guint8);
|
|
static int add_unknown_header (proto_tree *, tvbuff_t *, int, guint8);
|
|
static int add_application_header (proto_tree *, tvbuff_t *, int);
|
|
static void add_accept_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int);
|
|
static void add_accept_xxx_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, int, const value_string *,
|
|
const char *);
|
|
static void add_accept_ranges_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int);
|
|
static void add_cache_control_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int);
|
|
static int add_cache_control_field_name (proto_tree *, tvbuff_t *, int, guint);
|
|
static void add_connection_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int);
|
|
static void add_content_type_value (proto_tree *, tvbuff_t *, int, int,
|
|
tvbuff_t *, value_type_t, int, int, int, guint *, const char **);
|
|
static void add_wap_application_id_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int);
|
|
static void add_integer_value_header_common (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8, const value_string *);
|
|
static void add_integer_value_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8);
|
|
static void add_string_value_header_common (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8, const value_string *);
|
|
static void add_string_value_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8);
|
|
static void add_quoted_string_value_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8);
|
|
static void add_date_value_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8);
|
|
static int add_parameter (proto_tree *, tvbuff_t *, int);
|
|
static int add_untyped_parameter (proto_tree *, tvbuff_t *, int, int);
|
|
static int add_parameter_charset (proto_tree *, tvbuff_t *, int, int);
|
|
static int add_constrained_encoding (proto_tree *, tvbuff_t *, int, int);
|
|
static int add_parameter_type (proto_tree *, tvbuff_t *, int, int);
|
|
static int add_parameter_text (proto_tree *, tvbuff_t *, int, int, int, const char *);
|
|
static void add_post_data (proto_tree *, tvbuff_t *, guint, const char *);
|
|
static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
|
|
static void add_pragma_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
|
|
value_type_t, int);
|
|
static void add_transfer_encoding_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int);
|
|
static void add_warning_header (proto_tree *, tvbuff_t *, int, tvbuff_t *,
|
|
value_type_t, int);
|
|
static void add_accept_application_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int);
|
|
static void add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type);
|
|
static void add_capability_vals(tvbuff_t *, gboolean, int, guint, guint, char *, size_t);
|
|
static value_type_t get_value_type_len (tvbuff_t *, int, guint *, int *, int *);
|
|
static guint get_uintvar (tvbuff_t *, guint, guint);
|
|
static gint get_integer (tvbuff_t *, guint, guint, value_type_t, guint *);
|
|
|
|
static int add_well_known_openwave_header (proto_tree *, tvbuff_t *, int, guint8);
|
|
static void add_openwave_integer_value_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8);
|
|
static void add_openwave_string_value_header (proto_tree *, tvbuff_t *, int,
|
|
tvbuff_t *, value_type_t, int, int, guint8);
|
|
|
|
|
|
/* Code to actually dissect the packets */
|
|
static void
|
|
dissect_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|
proto_tree *tree, dissector_handle_t dissector_handle)
|
|
{
|
|
guint8 flags;
|
|
proto_item *ti;
|
|
proto_tree *flags_tree;
|
|
guint8 bearer_type;
|
|
guint8 address_flags_len;
|
|
int address_len;
|
|
proto_tree *atf_tree;
|
|
guint16 port_num;
|
|
guint32 address_ipv4;
|
|
struct e_in6_addr address_ipv6;
|
|
address redir_address;
|
|
conversation_t *conv;
|
|
|
|
flags = tvb_get_guint8 (tvb, offset);
|
|
if (tree) {
|
|
ti = proto_tree_add_uint (tree, hf_wsp_redirect_flags,
|
|
tvb, offset, 1, flags);
|
|
flags_tree = proto_item_add_subtree (ti, ett_redirect_flags);
|
|
proto_tree_add_boolean (flags_tree, hf_wsp_redirect_permanent,
|
|
tvb, offset, 1, flags);
|
|
proto_tree_add_boolean (flags_tree, hf_wsp_redirect_reuse_security_session,
|
|
tvb, offset, 1, flags);
|
|
}
|
|
offset++;
|
|
while (tvb_reported_length_remaining (tvb, offset) > 0) {
|
|
address_flags_len = tvb_get_guint8 (tvb, offset);
|
|
if (tree) {
|
|
ti = proto_tree_add_uint (tree, hf_wsp_redirect_afl,
|
|
tvb, offset, 1, address_flags_len);
|
|
atf_tree = proto_item_add_subtree (ti, ett_redirect_afl);
|
|
proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_bearer_type_included,
|
|
tvb, offset, 1, address_flags_len);
|
|
proto_tree_add_boolean (atf_tree, hf_wsp_redirect_afl_port_number_included,
|
|
tvb, offset, 1, address_flags_len);
|
|
proto_tree_add_uint (atf_tree, hf_wsp_redirect_afl_address_len,
|
|
tvb, offset, 1, address_flags_len);
|
|
}
|
|
offset++;
|
|
if (address_flags_len & BEARER_TYPE_INCLUDED) {
|
|
bearer_type = tvb_get_guint8 (tvb, offset);
|
|
if (tree) {
|
|
proto_tree_add_uint (tree, hf_wsp_redirect_bearer_type,
|
|
tvb, offset, 1, bearer_type);
|
|
}
|
|
offset++;
|
|
} else
|
|
bearer_type = 0x00; /* XXX */
|
|
if (address_flags_len & PORT_NUMBER_INCLUDED) {
|
|
port_num = tvb_get_ntohs (tvb, offset);
|
|
if (tree) {
|
|
proto_tree_add_uint (tree, hf_wsp_redirect_port_num,
|
|
tvb, offset, 2, port_num);
|
|
}
|
|
offset += 2;
|
|
} else {
|
|
/*
|
|
* Redirecting to the same server port number as was
|
|
* being used, i.e. the source port number of this
|
|
* redirect.
|
|
*/
|
|
port_num = pinfo->srcport;
|
|
}
|
|
address_len = address_flags_len & ADDRESS_LEN;
|
|
if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
|
|
/*
|
|
* We don't have the bearer type in the message,
|
|
* so we don't know the address type.
|
|
* (It's the same bearer type as the original
|
|
* connection.)
|
|
*/
|
|
goto unknown_address_type;
|
|
}
|
|
|
|
/*
|
|
* We know the bearer type, so we know the address type.
|
|
*/
|
|
switch (bearer_type) {
|
|
|
|
case BT_IPv4:
|
|
case BT_IS_95_CSD:
|
|
case BT_IS_95_PACKET_DATA:
|
|
case BT_ANSI_136_CSD:
|
|
case BT_ANSI_136_PACKET_DATA:
|
|
case BT_GSM_CSD:
|
|
case BT_GSM_GPRS:
|
|
case BT_GSM_USSD_IPv4:
|
|
case BT_AMPS_CDPD:
|
|
case BT_PDC_CSD:
|
|
case BT_PDC_PACKET_DATA:
|
|
case BT_IDEN_CSD:
|
|
case BT_IDEN_PACKET_DATA:
|
|
case BT_PHS_CSD:
|
|
case BT_TETRA_PACKET_DATA:
|
|
/*
|
|
* IPv4.
|
|
*/
|
|
if (address_len != 4) {
|
|
/*
|
|
* Say what?
|
|
*/
|
|
goto unknown_address_type;
|
|
}
|
|
tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
|
|
if (tree) {
|
|
proto_tree_add_ipv4 (tree,
|
|
hf_wsp_redirect_ipv4_addr,
|
|
tvb, offset, 4, address_ipv4);
|
|
}
|
|
|
|
/*
|
|
* Create a conversation so that the
|
|
* redirected session will be dissected
|
|
* as WAP.
|
|
*/
|
|
redir_address.type = AT_IPv4;
|
|
redir_address.len = 4;
|
|
redir_address.data = (const guint8 *)&address_ipv4;
|
|
conv = find_conversation(&redir_address, &pinfo->dst,
|
|
PT_UDP, port_num, 0, NO_PORT_B);
|
|
if (conv == NULL) {
|
|
conv = conversation_new(&redir_address,
|
|
&pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
|
|
}
|
|
conversation_set_dissector(conv, dissector_handle);
|
|
break;
|
|
|
|
case BT_IPv6:
|
|
/*
|
|
* IPv6.
|
|
*/
|
|
if (address_len != 16) {
|
|
/*
|
|
* Say what?
|
|
*/
|
|
goto unknown_address_type;
|
|
}
|
|
tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
|
|
if (tree) {
|
|
proto_tree_add_ipv6 (tree,
|
|
hf_wsp_redirect_ipv6_addr,
|
|
tvb, offset, 16, (guint8 *)&address_ipv6);
|
|
}
|
|
|
|
/*
|
|
* Create a conversation so that the
|
|
* redirected session will be dissected
|
|
* as WAP.
|
|
*/
|
|
redir_address.type = AT_IPv6;
|
|
redir_address.len = 16;
|
|
redir_address.data = (const guint8 *)&address_ipv4;
|
|
conv = find_conversation(&redir_address, &pinfo->dst,
|
|
PT_UDP, port_num, 0, NO_PORT_B);
|
|
if (conv == NULL) {
|
|
conv = conversation_new(&redir_address,
|
|
&pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
|
|
}
|
|
conversation_set_dissector(conv, dissector_handle);
|
|
break;
|
|
|
|
unknown_address_type:
|
|
default:
|
|
if (address_len != 0) {
|
|
if (tree) {
|
|
proto_tree_add_item (tree,
|
|
hf_wsp_redirect_addr,
|
|
tvb, offset, address_len,
|
|
bo_little_endian);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
offset += address_len;
|
|
}
|
|
}
|
|
|
|
static void
|
|
dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|
dissector_handle_t dissector_handle, gboolean is_connectionless)
|
|
{
|
|
int offset = 0;
|
|
|
|
guint8 pdut;
|
|
guint count = 0;
|
|
guint value = 0;
|
|
guint uriLength = 0;
|
|
guint uriStart = 0;
|
|
guint capabilityLength = 0;
|
|
guint capabilityStart = 0;
|
|
guint headersLength = 0;
|
|
guint headerLength = 0;
|
|
guint headerStart = 0;
|
|
guint nextOffset = 0;
|
|
guint contentTypeStart = 0;
|
|
guint contentType = 0;
|
|
const char *contentTypeStr;
|
|
tvbuff_t *tmp_tvb;
|
|
|
|
/* Set up structures we will need to add the protocol subtree and manage it */
|
|
proto_item *ti;
|
|
proto_tree *wsp_tree = NULL;
|
|
/* proto_tree *wsp_header_fixed; */
|
|
|
|
/* This field shows up as the "Info" column in the display; you should make
|
|
it, if possible, summarize what's in the packet, so that a user looking
|
|
at the list of packets can tell what type of packet it is. */
|
|
|
|
/* Connection-less mode has a TID first */
|
|
if (is_connectionless)
|
|
{
|
|
offset++;
|
|
};
|
|
|
|
/* Find the PDU type */
|
|
pdut = tvb_get_guint8 (tvb, offset);
|
|
|
|
/* Develop the string to put in the Info column */
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, "WSP %s",
|
|
val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"));
|
|
};
|
|
|
|
/* In the interest of speed, if "tree" is NULL, don't do any work not
|
|
necessary to generate protocol tree items. */
|
|
if (tree) {
|
|
ti = proto_tree_add_item(tree, proto_wsp, tvb, 0, -1,
|
|
bo_little_endian);
|
|
wsp_tree = proto_item_add_subtree(ti, ett_wsp);
|
|
|
|
/* Code to process the packet goes here */
|
|
/*
|
|
wsp_header_fixed = proto_item_add_subtree(ti, ett_header );
|
|
*/
|
|
|
|
/* Add common items: only TID and PDU Type */
|
|
|
|
/* If this is connectionless, then the TID Field is always first */
|
|
if (is_connectionless)
|
|
{
|
|
ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,tvb,
|
|
0,1,bo_little_endian);
|
|
}
|
|
|
|
ti = proto_tree_add_item(
|
|
wsp_tree, /* tree */
|
|
hf_wsp_header_pdu_type, /* id */
|
|
tvb,
|
|
offset, /* start of high light */
|
|
1, /* length of high light */
|
|
bo_little_endian /* value */
|
|
);
|
|
}
|
|
offset++;
|
|
|
|
switch (pdut)
|
|
{
|
|
case CONNECT:
|
|
case CONNECTREPLY:
|
|
case RESUME:
|
|
if (tree) {
|
|
if (pdut == CONNECT)
|
|
{
|
|
ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,tvb,offset,1,bo_little_endian);
|
|
ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,tvb,offset,1,bo_little_endian);
|
|
offset++;
|
|
} else {
|
|
count = 0; /* Initialise count */
|
|
value = tvb_get_guintvar (tvb, offset, &count);
|
|
ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
|
|
offset += count;
|
|
}
|
|
capabilityStart = offset;
|
|
count = 0; /* Initialise count */
|
|
capabilityLength = tvb_get_guintvar (tvb, offset, &count);
|
|
offset += count;
|
|
ti = proto_tree_add_uint (wsp_tree, hf_wsp_capability_length,tvb,capabilityStart,count,capabilityLength);
|
|
|
|
if (pdut != RESUME)
|
|
{
|
|
count = 0; /* Initialise count */
|
|
headerLength = tvb_get_guintvar (tvb, offset, &count);
|
|
ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headerLength);
|
|
offset += count;
|
|
capabilityStart = offset;
|
|
headerStart = capabilityStart + capabilityLength;
|
|
} else {
|
|
/* Resume computes the headerlength by remaining bytes */
|
|
capabilityStart = offset;
|
|
headerStart = capabilityStart + capabilityLength;
|
|
headerLength = tvb_reported_length_remaining (tvb, headerStart);
|
|
}
|
|
if (capabilityLength > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, offset, capabilityLength, capabilityLength);
|
|
add_capabilities (wsp_tree, tmp_tvb, pdut);
|
|
offset += capabilityLength;
|
|
}
|
|
|
|
if (headerLength > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, offset, headerLength, headerLength);
|
|
add_headers (wsp_tree, tmp_tvb);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case REDIRECT:
|
|
dissect_redirect(tvb, offset, pinfo, wsp_tree,
|
|
dissector_handle);
|
|
break;
|
|
|
|
case DISCONNECT:
|
|
case SUSPEND:
|
|
if (tree) {
|
|
count = 0; /* Initialise count */
|
|
value = tvb_get_guintvar (tvb, offset, &count);
|
|
ti = proto_tree_add_uint (wsp_tree, hf_wsp_server_session_id,tvb,offset,count,value);
|
|
}
|
|
break;
|
|
|
|
case GET:
|
|
count = 0; /* Initialise count */
|
|
/* Length of URI and size of URILen field */
|
|
value = tvb_get_guintvar (tvb, offset, &count);
|
|
nextOffset = offset + count;
|
|
add_uri (wsp_tree, pinfo, tvb, offset, nextOffset);
|
|
if (tree) {
|
|
offset += (value+count); /* VERIFY */
|
|
tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
|
|
add_headers (wsp_tree, tmp_tvb);
|
|
}
|
|
break;
|
|
|
|
case POST:
|
|
uriStart = offset;
|
|
count = 0; /* Initialise count */
|
|
uriLength = tvb_get_guintvar (tvb, offset, &count);
|
|
headerStart = uriStart+count;
|
|
count = 0; /* Initialise count */
|
|
headersLength = tvb_get_guintvar (tvb, headerStart, &count);
|
|
offset = headerStart + count;
|
|
|
|
add_uri (wsp_tree, pinfo, tvb, uriStart, offset);
|
|
if (tree) {
|
|
offset += uriLength;
|
|
|
|
ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,headerStart,count,headersLength);
|
|
|
|
if (headersLength == 0)
|
|
break;
|
|
|
|
contentTypeStart = offset;
|
|
nextOffset = add_content_type (wsp_tree,
|
|
tvb, offset, &contentType,
|
|
&contentTypeStr);
|
|
|
|
/* Add headers subtree that will hold the headers fields */
|
|
/* Runs from nextOffset for headersLength-(length of content-type field)*/
|
|
headerLength = headersLength-(nextOffset-contentTypeStart);
|
|
if (headerLength > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
|
|
add_headers (wsp_tree, tmp_tvb);
|
|
}
|
|
|
|
/* TODO: Post DATA */
|
|
/* Runs from start of headers+headerLength to end of frame */
|
|
offset = nextOffset+headerLength;
|
|
tmp_tvb = tvb_new_subset (tvb, offset, tvb_reported_length (tvb)-offset, tvb_reported_length (tvb)-offset);
|
|
add_post_data (wsp_tree, tmp_tvb,
|
|
contentType, contentTypeStr);
|
|
}
|
|
if (tvb_reported_length_remaining(tvb, headerStart + count + uriLength + headersLength) > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, headerStart + count + uriLength + headersLength, -1, -1);
|
|
if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
|
|
dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
|
|
}
|
|
break;
|
|
|
|
case REPLY:
|
|
count = 0; /* Initialise count */
|
|
headersLength = tvb_get_guintvar (tvb, offset+1, &count);
|
|
headerStart = offset + count + 1;
|
|
if (tree) {
|
|
ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
|
|
nextOffset = offset + 1 + count;
|
|
ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset+1,count,headersLength);
|
|
|
|
if (headersLength == 0)
|
|
break;
|
|
|
|
contentTypeStart = nextOffset;
|
|
nextOffset = add_content_type (wsp_tree,
|
|
tvb, nextOffset, &contentType,
|
|
&contentTypeStr);
|
|
|
|
/* Add headers subtree that will hold the headers fields */
|
|
/* Runs from nextOffset for headersLength-(length of content-type field)*/
|
|
headerLength = headersLength-(nextOffset-contentTypeStart);
|
|
if (headerLength > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
|
|
add_headers (wsp_tree, tmp_tvb);
|
|
}
|
|
offset += count+headersLength+1;
|
|
|
|
/* TODO: Data - decode WMLC */
|
|
/* Runs from offset+1+count+headerLength+1 to end of frame */
|
|
if (tvb_reported_length_remaining (tvb, offset) > 0)
|
|
{
|
|
ti = proto_tree_add_item (wsp_tree, hf_wsp_reply_data,tvb,offset,-1,bo_little_endian);
|
|
}
|
|
}
|
|
if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
|
|
if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
|
|
dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
|
|
}
|
|
break;
|
|
|
|
case PUSH:
|
|
case CONFIRMEDPUSH:
|
|
count = 0; /* Initialise count */
|
|
headersLength = tvb_get_guintvar (tvb, offset, &count);
|
|
headerStart = offset + count;
|
|
|
|
if (tree) {
|
|
ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,tvb,offset,count,headersLength);
|
|
|
|
if (headersLength == 0)
|
|
break;
|
|
|
|
offset += count;
|
|
contentTypeStart = offset;
|
|
nextOffset = add_content_type (wsp_tree,
|
|
tvb, offset, &contentType,
|
|
&contentTypeStr);
|
|
|
|
/* Add headers subtree that will hold the headers fields */
|
|
/* Runs from nextOffset for headersLength-(length of content-type field)*/
|
|
headerLength = headersLength-(nextOffset-contentTypeStart);
|
|
if (headerLength > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, nextOffset, headerLength, headerLength);
|
|
add_headers (wsp_tree, tmp_tvb);
|
|
}
|
|
offset += headersLength;
|
|
|
|
/* Push DATA */
|
|
if (tvb_reported_length_remaining (tvb, offset) > 0)
|
|
{
|
|
ti = proto_tree_add_item (wsp_tree, hf_wsp_push_data,tvb,offset,-1,bo_little_endian);
|
|
}
|
|
}
|
|
if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
|
|
if (!dissector_try_port(wsp_dissector_table, contentType, tmp_tvb, pinfo, tree))
|
|
dissector_try_heuristic(heur_subdissector_list, tmp_tvb, pinfo, tree);
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Called directly from UDP.
|
|
* Put "WSP" into the "Protocol" column.
|
|
*/
|
|
static void
|
|
dissect_wsp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSP" );
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
dissect_wsp_common(tvb, pinfo, tree, wsp_fromudp_handle, TRUE);
|
|
}
|
|
|
|
/*
|
|
* Called from a higher-level WAP dissector, in connection-oriented mode.
|
|
* Leave the "Protocol" column alone - the dissector calling us should
|
|
* have set it.
|
|
*/
|
|
static void
|
|
dissect_wsp_fromwap_co(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
/*
|
|
* XXX - what about WTLS->WTP->WSP?
|
|
*/
|
|
dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, FALSE);
|
|
}
|
|
|
|
/*
|
|
* Called from a higher-level WAP dissector, in connectionless mode.
|
|
* Leave the "Protocol" column alone - the dissector calling us should
|
|
* have set it.
|
|
*/
|
|
static void
|
|
dissect_wsp_fromwap_cl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
/*
|
|
* XXX - what about WTLS->WSP?
|
|
*/
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
{
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
}
|
|
dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, TRUE);
|
|
}
|
|
|
|
static void
|
|
add_uri (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint URILenOffset, guint URIOffset)
|
|
{
|
|
proto_item *ti;
|
|
|
|
guint count = 0;
|
|
guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
|
|
|
|
if (tree)
|
|
ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,tvb,URILenOffset,count,uriLen);
|
|
|
|
if (tree)
|
|
ti = proto_tree_add_item (tree, hf_wsp_header_uri,tvb,URIOffset,uriLen,bo_little_endian);
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
|
|
tvb_format_text (tvb, URIOffset, uriLen));
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_headers (proto_tree *tree, tvbuff_t *tvb)
|
|
{
|
|
proto_item *ti;
|
|
proto_tree *wsp_headers;
|
|
guint offset = 0;
|
|
guint headersLen = tvb_reported_length (tvb);
|
|
guint headerStart = 0;
|
|
guint peek = 0;
|
|
guint pageCode = 1;
|
|
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, headersLen);
|
|
#endif
|
|
|
|
/* End of buffer */
|
|
if (headersLen <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Headers to process\n");
|
|
#endif
|
|
|
|
ti = proto_tree_add_item (tree, hf_wsp_headers_section,tvb,offset,headersLen,bo_little_endian);
|
|
wsp_headers = proto_item_add_subtree( ti, ett_headers );
|
|
|
|
/* Parse Headers */
|
|
|
|
while (offset < headersLen)
|
|
{
|
|
/* Loop round each header */
|
|
headerStart = offset;
|
|
peek = tvb_get_guint8 (tvb, headerStart);
|
|
|
|
if (peek < 32) /* Short-cut shift delimiter */
|
|
{
|
|
pageCode = peek;
|
|
proto_tree_add_uint (wsp_headers,
|
|
hf_wsp_header_shift_code, tvb, offset, 1,
|
|
pageCode);
|
|
offset += 1;
|
|
continue;
|
|
}
|
|
else if (peek == 0x7F) /* Shift delimiter */
|
|
{
|
|
pageCode = tvb_get_guint8(tvb, offset+1);
|
|
proto_tree_add_uint (wsp_headers,
|
|
hf_wsp_header_shift_code, tvb, offset, 2,
|
|
pageCode);
|
|
offset += 2;
|
|
continue;
|
|
}
|
|
else if (peek < 127)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: header: application-header start %d (0x%02X)\n", peek, peek);
|
|
#endif
|
|
/*
|
|
* Token-text, followed by Application-specific-value.
|
|
*/
|
|
offset = add_application_header (wsp_headers, tvb,
|
|
headerStart);
|
|
}
|
|
else if (peek & 0x80)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: header: well-known %d (0x%02X)\n", peek, peek);
|
|
#endif
|
|
/*
|
|
* Well-known-header; the lower 7 bits of "peek"
|
|
* are the header code.
|
|
*/
|
|
switch (pageCode) {
|
|
case 1:
|
|
offset = add_well_known_header (wsp_headers,
|
|
tvb, headerStart, peek & 0x7F);
|
|
break;
|
|
|
|
case 2:
|
|
case 16:
|
|
offset = add_well_known_openwave_header (wsp_headers,
|
|
tvb, headerStart, peek & 0x7F);
|
|
break;
|
|
|
|
default:
|
|
offset = add_unknown_header (wsp_headers,
|
|
tvb, headerStart, peek & 0x7F);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int
|
|
add_well_known_header (proto_tree *tree, tvbuff_t *tvb, int offset,
|
|
guint8 headerType)
|
|
{
|
|
int headerStart;
|
|
value_type_t valueType;
|
|
int headerLen;
|
|
guint valueLen;
|
|
int valueStart;
|
|
tvbuff_t *header_buff;
|
|
tvbuff_t *value_buff;
|
|
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Got header 0x%02x\n", headerType);
|
|
#endif
|
|
headerStart = offset;
|
|
|
|
/*
|
|
* Skip the Short-Integer header type.
|
|
*/
|
|
offset++;
|
|
|
|
/*
|
|
* Get the value type and length (or, if the type is VALUE_IN_LEN,
|
|
* meaning the value is a Short-integer, get the value type
|
|
* and the value itself).
|
|
*/
|
|
valueType = get_value_type_len (tvb, offset, &valueLen,
|
|
&valueStart, &offset);
|
|
headerLen = offset - headerStart;
|
|
|
|
/*
|
|
* Get a tvbuff for the entire header.
|
|
* XXX - cut the actual length short so that it doesn't run
|
|
* past the actual length of tvb.
|
|
*/
|
|
header_buff = tvb_new_subset (tvb, headerStart, headerLen,
|
|
headerLen);
|
|
|
|
/*
|
|
* If the value wasn't in the length, get a tvbuff for the value.
|
|
* XXX - can valueLen be 0?
|
|
* XXX - cut the actual length short so that it doesn't run
|
|
* past the actual length of tvb.
|
|
*/
|
|
if (valueType != VALUE_IN_LEN) {
|
|
value_buff = tvb_new_subset (tvb, valueStart, valueLen,
|
|
valueLen);
|
|
} else {
|
|
/*
|
|
* XXX - when the last dissector is tvbuffified,
|
|
* so that NULL is no longer a valid tvb pointer
|
|
* value in "proto_tree_add" calls, just
|
|
* set "value_buff" to NULL.
|
|
*
|
|
* XXX - can we already do that? I.e., will that
|
|
* cause us always to crash if we mistakenly try
|
|
* to fetch the value of a VALUE_IN_LEN item?
|
|
*/
|
|
value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
|
|
}
|
|
|
|
switch (headerType) {
|
|
|
|
case FN_ACCEPT: /* Accept */
|
|
add_accept_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_ACCEPT_CHARSET_DEP: /* Accept-Charset */
|
|
/*
|
|
* XXX - should both encoding versions 1.1 and
|
|
* 1.3 be handled this way?
|
|
*/
|
|
add_accept_xxx_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_accept_charset,
|
|
hf_wsp_header_accept_charset_str,
|
|
vals_character_sets, "Unknown charset (%u)");
|
|
break;
|
|
|
|
case FN_ACCEPT_LANGUAGE: /* Accept-Language */
|
|
add_accept_xxx_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_accept_language,
|
|
hf_wsp_header_accept_language_str,
|
|
vals_languages, "Unknown language (%u)");
|
|
break;
|
|
|
|
case FN_ACCEPT_RANGES: /* Accept-Ranges */
|
|
add_accept_ranges_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_AGE: /* Age */
|
|
add_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_age,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_CACHE_CONTROL_DEP: /* Cache-Control */
|
|
case FN_CACHE_CONTROL:
|
|
case FN_CACHE_CONTROL14:
|
|
/*
|
|
* XXX - is the only difference in the three different
|
|
* versions (1.1, 1.3, 1.4) really only S_MAXAGE?
|
|
*/
|
|
add_cache_control_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_CONNECTION: /* Connection */
|
|
add_connection_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_CONTENT_LENGTH: /* Content-Length */
|
|
add_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_content_length,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_DATE: /* Date */
|
|
add_date_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_date, headerType);
|
|
break;
|
|
|
|
case FN_ETAG: /* Etag */
|
|
add_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_etag, headerType);
|
|
break;
|
|
|
|
case FN_EXPIRES: /* Expires */
|
|
add_date_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_expires, headerType);
|
|
break;
|
|
|
|
case FN_IF_MODIFIED_SINCE: /* If-Modified-Since */
|
|
add_date_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_if_modified_since, headerType);
|
|
break;
|
|
|
|
case FN_LOCATION: /* Location */
|
|
add_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_location, headerType);
|
|
break;
|
|
|
|
case FN_LAST_MODIFIED: /* Last-Modified */
|
|
add_date_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_last_modified, headerType);
|
|
break;
|
|
|
|
case FN_PRAGMA: /* Pragma */
|
|
add_pragma_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_SERVER: /* Server */
|
|
add_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_server, headerType);
|
|
break;
|
|
|
|
case FN_TRANSFER_ENCODING: /* Transfer-Encoding */
|
|
add_transfer_encoding_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_USER_AGENT: /* User-Agent */
|
|
add_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_user_agent, headerType);
|
|
break;
|
|
|
|
case FN_VIA: /* Via */
|
|
add_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_via, headerType);
|
|
break;
|
|
|
|
case FN_WARNING: /* Warning */
|
|
add_warning_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_ACCEPT_APPLICATION: /* Accept-Application */
|
|
add_accept_application_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_BEARER_INDICATION: /* Bearer-Indication */
|
|
add_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_bearer_indication, headerType);
|
|
break;
|
|
|
|
case FN_PROFILE: /* Profile */
|
|
add_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_profile, headerType);
|
|
break;
|
|
|
|
case FN_X_WAP_APPLICATION_ID: /* X-Wap-Application-Id */
|
|
add_wap_application_id_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_CONTENT_ID: /* Content-ID */
|
|
add_quoted_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_content_ID, headerType);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Unsupported Header: %s",
|
|
val_to_str (headerType, vals_field_names, "Unknown (0x%02X)"));
|
|
break;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
|
|
static int
|
|
add_well_known_openwave_header (proto_tree *tree, tvbuff_t *tvb, int offset,
|
|
guint8 headerType)
|
|
{
|
|
int headerStart;
|
|
value_type_t valueType;
|
|
int headerLen;
|
|
guint valueLen;
|
|
int valueStart;
|
|
tvbuff_t *header_buff;
|
|
tvbuff_t *value_buff;
|
|
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Got Openwave header 0x%02x\n", headerType);
|
|
#endif
|
|
headerStart = offset;
|
|
|
|
/*
|
|
* Skip the Short-Integer header type.
|
|
*/
|
|
offset++;
|
|
|
|
/*
|
|
* Get the value type and length (or, if the type is VALUE_IN_LEN,
|
|
* meaning the value is a Short-integer, get the value type
|
|
* and the value itself).
|
|
*/
|
|
valueType = get_value_type_len (tvb, offset, &valueLen,
|
|
&valueStart, &offset);
|
|
headerLen = offset - headerStart;
|
|
|
|
/*
|
|
* Get a tvbuff for the entire header.
|
|
* XXX - cut the actual length short so that it doesn't run
|
|
* past the actual length of tvb.
|
|
*/
|
|
header_buff = tvb_new_subset (tvb, headerStart, headerLen,
|
|
headerLen);
|
|
|
|
/*
|
|
* If the value wasn't in the length, get a tvbuff for the value.
|
|
* XXX - can valueLen be 0?
|
|
* XXX - cut the actual length short so that it doesn't run
|
|
* past the actual length of tvb.
|
|
*/
|
|
if (valueType != VALUE_IN_LEN) {
|
|
value_buff = tvb_new_subset (tvb, valueStart, valueLen,
|
|
valueLen);
|
|
} else {
|
|
/*
|
|
* XXX - when the last dissector is tvbuffified,
|
|
* so that NULL is no longer a valid tvb pointer
|
|
* value in "proto_tree_add" calls, just
|
|
* set "value_buff" to NULL.
|
|
*
|
|
* XXX - can we already do that? I.e., will that
|
|
* cause us always to crash if we mistakenly try
|
|
* to fetch the value of a VALUE_IN_LEN item?
|
|
*/
|
|
value_buff = tvb_new_subset (tvb, headerStart, 0, 0);
|
|
}
|
|
|
|
switch (headerType) {
|
|
|
|
/* case FN_OPENWAVE_PROXY_PUSH_ADDR: / x-up-proxy-push-addr */
|
|
/* add_openwave_push_address_header (tree, header_buff, headerLen, */
|
|
/* value_buff, valueType, valueLen); */
|
|
/* break; */
|
|
|
|
case FN_OPENWAVE_PROXY_PUSH_ACCEPT: /* x-up-proxy-push-accept */
|
|
add_accept_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_PUSH_SEQ: /* x-up-proxy-push-seq */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_push_seq,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_NOTIFY: /* x-up-proxy-notify */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_notify,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_OPERATOR_DOMAIN: /* x-up-proxy-operator-domain */
|
|
add_openwave_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_operator_domain, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_HOME_PAGE: /* x-up-proxy-home-page */
|
|
add_openwave_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_home_page, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_DEVCAP_HAS_COLOR: /* x-up-devcap-has-color */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_has_color,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS: /* x-up-devcap-num-softkeys */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_num_softkeys,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE: /* x-up-devcap-softkey-size */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_softkey_size,
|
|
headerType);
|
|
break;
|
|
|
|
/* case FN_OPENWAVE_DEVCAP_SCREEN_CHARS: / x-up-devcap-screen-chars */
|
|
/* add_openwave_integer_value_header (tree, header_buff, headerLen, */
|
|
/* value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_chars, */
|
|
/* headerType); */
|
|
/* break; */
|
|
|
|
/* case FN_OPENWAVE_DEVCAP_SCREEN_PIXELS: / x-up-devcap-screen-pixels */
|
|
/* add_openwave_integer_value_header (tree, header_buff, headerLen, */
|
|
/* value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_pixels, */
|
|
/* headerType); */
|
|
/* break; */
|
|
|
|
/* case FN_OPENWAVE_DEVCAP_EM_SIZE: / x-up-devcap-em-size */
|
|
/* add_openwave_integer_value_header (tree, header_buff, headerLen, */
|
|
/* value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_em_size, */
|
|
/* headerType); */
|
|
/* break; */
|
|
|
|
case FN_OPENWAVE_DEVCAP_SCREEN_DEPTH: /* x-up-devcap-screen-depth */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_screen_depth,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_DEVCAP_IMMED_ALERT: /* x-up-devcap-immed-alert */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_immed_alert,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_NET_ASK: /* x-up-proxy-net-ask */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_net_ask,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_UPLINK_VERSION: /* x-up-proxy-uplink-version */
|
|
add_openwave_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_uplink_version, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_TOD: /* x-up-proxy-tod */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_tod, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_BA_ENABLE: /* x-up-proxy-ba-enable */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_ba_enable, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_BA_REALM: /* x-up-proxy-ba-realm */
|
|
add_openwave_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_ba_realm, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_REDIRECT_ENABLE: /* x-up-proxy-redirect-enable */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_redirect_enable, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_REQUEST_URI: /* x-up-proxy-request-uri */
|
|
add_openwave_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_request_uri, headerType);
|
|
break;
|
|
|
|
/* case FN_OPENWAVE_PROXY_REDIRECT_STATUS: / x-up-proxy-redirect-status */
|
|
/* add_openwave_integer_value_header (tree, header_buff, headerLen, */
|
|
/* value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_redirect_status, */
|
|
/* headerType); */
|
|
/* break; */
|
|
|
|
case FN_OPENWAVE_PROXY_TRANS_CHARSET: /* x-up-proxy-trans-charset */
|
|
add_accept_xxx_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_trans_charset,
|
|
hf_wsp_header_openwave_proxy_trans_charset_str,
|
|
vals_character_sets, "Unknown charset (%u)");
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_LINGER: /* x-up-proxy-linger */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_linger,
|
|
headerType);
|
|
break;
|
|
|
|
/* case FN_OPENWAVE_PROXY_CLIENT_ID: / x-up-proxy-client-id */
|
|
/* add_openwave_string_value_header (tree, header_buff, headerLen, */
|
|
/* value_buff, valueType, valueLen, */
|
|
/* hf_wsp_header_openwave_proxy_client_id, headerType); */
|
|
/* break; */
|
|
|
|
case FN_OPENWAVE_PROXY_ENABLE_TRUST: /* x-up-proxy-enable-trust */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_enable_trust,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_TRUST_OLD: /* x-up-proxy-trust old value */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_trust_old,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_TRUST: /* x-up-proxy-trust */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_proxy_trust,
|
|
headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_PROXY_BOOKMARK: /* x-up-proxy-bookmark */
|
|
add_openwave_string_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen,
|
|
hf_wsp_header_openwave_proxy_bookmark, headerType);
|
|
break;
|
|
|
|
case FN_OPENWAVE_DEVCAP_GUI: /* x-up-devcap-gui */
|
|
add_openwave_integer_value_header (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_wsp_header_openwave_devcap_gui,
|
|
headerType);
|
|
break;
|
|
|
|
default:
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Unsupported Openwave Header: %s",
|
|
val_to_str (headerType, vals_openwave_field_names, "Unknown (0x%02X)"));
|
|
break;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
/* *********
|
|
static void
|
|
add_openwave_push_address_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
|
|
???
|
|
|
|
}
|
|
********* */
|
|
|
|
static int
|
|
add_unknown_header (proto_tree *tree, tvbuff_t *tvb, int offset,
|
|
guint8 headerType)
|
|
{
|
|
int headerStart;
|
|
int valueStart;
|
|
value_type_t valueType;
|
|
int headerLen;
|
|
guint valueLen;
|
|
int valueOffset;
|
|
|
|
headerStart = offset;
|
|
|
|
/*
|
|
* Skip the Short-Integer header type.
|
|
*/
|
|
offset++;
|
|
|
|
valueStart = offset;
|
|
|
|
/*
|
|
* Get the value type and length (or, if the type is VALUE_IN_LEN,
|
|
* meaning the value is a Short-integer, get the value type
|
|
* and the value itself).
|
|
*/
|
|
valueType = get_value_type_len (tvb, valueStart, &valueLen,
|
|
&valueOffset, &offset);
|
|
headerLen = offset - headerStart;
|
|
|
|
proto_tree_add_text (tree, tvb, headerStart, headerLen,
|
|
"Unsupported Header (0x%02X)", headerType);
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
add_application_header (proto_tree *tree, tvbuff_t *tvb, int offset)
|
|
{
|
|
int startOffset;
|
|
guint tokenSize;
|
|
const guint8 *token;
|
|
value_type_t valueType;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint secs;
|
|
nstime_t timeValue;
|
|
int asvOffset;
|
|
guint stringSize;
|
|
|
|
startOffset = offset;
|
|
tokenSize = tvb_strsize (tvb, startOffset);
|
|
token = tvb_get_ptr (tvb, startOffset, tokenSize);
|
|
offset += tokenSize;
|
|
|
|
/*
|
|
* Special case header "X-WAP.TOD" that is sometimes followed
|
|
* by a 4-byte date value.
|
|
*
|
|
* XXX - according to the 4-May-2000 WSP spec, X-Wap-Tod is
|
|
* encoded as a well known header, with a code of 0x3F.
|
|
*/
|
|
if (tokenSize == 10 && strncasecmp ("x-wap.tod", token, 9) == 0)
|
|
{
|
|
valueType = get_value_type_len (tvb, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (get_integer (tvb, subvalueOffset, subvalueLen,
|
|
valueType, &secs) == 0)
|
|
{
|
|
/*
|
|
* Fill in the "struct timeval", and add it to the
|
|
* protocol tree.
|
|
* Note: this will succeed even if it's a Short-integer.
|
|
* A Short-integer would work, but, as the time values
|
|
* are UNIX seconds-since-the-Epoch value, and as
|
|
* there weren't WAP phones or Web servers back in
|
|
* late 1969/early 1970, they're unlikely to be used.
|
|
*/
|
|
timeValue.secs = secs;
|
|
timeValue.nsecs = 0;
|
|
proto_tree_add_time (tree, hf_wsp_header_x_wap_tod,
|
|
tvb, startOffset, offset - startOffset, &timeValue);
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_text (tree, tvb, startOffset,
|
|
offset - startOffset,
|
|
"%s: invalid date value", token);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
asvOffset = offset;
|
|
stringSize = tvb_strsize (tvb, asvOffset);
|
|
offset += stringSize;
|
|
proto_tree_add_text (tree, tvb, startOffset,
|
|
offset - startOffset,
|
|
"%s: %s", token,
|
|
tvb_get_ptr (tvb, asvOffset, stringSize));
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
add_accept_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
guint contentType;
|
|
const char *contentTypeStr;
|
|
|
|
add_content_type_value (tree, header_buff, 0, headerLen, value_buff,
|
|
valueType, valueLen, hf_wsp_header_accept,
|
|
hf_wsp_header_accept_str, &contentType, &contentTypeStr);
|
|
}
|
|
|
|
static void
|
|
add_accept_xxx_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_numeric, int hf_string,
|
|
const value_string *vals, const char *unknown_tag)
|
|
{
|
|
int offset = 0;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value = 0;
|
|
char valString[100];
|
|
const char *valMatch;
|
|
guint peek;
|
|
double q_value = 1.0;
|
|
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Constrained-{charset,language} (Short-Integer).
|
|
*/
|
|
proto_tree_add_uint (tree, hf_numeric,
|
|
header_buff, 0, headerLen,
|
|
valueLen); /* valueLen is the value */
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Constrained-{charset,language} (text, i.e.
|
|
* Extension-Media).
|
|
*/
|
|
proto_tree_add_string (tree, hf_string,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* First byte had the 8th bit set.
|
|
*/
|
|
if (valueLen == 0) {
|
|
/*
|
|
* Any-{charset,language}.
|
|
*/
|
|
proto_tree_add_string (tree, hf_string,
|
|
header_buff, 0, headerLen,
|
|
"*");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Accept-{charset,language}-general-form; Value-length, followed
|
|
* by Well-known-{charset,language} or {Token-text,Text-string},
|
|
* possibly followed by a Q-value.
|
|
*
|
|
* Get Value-length.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, 0, &subvalueLen,
|
|
&subvalueOffset, &offset);
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* {Token-text,Text-string}.
|
|
*/
|
|
valMatch =
|
|
tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
|
|
proto_tree_add_string (tree, hf_string,
|
|
value_buff, 0, valueLen, valMatch);
|
|
} else {
|
|
/*
|
|
* Well-known-{charset,langugage}; starts with an
|
|
* Integer-value.
|
|
*/
|
|
if (get_integer (value_buff, subvalueOffset, subvalueLen,
|
|
valueType, &value) < 0)
|
|
{
|
|
valMatch = "Invalid integer";
|
|
}
|
|
else
|
|
{
|
|
valMatch = val_to_str(value, vals, unknown_tag);
|
|
}
|
|
}
|
|
|
|
/* Any remaining data relates to Q-value */
|
|
if (offset < valueLen)
|
|
{
|
|
peek = tvb_get_guintvar (value_buff, offset, NULL);
|
|
if (peek <= 100) {
|
|
peek = (peek - 1) * 10;
|
|
}
|
|
else {
|
|
peek -= 100;
|
|
}
|
|
q_value = peek/1000.0;
|
|
}
|
|
|
|
/* Build string including Q-value if present */
|
|
if (q_value == 1.0) /* Default */
|
|
{
|
|
snprintf (valString, 100, "%s", valMatch);
|
|
}
|
|
else
|
|
{
|
|
snprintf (valString, 100, "%s; Q=%5.3f", valMatch, q_value);
|
|
}
|
|
/* Add string to tree */
|
|
proto_tree_add_string (tree, hf_string,
|
|
header_buff, 0, headerLen, valString);
|
|
}
|
|
|
|
static void
|
|
add_accept_ranges_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Must be 0 (None) or 1 (Bytes) (the 8th bit was stripped
|
|
* off).
|
|
*/
|
|
proto_tree_add_uint (tree, hf_wsp_header_accept_ranges,
|
|
header_buff, 0, headerLen,
|
|
valueLen); /* valueLen is the value */
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Token-text.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_header_accept_ranges_str,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Not valid.
|
|
*/
|
|
fprintf(stderr, "dissect_wsp: Accept-Ranges is neither None, Bytes, nor Token-text\n");
|
|
return;
|
|
}
|
|
|
|
static void
|
|
add_cache_control_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
int offset = 0;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value;
|
|
proto_item *ti;
|
|
proto_tree *parameter_tree;
|
|
proto_tree *field_names_tree;
|
|
guint delta_secs;
|
|
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* No-cache, No-store, Max-age, Max-stale, Min-fresh,
|
|
* Only-if-cached, Public, Private, No-transform,
|
|
* Must-revalidate, Proxy-revalidate, or S-maxage.
|
|
*/
|
|
proto_tree_add_uint (tree, hf_wsp_header_cache_control,
|
|
header_buff, 0, headerLen,
|
|
valueLen); /* valueLen is the value */
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Cache-extension.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Value-length Cache-directive.
|
|
* Get first field of Cache-directive.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, offset, &subvalueLen,
|
|
&subvalueOffset, &offset);
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Cache-extension Parameter.
|
|
*/
|
|
ti = proto_tree_add_string (tree, hf_wsp_header_cache_control_str,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
parameter_tree = proto_item_add_subtree (ti,
|
|
ett_header_cache_control_parameters);
|
|
|
|
/*
|
|
* Process the rest of the value as parameters.
|
|
*/
|
|
while (tvb_reported_length_remaining (value_buff, offset) > 0) {
|
|
offset = add_parameter (parameter_tree, value_buff,
|
|
offset);
|
|
}
|
|
return;
|
|
}
|
|
if (get_integer (value_buff, subvalueOffset, subvalueLen, valueType,
|
|
&value) < 0)
|
|
{
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Cache-Control Cache-directive value");
|
|
}
|
|
else
|
|
{
|
|
switch (value) {
|
|
|
|
case NO_CACHE:
|
|
case PRIVATE:
|
|
/*
|
|
* Loop, processing Field-names.
|
|
*/
|
|
ti = proto_tree_add_uint (tree,
|
|
hf_wsp_header_cache_control,
|
|
header_buff, 0, headerLen,
|
|
value);
|
|
field_names_tree = proto_item_add_subtree (ti,
|
|
ett_header_cache_control_field_names);
|
|
while (tvb_reported_length_remaining (value_buff, offset)
|
|
> 0) {
|
|
offset = add_cache_control_field_name (tree,
|
|
value_buff, offset, value);
|
|
}
|
|
break;
|
|
|
|
case MAX_AGE:
|
|
case MAX_STALE:
|
|
case MIN_FRESH:
|
|
case S_MAXAGE:
|
|
/*
|
|
* Get Delta-second-value.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (get_integer (value_buff, subvalueOffset,
|
|
subvalueLen, valueType, &delta_secs) < 0)
|
|
{
|
|
proto_tree_add_text (tree,
|
|
header_buff, 0, headerLen,
|
|
"Invalid Cache-Control %s Delta-second-value",
|
|
match_strval (value, vals_cache_control));
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_uint_format (tree,
|
|
hf_wsp_header_cache_control,
|
|
header_buff, 0, headerLen,
|
|
value,
|
|
"Cache-Control: %s %u secs",
|
|
match_strval (value, vals_cache_control),
|
|
delta_secs);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
* This should not happen, but handle it anyway.
|
|
*/
|
|
proto_tree_add_uint (tree,
|
|
hf_wsp_header_cache_control,
|
|
header_buff, 0, headerLen,
|
|
value);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int
|
|
add_cache_control_field_name (proto_tree *tree, tvbuff_t *value_buff,
|
|
int offset, guint cache_control_value)
|
|
{
|
|
value_type_t valueType;
|
|
int startOffset;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
|
|
startOffset = offset;
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Token-text.
|
|
*/
|
|
proto_tree_add_item (tree,
|
|
hf_wsp_header_cache_control_field_name_str,
|
|
value_buff, startOffset, offset - startOffset,
|
|
bo_little_endian);
|
|
}
|
|
else if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Short-integer Field-name.
|
|
*/
|
|
proto_tree_add_uint (tree,
|
|
hf_wsp_header_cache_control_field_name,
|
|
value_buff, startOffset, offset - startOffset,
|
|
subvalueLen);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Long-integer - illegal.
|
|
*/
|
|
proto_tree_add_text (tree,
|
|
value_buff, startOffset, offset - startOffset,
|
|
"Invalid Cache-Control %s Field-name",
|
|
match_strval (cache_control_value, vals_cache_control));
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
add_connection_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
int offset = 0;
|
|
|
|
if (valueType == VALUE_LEN_SUPPLIED)
|
|
{
|
|
/*
|
|
* Invalid.
|
|
*/
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Connection value");
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Token-text.
|
|
*/
|
|
proto_tree_add_string (tree,
|
|
hf_wsp_header_connection_str,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* First byte had the 8th bit set.
|
|
*/
|
|
if (valueLen == 0) {
|
|
/*
|
|
* Close.
|
|
*/
|
|
proto_tree_add_uint (tree, hf_wsp_header_connection,
|
|
header_buff, offset, headerLen, valueLen);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Invalid.
|
|
*/
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Connection value");
|
|
}
|
|
|
|
static void
|
|
add_pragma_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
int offset = 0;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Invalid.
|
|
*/
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Pragma");
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Invalid?
|
|
*/
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Pragma");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* First byte had the 8th bit set.
|
|
*/
|
|
if (valueLen == 0) {
|
|
/*
|
|
* No-cache.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_header_pragma,
|
|
header_buff, 0, headerLen, "No-cache");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Value-length, followed by Parameter.
|
|
*
|
|
* Get Value-length.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, 0, &subvalueLen,
|
|
&subvalueOffset, &offset);
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Parameter - a text string.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_header_pragma,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
|
|
} else {
|
|
/*
|
|
* Parameter - numeric; illegal?
|
|
*/
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Pragma");
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_transfer_encoding_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
int offset = 0;
|
|
|
|
if (valueType == VALUE_LEN_SUPPLIED)
|
|
{
|
|
/*
|
|
* Invalid.
|
|
*/
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Transfer-Encoding value");
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Token-text.
|
|
*/
|
|
proto_tree_add_string (tree,
|
|
hf_wsp_header_transfer_encoding_str,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* First byte had the 8th bit set.
|
|
*/
|
|
if (valueLen == 0) {
|
|
/*
|
|
* Chunked.
|
|
*/
|
|
proto_tree_add_uint (tree, hf_wsp_header_transfer_encoding,
|
|
header_buff, offset, headerLen, valueLen);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Invalid.
|
|
*/
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Transfer Encoding value");
|
|
}
|
|
|
|
static void
|
|
add_warning_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
int offset = 0;
|
|
proto_item *ti;
|
|
proto_tree *warning_tree;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
|
|
/*
|
|
* Put the items under a header.
|
|
* XXX - make the text of the item summarize the elements.
|
|
*/
|
|
ti = proto_tree_add_item (tree, hf_wsp_header_warning,
|
|
header_buff, 0, headerLen, bo_little_endian);
|
|
warning_tree = proto_item_add_subtree(ti, ett_header_warning);
|
|
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Warn-code (Short-integer).
|
|
*/
|
|
proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
|
|
header_buff, 0, headerLen,
|
|
valueLen); /* valueLen is the value */
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Invalid.
|
|
*/
|
|
proto_tree_add_text (warning_tree, header_buff, 0, headerLen,
|
|
"Invalid Warning (all text)");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Warning-value; Warn-code, followed by Warn-agent, followed by
|
|
* Warn-text.
|
|
*/
|
|
/*
|
|
* Get Short-integer Warn-code.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, offset, &subvalueLen,
|
|
&subvalueOffset, &offset);
|
|
if (valueType != VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Not a Short-integer.
|
|
*/
|
|
proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
|
|
subvalueLen, "Invalid Warn-code (not a Short-integer)");
|
|
return;
|
|
}
|
|
proto_tree_add_uint (warning_tree, hf_wsp_header_warning_code,
|
|
value_buff, subvalueOffset, 1,
|
|
subvalueLen); /* subvalueLen is the value */
|
|
|
|
/*
|
|
* Warn-agent; must be text.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, offset, &subvalueLen,
|
|
&subvalueOffset, &offset);
|
|
if (valueType != VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Not text.
|
|
*/
|
|
proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
|
|
subvalueLen, "Invalid Warn-agent (not a text string)");
|
|
return;
|
|
}
|
|
proto_tree_add_item (warning_tree,
|
|
hf_wsp_header_warning_agent,
|
|
value_buff, subvalueOffset, subvalueLen, bo_little_endian);
|
|
|
|
/*
|
|
* Warn-text; must be text.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, offset, &subvalueLen,
|
|
&subvalueOffset, &offset);
|
|
if (valueType != VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Not text.
|
|
*/
|
|
proto_tree_add_text (warning_tree, value_buff, subvalueOffset,
|
|
subvalueLen, "Invalid Warn-text (not a text string)");
|
|
return;
|
|
}
|
|
proto_tree_add_item (warning_tree,
|
|
hf_wsp_header_warning_text,
|
|
value_buff, subvalueOffset, subvalueLen, bo_little_endian);
|
|
}
|
|
|
|
static void
|
|
add_accept_application_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
guint value;
|
|
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Application-id-value; numeric, so it's App-assigned-code.
|
|
*/
|
|
proto_tree_add_uint (tree, hf_wsp_header_accept_application,
|
|
header_buff, 0, headerLen,
|
|
valueLen); /* valueLen is the value */
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Uri-value.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* First byte had the 8th bit set.
|
|
*/
|
|
if (valueLen == 0) {
|
|
/*
|
|
* Any-application.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_header_accept_application_str,
|
|
header_buff, 0, headerLen,
|
|
"*");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Integer-value, hence App-assigned-code.
|
|
*/
|
|
if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
|
|
{
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid Accept-Application App-assigned-code");
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_uint (tree, hf_wsp_header_accept_application,
|
|
header_buff, 0, headerLen, value);
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_wap_application_id_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen)
|
|
{
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Must application-id (the 8th bit was stripped off).
|
|
*/
|
|
proto_tree_add_uint (tree, hf_wsp_header_wap_application_id,
|
|
header_buff, 0, headerLen,
|
|
valueLen); /* valueLen is the value */
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Token-text.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_header_wap_application_id_str,
|
|
header_buff, 0, headerLen,
|
|
tvb_get_ptr (value_buff, 0, valueLen));
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Not valid.
|
|
*/
|
|
fprintf(stderr, "dissect_wsp: Suprising format of X-Wap-Application-Id\n");
|
|
return;
|
|
}
|
|
|
|
static void
|
|
add_capabilities (proto_tree *tree, tvbuff_t *tvb, int type)
|
|
{
|
|
proto_item *ti;
|
|
proto_tree *wsp_capabilities;
|
|
guint offset = 0;
|
|
guint offsetStr = 0;
|
|
guint capabilitiesLen = tvb_reported_length (tvb);
|
|
guint capabilitiesStart = 0;
|
|
guint peek = 0;
|
|
guint length = 0;
|
|
guint value = 0;
|
|
guint i;
|
|
int ret;
|
|
char valString[200];
|
|
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Offset is %d, size is %d\n", offset, capabilitiesLen);
|
|
#endif
|
|
|
|
/* End of buffer */
|
|
if (capabilitiesLen <= 0)
|
|
{
|
|
fprintf (stderr, "dissect_wsp: Capabilities = 0\n");
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: capabilities to process\n");
|
|
#endif
|
|
|
|
ti = proto_tree_add_item (tree, hf_wsp_capabilities_section,tvb,offset,capabilitiesLen,bo_little_endian);
|
|
wsp_capabilities = proto_item_add_subtree( ti, ett_capabilities );
|
|
|
|
/* Parse Headers */
|
|
|
|
while (offset < capabilitiesLen)
|
|
{
|
|
/* Loop round each header */
|
|
capabilitiesStart = offset;
|
|
length = tvb_get_guint8 (tvb, capabilitiesStart);
|
|
|
|
if (length >= 127) /* length */
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: capabilities length invalid %d\n",length);
|
|
#endif
|
|
offset+=length;
|
|
continue;
|
|
}
|
|
offset++;
|
|
peek = tvb_get_guint8 (tvb, offset);
|
|
offset++;
|
|
switch (peek & 0x7f)
|
|
{
|
|
case 0x00 : /* Client-SDU-Size */
|
|
value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
|
|
proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_client_SDU, tvb, capabilitiesStart, length+1, value);
|
|
break;
|
|
case 0x01 : /* Server-SDU-Size */
|
|
value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
|
|
proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_server_SDU, tvb, capabilitiesStart, length+1, value);
|
|
break;
|
|
case 0x02 : /* Protocol Options */
|
|
value = get_uintvar (tvb, offset, length+capabilitiesStart+1);
|
|
i = 0;
|
|
valString[0]=0;
|
|
if (value & 0x80)
|
|
{
|
|
ret = snprintf(valString+i,200-i,"%s","(Confirmed push facility) ");
|
|
if (ret == -1) {
|
|
/*
|
|
* Some versions of snprintf
|
|
* return -1 if they'd
|
|
* truncate the output.
|
|
*/
|
|
goto add_string;
|
|
}
|
|
i += ret;
|
|
}
|
|
if (value & 0x40)
|
|
{
|
|
if (i >= 200) {
|
|
/* No more room. */
|
|
goto add_string;
|
|
}
|
|
ret = snprintf(valString+i,200-i,"%s","(Push facility) ");
|
|
if (ret == -1) {
|
|
/*
|
|
* Some versions of snprintf
|
|
* return -1 if they'd
|
|
* truncate the output.
|
|
*/
|
|
goto add_string;
|
|
}
|
|
i += ret;
|
|
}
|
|
if (value & 0x20)
|
|
{
|
|
if (i >= 200) {
|
|
/* No more room. */
|
|
goto add_string;
|
|
}
|
|
ret = snprintf(valString+i,200-i,"%s","(Session resume facility) ");
|
|
if (ret == -1) {
|
|
/*
|
|
* Some versions of snprintf
|
|
* return -1 if they'd
|
|
* truncate the output.
|
|
*/
|
|
goto add_string;
|
|
}
|
|
i += ret;
|
|
}
|
|
if (value & 0x10)
|
|
{
|
|
if (i >= 200) {
|
|
/* No more room. */
|
|
goto add_string;
|
|
}
|
|
ret = snprintf(valString+i,200-i,"%s","(Acknowledgement headers) ");
|
|
if (ret == -1) {
|
|
/*
|
|
* Some versions of snprintf
|
|
* return -1 if they'd
|
|
* truncate the output.
|
|
*/
|
|
goto add_string;
|
|
}
|
|
i += ret;
|
|
}
|
|
add_string:
|
|
proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_protocol_opt, tvb, capabilitiesStart, length+1, valString);
|
|
break;
|
|
case 0x03 : /* Method-MOR */
|
|
value = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_method_MOR, tvb, capabilitiesStart, length+1, value);
|
|
break;
|
|
case 0x04 : /* Push-MOR */
|
|
value = tvb_get_guint8(tvb, offset);
|
|
proto_tree_add_uint (wsp_capabilities, hf_wsp_capabilities_push_MOR, tvb, capabilitiesStart, length+1, value);
|
|
break;
|
|
break;
|
|
case 0x05 : /* Extended Methods */
|
|
offsetStr = offset;
|
|
offset++;
|
|
add_capability_vals(tvb, (type == CONNECT),
|
|
offsetStr, length, capabilitiesStart,
|
|
valString, sizeof valString);
|
|
proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_extended_methods, tvb, capabilitiesStart, length+1, valString);
|
|
break;
|
|
case 0x06 : /* Header Code Pages */
|
|
offsetStr = offset;
|
|
offset++;
|
|
add_capability_vals(tvb, (type == CONNECT),
|
|
offsetStr, length, capabilitiesStart,
|
|
valString, sizeof valString);
|
|
proto_tree_add_string(wsp_capabilities, hf_wsp_capabilities_header_code_pages, tvb, capabilitiesStart, length+1, valString);
|
|
break;
|
|
case 0x07 : /* Aliases */
|
|
break;
|
|
default:
|
|
proto_tree_add_text (wsp_capabilities, tvb , capabilitiesStart, length+1,
|
|
"Unsupported Header (0x%02X)", peek & 0x7F);
|
|
break;
|
|
}
|
|
offset=capabilitiesStart+length+1;
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_capability_vals(tvbuff_t *tvb, gboolean add_string, int offsetStr,
|
|
guint length, guint capabilitiesStart, char *valString,
|
|
size_t valStringSize)
|
|
{
|
|
guint i;
|
|
int ret;
|
|
guint value;
|
|
guint8 c;
|
|
|
|
i = 0;
|
|
while ((offsetStr-capabilitiesStart) <= length)
|
|
{
|
|
value = tvb_get_guint8(tvb, offsetStr);
|
|
if (i >= valStringSize) {
|
|
/* No more room. */
|
|
break;
|
|
}
|
|
if (add_string)
|
|
{
|
|
ret = snprintf(valString+i,valStringSize-i,
|
|
"(%d - ",value);
|
|
}
|
|
else
|
|
{
|
|
ret = snprintf(valString+i,valStringSize-i,"(%d) ",
|
|
value);
|
|
}
|
|
if (ret == -1) {
|
|
/*
|
|
* Some versions of snprintf return -1
|
|
* if they'd truncate the output.
|
|
*/
|
|
break;
|
|
}
|
|
i += ret;
|
|
offsetStr++;
|
|
if (add_string)
|
|
{
|
|
for (;(c = tvb_get_guint8(tvb, offsetStr))
|
|
&& i < valStringSize - 1; i++,offsetStr++)
|
|
valString[i] = c;
|
|
offsetStr++;
|
|
if (i < valStringSize - 2) {
|
|
valString[i++] = ')';
|
|
valString[i++] = ' ';
|
|
}
|
|
}
|
|
}
|
|
valString[i] = '\0';
|
|
}
|
|
|
|
static value_type_t
|
|
get_value_type_len (tvbuff_t *tvb, int offset, guint *valueLen,
|
|
int *valueOffset, int *nextOffset)
|
|
{
|
|
guint8 peek;
|
|
guint32 len;
|
|
guint count;
|
|
|
|
/* Get value part of header */
|
|
peek = tvb_get_guint8 (tvb, offset);
|
|
if (peek <= 30)
|
|
{
|
|
/*
|
|
* The value follows "peek", and is "peek" octets long.
|
|
*/
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Looking for %d octets\n", peek);
|
|
#endif
|
|
len = peek;
|
|
*valueLen = len; /* Length of value */
|
|
offset++; /* Skip the length */
|
|
*valueOffset = offset; /* Offset of value */
|
|
offset += len; /* Skip the value */
|
|
*nextOffset = offset; /* Offset after value */
|
|
return VALUE_LEN_SUPPLIED;
|
|
}
|
|
else if (peek == 31)
|
|
{
|
|
/*
|
|
* A uintvar giving the length of the value follows
|
|
* "peek", and the value follows that.
|
|
*/
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Looking for uintvar octets\n");
|
|
#endif
|
|
offset++; /* Skip the uintvar indicator */
|
|
count = 0; /* Initialise count */
|
|
len = tvb_get_guintvar (tvb, offset, &count);
|
|
*valueLen = len; /* Length of value */
|
|
offset += count; /* Skip the length */
|
|
*valueOffset = offset; /* Offset of value */
|
|
offset += len; /* Skip the value */
|
|
*nextOffset = offset; /* Offset after value */
|
|
return VALUE_LEN_SUPPLIED;
|
|
}
|
|
else if (peek <= 127)
|
|
{
|
|
/*
|
|
* The value is a NUL-terminated string, and "peek"
|
|
* is the first octet of the string.
|
|
*/
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Looking for NUL-terminated string\n");
|
|
#endif
|
|
len = tvb_strsize (tvb, offset);
|
|
*valueLen = len; /* Length of value */
|
|
*valueOffset = offset; /* Offset of value */
|
|
offset += len; /* Skip the value */
|
|
*nextOffset = offset; /* Offset after value */
|
|
return VALUE_IS_TEXT_STRING;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* "peek", with the 8th bit stripped off, is the value.
|
|
*/
|
|
#ifdef DEBUG
|
|
fprintf (stderr, "dissect_wsp: Value is %d\n", (peek & 0x7F));
|
|
#endif
|
|
*valueLen = peek & 0x7F; /* Return the value itself */
|
|
*valueOffset = offset; /* Offset of value */
|
|
offset++; /* Skip the value */
|
|
*nextOffset = offset; /* Offset after value */
|
|
return VALUE_IN_LEN;
|
|
}
|
|
}
|
|
|
|
static guint
|
|
get_uintvar (tvbuff_t *tvb, guint offset, guint offsetEnd)
|
|
{
|
|
guint value = 0;
|
|
guint octet;
|
|
|
|
do
|
|
{
|
|
octet = tvb_get_guint8 (tvb, offset);
|
|
offset++;
|
|
value <<= 7;
|
|
value += octet & 0x7f;
|
|
}
|
|
while ((offsetEnd > offset) && (octet & 0x80));
|
|
return value;
|
|
}
|
|
|
|
static void
|
|
add_content_type_value (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerOffset, int headerLen, tvbuff_t *value_buff,
|
|
value_type_t valueType, int valueLen, int hf_numeric, int hf_string,
|
|
guint *contentTypep, const char **contentTypeStrp)
|
|
{
|
|
proto_item *ti;
|
|
proto_tree *parameter_tree;
|
|
const char *contentTypeStr;
|
|
int offset;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value;
|
|
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Constrained-media (Short-Integer).
|
|
*/
|
|
proto_tree_add_uint (tree, hf_numeric,
|
|
header_buff, headerOffset, headerLen,
|
|
valueLen); /* valueLen is the value */
|
|
|
|
/*
|
|
* Return the numerical value, and a null string value
|
|
* indicating that the value is numerical.
|
|
*/
|
|
*contentTypep = valueLen;
|
|
*contentTypeStrp = NULL;
|
|
return;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Constrained-media (text, i.e. Extension-Media).
|
|
*/
|
|
contentTypeStr = tvb_get_ptr (value_buff, 0, valueLen);
|
|
proto_tree_add_string (tree, hf_string,
|
|
header_buff, headerOffset, headerLen,
|
|
contentTypeStr);
|
|
|
|
/*
|
|
* Return the string value, and set the numerical value
|
|
* to 0 (as it shouldn't be used).
|
|
*/
|
|
*contentTypep = 0;
|
|
*contentTypeStrp = contentTypeStr;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Content-general-form; Value-length, followed by Media-range,
|
|
* followed by optional Accept-parameters.
|
|
*
|
|
* Get Value-length.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, 0, &subvalueLen,
|
|
&subvalueOffset, &offset);
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Extension-Media; value is a string.
|
|
*/
|
|
contentTypeStr =
|
|
tvb_get_ptr (value_buff, subvalueOffset, subvalueLen);
|
|
ti = proto_tree_add_string (tree, hf_string, header_buff,
|
|
headerOffset, headerLen, contentTypeStr);
|
|
|
|
/*
|
|
* Return the string value, and set the numerical value
|
|
* to 0 (as it shouldn't be used).
|
|
*/
|
|
*contentTypep = 0;
|
|
*contentTypeStrp = contentTypeStr;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Well-known-media; value is an Integer.
|
|
*/
|
|
if (get_integer (value_buff, subvalueOffset, subvalueLen,
|
|
valueType, &value) < 0)
|
|
{
|
|
proto_tree_add_text (tree, header_buff,
|
|
headerOffset, headerLen,
|
|
"Invalid integer for Well-known-media");
|
|
|
|
/*
|
|
* Content type is invalid.
|
|
* Don't try to parse the rest of the value.
|
|
*/
|
|
*contentTypep = 0;
|
|
*contentTypeStrp = NULL;
|
|
return;
|
|
}
|
|
ti = proto_tree_add_uint (tree, hf_numeric,
|
|
header_buff, headerOffset, headerLen, value);
|
|
|
|
/*
|
|
* Return the numerical value, and a null string value
|
|
* indicating that the value is numerical.
|
|
*/
|
|
*contentTypep = value;
|
|
*contentTypeStrp = NULL;
|
|
}
|
|
|
|
/*
|
|
* Process the rest of the value as parameters.
|
|
*/
|
|
parameter_tree = proto_item_add_subtree(ti,
|
|
ett_content_type_parameters);
|
|
while (tvb_reported_length_remaining (value_buff, offset) > 0)
|
|
offset = add_parameter (parameter_tree, value_buff, offset);
|
|
}
|
|
|
|
guint
|
|
add_content_type (proto_tree *tree, tvbuff_t *tvb, guint offset,
|
|
guint *contentTypep, const char **contentTypeStrp)
|
|
{
|
|
int valueStart;
|
|
value_type_t valueType;
|
|
int valueTypeLen;
|
|
guint valueLen;
|
|
int valueOffset;
|
|
tvbuff_t *value_buff;
|
|
|
|
valueStart = offset;
|
|
|
|
/*
|
|
* Get the value type and length (or, if the type is VALUE_IN_LEN,
|
|
* meaning the value is a Short-integer, get the value type
|
|
* and the value itself).
|
|
*/
|
|
valueType = get_value_type_len (tvb, valueStart, &valueLen,
|
|
&valueOffset, &offset);
|
|
valueTypeLen = offset - valueStart;
|
|
|
|
/*
|
|
* Get a tvbuff for the value.
|
|
* XXX - can valueLen be 0?
|
|
* XXX - cut the actual length short so that it doesn't run
|
|
* past the actual length of tvb.
|
|
*/
|
|
if (valueType != VALUE_IN_LEN) {
|
|
value_buff = tvb_new_subset (tvb, valueOffset, valueLen,
|
|
valueLen);
|
|
} else {
|
|
/*
|
|
* XXX - when the last dissector is tvbuffified,
|
|
* so that NULL is no longer a valid tvb pointer
|
|
* value in "proto_tree_add" calls, just
|
|
* set "value_buff" to NULL.
|
|
*
|
|
* XXX - can we already do that? I.e., will that
|
|
* cause us always to crash if we mistakenly try
|
|
* to fetch the value of a VALUE_IN_LEN item?
|
|
*/
|
|
value_buff = tvb_new_subset (tvb, valueStart, 0, 0);
|
|
}
|
|
|
|
add_content_type_value (tree, tvb, valueStart, valueTypeLen, value_buff,
|
|
valueType, valueLen, hf_wsp_content_type,
|
|
hf_wsp_content_type_str, contentTypep, contentTypeStrp);
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
add_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_numeric, guint8 headerType)
|
|
{
|
|
add_integer_value_header_common (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_numeric, headerType,
|
|
vals_field_names);
|
|
}
|
|
|
|
static void
|
|
add_openwave_integer_value_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_numeric, guint8 headerType)
|
|
{
|
|
add_integer_value_header_common (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_numeric, headerType,
|
|
vals_openwave_field_names);
|
|
}
|
|
|
|
static void
|
|
add_integer_value_header_common (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_numeric, guint8 headerType,
|
|
const value_string *vals)
|
|
{
|
|
guint value;
|
|
|
|
if (get_integer (value_buff, 0, valueLen, valueType, &value) < 0)
|
|
{
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid %s integer value",
|
|
match_strval (headerType, vals));
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_uint (tree, hf_numeric,
|
|
header_buff, 0, headerLen, value);
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_string, guint8 headerType)
|
|
{
|
|
add_string_value_header_common (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_string, headerType,
|
|
vals_field_names);
|
|
}
|
|
|
|
static void
|
|
add_openwave_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_string, guint8 headerType)
|
|
{
|
|
add_string_value_header_common (tree, header_buff, headerLen,
|
|
value_buff, valueType, valueLen, hf_string, headerType,
|
|
vals_openwave_field_names);
|
|
}
|
|
|
|
static void
|
|
add_string_value_header_common (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_string, guint8 headerType,
|
|
const value_string *vals)
|
|
{
|
|
if (valueType != VALUE_IS_TEXT_STRING)
|
|
{
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid %s string value",
|
|
match_strval (headerType, vals));
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_string (tree, hf_string, header_buff,
|
|
0, headerLen, tvb_get_ptr (value_buff, 0, valueLen));
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_quoted_string_value_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_string, guint8 headerType)
|
|
{
|
|
if (valueType != VALUE_IS_TEXT_STRING)
|
|
{
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid %s quoted string value",
|
|
match_strval (headerType, vals_field_names));
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_string (tree, hf_string, header_buff,
|
|
0, headerLen, tvb_get_ptr (value_buff, 1, valueLen - 1));
|
|
}
|
|
}
|
|
|
|
/* Utility function to add a date value to the protocol tree */
|
|
static void
|
|
add_date_value_header (proto_tree *tree, tvbuff_t *header_buff,
|
|
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
|
|
int valueLen, int hf_time, guint8 headerType)
|
|
{
|
|
guint secs;
|
|
nstime_t timeValue;
|
|
|
|
/* Attempt to get the date value from the buffer */
|
|
if (get_integer (value_buff, 0, valueLen, valueType, &secs) == 0)
|
|
{
|
|
/*
|
|
* Fill in the "struct timeval", and add it to the
|
|
* protocol tree.
|
|
* Note: this will succeed even if it's a Short-integer.
|
|
* A Short-integer would work, but, as the time values
|
|
* are UNIX seconds-since-the-Epoch value, and as
|
|
* there weren't WAP phones or Web servers back in
|
|
* late 1969/early 1970, they're unlikely to be used.
|
|
*/
|
|
timeValue.secs = secs;
|
|
timeValue.nsecs = 0;
|
|
proto_tree_add_time (tree, hf_time, header_buff, 0,
|
|
headerLen, &timeValue);
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_text (tree, header_buff, 0, headerLen,
|
|
"Invalid %s date value",
|
|
match_strval (headerType, vals_field_names));
|
|
}
|
|
}
|
|
|
|
static int
|
|
add_parameter (proto_tree *tree, tvbuff_t *value_buff, int offset)
|
|
{
|
|
int startOffset;
|
|
value_type_t valueType;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value;
|
|
|
|
startOffset = offset;
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Untyped-parameter.
|
|
*/
|
|
offset = add_untyped_parameter (tree, value_buff, startOffset, offset);
|
|
return offset;
|
|
}
|
|
|
|
/*
|
|
* Well-known-parameter-token.
|
|
*/
|
|
if (get_integer (value_buff, subvalueOffset,
|
|
subvalueLen, valueType, &value) < 0)
|
|
{
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset,
|
|
"Invalid Well-known-parameter-token");
|
|
return offset;
|
|
}
|
|
|
|
switch (value) {
|
|
|
|
case 0x01: /* Charset */
|
|
offset = add_parameter_charset (tree, value_buff, startOffset, offset);
|
|
break;
|
|
|
|
case 0x03: /* Type */
|
|
offset = add_parameter_type (tree, value_buff, startOffset, offset);
|
|
break;
|
|
|
|
case 0x05: /* Name */
|
|
offset = add_parameter_text (tree, value_buff, startOffset, offset,
|
|
hf_wsp_parameter_name, "Name");
|
|
break;
|
|
|
|
case 0x06: /* Filename */
|
|
offset = add_parameter_text (tree, value_buff, startOffset, offset,
|
|
hf_wsp_parameter_filename, "Filename");
|
|
break;
|
|
|
|
case 0x09: /* Type (special) */
|
|
offset = add_constrained_encoding(tree, value_buff, startOffset, offset);
|
|
break;
|
|
|
|
case 0x0A: /* Start */
|
|
offset = add_parameter_text (tree, value_buff, startOffset, offset,
|
|
hf_wsp_parameter_start, "Start");
|
|
break;
|
|
|
|
case 0x0B: /* Start-info */
|
|
offset = add_parameter_text (tree, value_buff, startOffset, offset,
|
|
hf_wsp_parameter_start_info, "Start-info");
|
|
break;
|
|
|
|
case 0x0C: /* Comment */
|
|
offset = add_parameter_text (tree, value_buff, startOffset, offset,
|
|
hf_wsp_parameter_comment, "Comment");
|
|
break;
|
|
|
|
case 0x0D: /* Domain */
|
|
offset = add_parameter_text (tree, value_buff, startOffset, offset,
|
|
hf_wsp_parameter_domain, "Domain");
|
|
break;
|
|
|
|
case 0x0F: /* Path */
|
|
offset = add_parameter_text (tree, value_buff, startOffset, offset,
|
|
hf_wsp_parameter_path, "Path");
|
|
break;
|
|
|
|
case 0x00: /* Q */
|
|
case 0x02: /* Level */
|
|
case 0x07: /* Differences */
|
|
case 0x08: /* Padding */
|
|
case 0x0E: /* Max-Age */
|
|
case 0x10: /* Secure */
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
add_untyped_parameter (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
|
|
int offset)
|
|
{
|
|
const guint8 *token;
|
|
value_type_t valueType;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value;
|
|
int vOffset = offset;
|
|
|
|
token = tvb_get_ptr (value_buff, startOffset, offset - startOffset);
|
|
/*
|
|
* Now an Untyped-value; either an Integer-value or a Text-value.
|
|
*/
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Text-value.
|
|
*/
|
|
if ((offset - vOffset) == 1) {
|
|
/*
|
|
* No-value. (stringSize includes the terminating
|
|
* null byte, so an empty string has a size of 1.)
|
|
*/
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset,
|
|
"%s", token);
|
|
return offset;
|
|
}
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset,
|
|
"%s: %s", token,
|
|
tvb_get_ptr (value_buff, vOffset, offset - vOffset));
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Integer-value.
|
|
*/
|
|
if (get_integer (value_buff, subvalueOffset, subvalueLen,
|
|
valueType, &value) == 0)
|
|
{
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset,
|
|
"%s: %u", token, value);
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset,
|
|
"%s: Invalid Integer-value", token);
|
|
}
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
add_parameter_charset (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
|
|
int offset)
|
|
{
|
|
value_type_t valueType;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value;
|
|
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Integer-value.
|
|
*/
|
|
proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
|
|
value_buff, startOffset, offset - startOffset,
|
|
subvalueLen); /* subvalueLen is the value */
|
|
return offset;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* Invalid.
|
|
*/
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset, "Invalid Well-known charset");
|
|
return offset;
|
|
}
|
|
|
|
/*
|
|
* First byte had the 8th bit set.
|
|
*/
|
|
if (subvalueLen == 0) {
|
|
/*
|
|
* Any-charset.
|
|
* XXX - add this as a field?
|
|
*/
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset- startOffset, "*");
|
|
return offset;
|
|
}
|
|
|
|
if (get_integer(value_buff, subvalueOffset, subvalueLen,
|
|
valueType, &value) == -1) {
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset, "Length %u not handled in Well-known charset",
|
|
subvalueLen);
|
|
} else {
|
|
proto_tree_add_uint (tree, hf_wsp_parameter_well_known_charset,
|
|
value_buff, startOffset, offset - startOffset, value);
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
add_constrained_encoding (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
|
|
int offset)
|
|
{
|
|
value_type_t valueType;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value;
|
|
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (valueType == VALUE_IN_LEN)
|
|
{
|
|
/*
|
|
* Integer-value, invalid
|
|
*/
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset, "Invalid multipart type parameter");
|
|
return offset;
|
|
}
|
|
if (valueType == VALUE_IS_TEXT_STRING)
|
|
{
|
|
/*
|
|
* type-label.
|
|
*/
|
|
proto_tree_add_string (tree, hf_wsp_parameter_upart_type,
|
|
value_buff, startOffset, offset - startOffset,
|
|
tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
|
|
return offset;
|
|
}
|
|
/*
|
|
* First byte had the 8th bit set.
|
|
*/
|
|
get_integer(value_buff, subvalueOffset, subvalueLen, valueType, &value);
|
|
proto_tree_add_uint (tree, hf_wsp_parameter_upart_type_value,
|
|
value_buff, startOffset, offset - startOffset, value);
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
add_parameter_type (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
|
|
int offset)
|
|
{
|
|
value_type_t valueType;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
guint value;
|
|
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (get_integer(value_buff, subvalueOffset, subvalueLen,
|
|
valueType, &value) == -1) {
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset, "Invalid type");
|
|
} else {
|
|
proto_tree_add_uint (tree, hf_wsp_parameter_type, value_buff,
|
|
startOffset, offset - startOffset, value);
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
static int
|
|
add_parameter_text (proto_tree *tree, tvbuff_t *value_buff, int startOffset,
|
|
int offset, int hf_string, const char *paramName)
|
|
{
|
|
value_type_t valueType;
|
|
int subvalueLen;
|
|
int subvalueOffset;
|
|
|
|
valueType = get_value_type_len (value_buff, offset,
|
|
&subvalueLen, &subvalueOffset, &offset);
|
|
if (valueType != VALUE_IS_TEXT_STRING) {
|
|
proto_tree_add_text (tree, value_buff, startOffset,
|
|
offset - startOffset, "Invalid %s", paramName);
|
|
} else {
|
|
proto_tree_add_string (tree, hf_string, value_buff,
|
|
startOffset, offset - startOffset,
|
|
tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
static void
|
|
add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType,
|
|
const char *contentTypeStr)
|
|
{
|
|
guint offset = 0;
|
|
guint variableStart = 0;
|
|
guint variableEnd = 0;
|
|
guint valueStart = 0;
|
|
guint valueEnd = 0;
|
|
guint8 peek = 0;
|
|
proto_item *ti;
|
|
|
|
/* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian); */
|
|
ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian);
|
|
|
|
if (contentTypeStr == NULL && contentType == 0x12)
|
|
{
|
|
/*
|
|
* URL Encoded data.
|
|
* Iterate through post data.
|
|
*/
|
|
for (offset = 0; offset < tvb_reported_length (tvb); offset++)
|
|
{
|
|
peek = tvb_get_guint8 (tvb, offset);
|
|
if (peek == '=')
|
|
{
|
|
variableEnd = offset;
|
|
valueStart = offset+1;
|
|
}
|
|
else if (peek == '&')
|
|
{
|
|
if (variableEnd > 0)
|
|
{
|
|
add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
|
|
}
|
|
variableStart = offset+1;
|
|
variableEnd = 0;
|
|
valueStart = 0;
|
|
valueEnd = 0;
|
|
}
|
|
}
|
|
|
|
/* See if there's outstanding data */
|
|
if (variableEnd > 0)
|
|
{
|
|
add_post_variable (ti, tvb, variableStart, variableEnd, valueStart, offset);
|
|
}
|
|
}
|
|
else if ((contentType == 0x22) || (contentType == 0x23) || (contentType == 0x23) || (contentType == 0x24) ||
|
|
(contentType == 0x25) || (contentType == 0x26) || (contentType == 0x33))
|
|
{
|
|
add_multipart_data(ti, tvb);
|
|
}
|
|
}
|
|
|
|
static void
|
|
add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
|
|
{
|
|
int variableLength = variableEnd-variableStart;
|
|
int valueLength = 0;
|
|
char *variableBuffer;
|
|
char *valueBuffer;
|
|
|
|
variableBuffer = g_malloc (variableLength+1);
|
|
strncpy (variableBuffer, tvb_get_ptr (tvb, variableStart, variableLength), variableLength);
|
|
variableBuffer[variableLength] = 0;
|
|
|
|
if (valueEnd < valueStart)
|
|
{
|
|
valueBuffer = g_malloc (1);
|
|
valueBuffer[0] = 0;
|
|
valueEnd = valueStart;
|
|
}
|
|
else
|
|
{
|
|
valueLength = valueEnd-valueStart;
|
|
valueBuffer = g_malloc (valueLength+1);
|
|
strncpy (valueBuffer, tvb_get_ptr (tvb, valueStart, valueLength), valueLength);
|
|
valueBuffer[valueLength] = 0;
|
|
}
|
|
|
|
/* Check for variables with no value */
|
|
if (valueStart >= tvb_reported_length (tvb))
|
|
{
|
|
valueStart = tvb_reported_length (tvb);
|
|
valueEnd = valueStart;
|
|
}
|
|
valueLength = valueEnd-valueStart;
|
|
|
|
proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
|
|
|
|
g_free (variableBuffer);
|
|
g_free (valueBuffer);
|
|
}
|
|
|
|
void
|
|
add_multipart_data (proto_tree *tree, tvbuff_t *tvb)
|
|
{
|
|
int offset = 0;
|
|
guint nextOffset;
|
|
guint nEntries = 0;
|
|
guint count;
|
|
guint HeadersLen;
|
|
guint DataLen;
|
|
guint contentType = 0;
|
|
const char *contentTypeStr;
|
|
tvbuff_t *tmp_tvb;
|
|
int partnr = 1;
|
|
int part_start;
|
|
|
|
proto_item *sub_tree = NULL,
|
|
*ti;
|
|
proto_tree *mpart_tree;
|
|
|
|
nEntries = tvb_get_guintvar (tvb, offset, &count);
|
|
offset += count;
|
|
if (nEntries)
|
|
{
|
|
sub_tree = proto_tree_add_text(tree, tvb, offset - count, 0,
|
|
"Multipart body");
|
|
proto_item_add_subtree(sub_tree, ett_mpartlist);
|
|
}
|
|
while (nEntries--)
|
|
{
|
|
part_start = offset;
|
|
HeadersLen = tvb_get_guintvar (tvb, offset, &count);
|
|
offset += count;
|
|
DataLen = tvb_get_guintvar (tvb, offset, &count);
|
|
offset += count;
|
|
ti = proto_tree_add_uint(sub_tree, hf_wsp_mpart, tvb, part_start,
|
|
HeadersLen + DataLen + (offset - part_start), partnr);
|
|
mpart_tree = proto_item_add_subtree(ti, ett_multiparts);
|
|
nextOffset = add_content_type (mpart_tree, tvb, offset, &contentType, &contentTypeStr);
|
|
HeadersLen -= (nextOffset - offset);
|
|
if (HeadersLen > 0)
|
|
{
|
|
tmp_tvb = tvb_new_subset (tvb, nextOffset, HeadersLen, HeadersLen);
|
|
add_headers (mpart_tree, tmp_tvb);
|
|
}
|
|
offset = nextOffset + HeadersLen;
|
|
proto_tree_add_item (mpart_tree, hf_wsp_multipart_data, tvb, offset, DataLen, bo_little_endian);
|
|
offset += DataLen;
|
|
partnr++;
|
|
}
|
|
}
|
|
|
|
static gint
|
|
get_integer (tvbuff_t *tvb, guint offset, guint valueLength,
|
|
value_type_t valueType, guint *value)
|
|
{
|
|
if (valueType == VALUE_IS_TEXT_STRING) {
|
|
/*
|
|
* Not valid.
|
|
*/
|
|
return -1;
|
|
}
|
|
|
|
if (valueType == VALUE_IN_LEN) {
|
|
/*
|
|
* Short-integer.
|
|
*/
|
|
*value = valueLength;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Long-integer.
|
|
*/
|
|
switch (valueLength)
|
|
{
|
|
case 1:
|
|
*value = tvb_get_guint8(tvb, offset);
|
|
break;
|
|
case 2:
|
|
*value = tvb_get_ntohs(tvb, offset);
|
|
break;
|
|
case 3:
|
|
*value = tvb_get_ntoh24(tvb, offset);
|
|
break;
|
|
case 4:
|
|
*value = tvb_get_ntohl(tvb, offset);
|
|
break;
|
|
default:
|
|
/* TODO: Need to read peek octets */
|
|
*value = 0;
|
|
fprintf (stderr, "dissect_wsp: get_integer size %u NYI\n", valueLength);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Register the protocol with Ethereal */
|
|
void
|
|
proto_register_wsp(void)
|
|
{
|
|
|
|
/* Setup list of header fields */
|
|
static hf_register_info hf[] = {
|
|
{ &hf_wsp_header_tid,
|
|
{ "Transmission ID",
|
|
"wsp.TID",
|
|
FT_UINT8, BASE_HEX, NULL, 0x00,
|
|
"Transmission ID", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_pdu_type,
|
|
{ "PDU Type",
|
|
"wsp.pdu_type",
|
|
FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
|
|
"PDU Type", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_version_major,
|
|
{ "Version (Major)",
|
|
"wsp.version.major",
|
|
FT_UINT8, BASE_DEC, NULL, 0xF0,
|
|
"Version (Major)", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_version_minor,
|
|
{ "Version (Minor)",
|
|
"wsp.version.minor",
|
|
FT_UINT8, BASE_DEC, NULL, 0x0F,
|
|
"Version (Minor)", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capability_length,
|
|
{ "Capability Length",
|
|
"wsp.capability.length",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Capability Length", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_length,
|
|
{ "Headers Length",
|
|
"wsp.headers_length",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Headers Length", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_section,
|
|
{ "Capabilities",
|
|
"wsp.capabilities",
|
|
FT_NONE, BASE_DEC, NULL, 0x00,
|
|
"Capabilities", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_headers_section,
|
|
{ "Headers",
|
|
"wsp.headers",
|
|
FT_NONE, BASE_DEC, NULL, 0x00,
|
|
"Headers", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header,
|
|
{ "Header",
|
|
"wsp.headers.header",
|
|
FT_NONE, BASE_DEC, NULL, 0x00,
|
|
"Header", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_uri_len,
|
|
{ "URI Length",
|
|
"wsp.uri_length",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"URI Length", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_uri,
|
|
{ "URI",
|
|
"wsp.uri",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"URI", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_server_session_id,
|
|
{ "Server Session ID",
|
|
"wsp.server.session_id",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Server Session ID", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_status,
|
|
{ "Status",
|
|
"wsp.reply.status",
|
|
FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
|
|
"Status", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_content_type,
|
|
{ "Content Type",
|
|
"wsp.content_type.type",
|
|
FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
|
|
"Content Type", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_content_type_str,
|
|
{ "Content Type",
|
|
"wsp.content_type.type.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Content Type", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_well_known_charset,
|
|
{ "Charset",
|
|
"wsp.content_type.parameter.charset",
|
|
FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
|
|
"Charset", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_type,
|
|
{ "Type",
|
|
"wsp.content_type.parameter.type",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Type", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_name,
|
|
{ "Name",
|
|
"wsp.content_type.parameter.name",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Name", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_filename,
|
|
{ "Filename",
|
|
"wsp.content_type.parameter.filename",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Filename", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_start,
|
|
{ "Start",
|
|
"wsp.content_type.parameter.start",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Start", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_start_info,
|
|
{ "Start-info",
|
|
"wsp.content_type.parameter.start_info",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Start-info", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_comment,
|
|
{ "Comment",
|
|
"wsp.content_type.parameter.comment",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Comment", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_domain,
|
|
{ "Domain",
|
|
"wsp.content_type.parameter.domain",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Domain", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_path,
|
|
{ "Path",
|
|
"wsp.content_type.parameter.path",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Path", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_upart_type,
|
|
{ "Type",
|
|
"wsp.content_type.parameter.upart.type",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Multipart type", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_parameter_upart_type_value,
|
|
{ "Type",
|
|
"wsp.content_type.parameter.upart.type.int",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Multipart type (int value)", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_reply_data,
|
|
{ "Data",
|
|
"wsp.reply.data",
|
|
FT_NONE, BASE_NONE, NULL, 0x00,
|
|
"Data", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_shift_code,
|
|
{ "Shift code",
|
|
"wsp.header.shift",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_UINT8, BASE_HEX, NULL, 0x00,
|
|
"Shift code", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept,
|
|
{ "Accept",
|
|
"wsp.header.accept",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_UINT8, BASE_HEX, VALS ( vals_content_types ), 0x00,
|
|
"Accept", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_str,
|
|
{ "Accept",
|
|
"wsp.header.accept.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Accept", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_application,
|
|
{ "Accept-Application",
|
|
"wsp.header.accept_application",
|
|
FT_UINT32, BASE_HEX, NULL, 0x00,
|
|
"Accept-Application", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_application_str,
|
|
{ "Accept-Application",
|
|
"wsp.header.accept_application.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Accept-Application", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_charset,
|
|
{ "Accept-Charset",
|
|
"wsp.header.accept_charset",
|
|
FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
|
|
"Accept-Charset", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_charset_str,
|
|
{ "Accept-Charset",
|
|
"wsp.header.accept_charset.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Accept-Charset", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_language,
|
|
{ "Accept-Language",
|
|
"wsp.header.accept_language",
|
|
FT_UINT8, BASE_HEX, VALS ( vals_languages ), 0x00,
|
|
"Accept-Language", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_language_str,
|
|
{ "Accept-Language",
|
|
"wsp.header.accept_language.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Accept-Language", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_ranges,
|
|
{ "Accept-Ranges",
|
|
"wsp.header.accept_ranges",
|
|
FT_UINT8, BASE_HEX, VALS ( vals_accept_ranges ), 0x00,
|
|
"Accept-Ranges", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_accept_ranges_str,
|
|
{ "Accept-Ranges",
|
|
"wsp.header.accept_ranges.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Accept-Ranges", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_age,
|
|
{ "Age",
|
|
"wsp.header.age",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Age", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_push_addr,
|
|
{ "x-up-proxy-push-addr",
|
|
"wsp.header.x-up-proxy-push-addr",
|
|
FT_BYTES, BASE_HEX, NULL, 0x00,
|
|
"The network address and port number that the handset can receive UPNOTIFY pushes on.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_push_accept,
|
|
{ "x-up-proxy-push-accept",
|
|
"wsp.header.x-up-proxy-push-accept",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"The content types that the handset can handle when sent via UPNOTIFY pushes.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_push_seq,
|
|
{ "x-up-proxy-push-seq",
|
|
"wsp.header.x-up-proxy-push-seq",
|
|
FT_UINT16, BASE_DEC, NULL, 0x00,
|
|
"Specifies the sequence number of the last UPNOTIFY push sent.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_notify,
|
|
{ "x-up-proxy-notify",
|
|
"wsp.header.x-up-proxy-notify",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates to the handset that there are pending UPNOTIFY pushes waiting.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_operator_domain,
|
|
{ "x-up-proxy-operator-domain",
|
|
"wsp.header.x-up-proxy-operator-domain",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Indicates the Trusted Provisioning Domain.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_home_page,
|
|
{ "x-up-proxy-home-page",
|
|
"wsp.header.x-up-proxy-home-page",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Specifies the server-assigned home page URL.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_has_color,
|
|
{ "x-up-devcap-has-color",
|
|
"wsp.header.x-up-devcap-has-color",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates if the handset supports colour.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_num_softkeys,
|
|
{ "x-up-devcap-num-softkeys",
|
|
"wsp.header.x-up-devcap-num-softkeys",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"The number of softkeys that can be displayed on the handset.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_softkey_size,
|
|
{ "x-up-devcap-softkey-size",
|
|
"wsp.header.x-up-devcap-softkey-size",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"The number of chars that can be displayed on a softkey label.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_screen_chars,
|
|
{ "x-up-devcap-screen-chars",
|
|
"wsp.header.x-up-devcap-screen-chars",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"The height and width of the handset's display in characters.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_screen_pixels,
|
|
{ "x-up-devcap-screen-pixels",
|
|
"wsp.header.x-up-devcap-screen-pixels",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"The height and width of the handset's display in pixels.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_em_size,
|
|
{ "x-up-devcap-em-size",
|
|
"wsp.header.x-up-devcap-em-size",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"The height and width of an uppercase M in pixels in a handset.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_screen_depth,
|
|
{ "x-up-devcap-screen-depth",
|
|
"wsp.header.x-up-devcap-screen-depth",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"The colour/gray depth of the display in bits.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_immed_alert,
|
|
{ "x-up-devcap-immed-alert",
|
|
"wsp.header.x-up-devcap-immed-alert",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates if the handset has support for immediate UPNOTIFY alerts.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_net_ask,
|
|
{ "x-up-proxy-net-ask",
|
|
"wsp.header.x-up-proxy-net-ask",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates to browser if circuit switched call is allowed without user interaction", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_uplink_version,
|
|
{ "x-up-proxy-uplink-version",
|
|
"wsp.header.x-up-proxy-uplink-version",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Version of the MAG WAP gateway", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_tod,
|
|
{ "x-up-proxy-tod",
|
|
"wsp.header.x-up-proxy-tod",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Time of day", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_ba_enable,
|
|
{ "x-up-proxy-ba-enable",
|
|
"wsp.header.x-up-proxy-ba-enable",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates if the WAP gateway should cache basic authentication details on behalf of the handset", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_ba_realm,
|
|
{ "x-up-proxy-ba-realm",
|
|
"wsp.header.x-up-proxy-ba-realm",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Indicates the realm within which basic authentication credentials apply", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_redirect_enable,
|
|
{ "x-up-proxy-redirect-enable",
|
|
"wsp.header.x-up-proxy-redirect-enable",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates if the handset wants the WAP gateway to handle HTTP redirects on its behalf", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_request_uri,
|
|
{ "x-up-proxy-request-uri",
|
|
"wsp.header.x-up-proxy-request-uri",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Indicates to the handset that the previous request was redirected to the specified URI", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_redirect_status,
|
|
{ "x-up-proxy-redirect-status",
|
|
"wsp.header.x-up-proxy-redirect-status",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Indicates the status of a redirect performed on behalf of a handset", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_trans_charset,
|
|
{ "x-up-proxy-trans-charset",
|
|
"wsp.header.x-up-proxy-trans-charset",
|
|
FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
|
|
"For POSTs indicates the charset encoding of a document", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_trans_charset_str,
|
|
{ "x-up-proxy-trans-charset",
|
|
"wsp.header.x-up-proxy-trans-charset.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"For POSTs indicates the charset encoding of a document", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_linger,
|
|
{ "x-up-proxy-linger",
|
|
"wsp.header.x-up-proxy-linger",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates the circuit linger time in seconds", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_client_id,
|
|
{ "x-up-proxy-client-id",
|
|
"wsp.header.x-up-proxy-client-id",
|
|
FT_BYTES, BASE_DEC, NULL, 0x00,
|
|
"The ClientId of the handset", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_enable_trust,
|
|
{ "x-up-proxy-enable-trust",
|
|
"wsp.header.x-up-proxy-enable-trust",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates whether to enable Trusted Provisioning Domain", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_trust_old,
|
|
{ "x-up-proxy-trust-old",
|
|
"wsp.header.x-up-proxy-trust-old",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates if the content being returned was received from within the Trusted Provisioning Domain", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_trust,
|
|
{ "x-up-proxy-trust",
|
|
"wsp.header.x-up-proxy-trust",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates if the content being returned was received from within the Trusted Provisioning Domain", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_proxy_bookmark,
|
|
{ "x-up-proxy-bookmark",
|
|
"wsp.header.x-up-proxy-bookmark",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Specifies the URL to use for server-side bookmarks", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_openwave_devcap_gui,
|
|
{ "x-up-devcap-gui",
|
|
"wsp.header.x-up-devcap-gui",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Indicates if the handset has a GUI", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_bearer_indication,
|
|
/*
|
|
* XXX - I'm assuming that the bearer indication is
|
|
* just a bearer type.
|
|
*/
|
|
{ "Bearer-indication",
|
|
"wsp.header.bearer_indication",
|
|
FT_UINT32, BASE_HEX, VALS(vals_bearer_types), 0x00,
|
|
"Bearer-indication", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_cache_control,
|
|
{ "Cache-Control",
|
|
"wsp.header.cache_control",
|
|
FT_UINT8, BASE_HEX, VALS ( vals_cache_control ), 0x00,
|
|
"Cache-Control", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_cache_control_str,
|
|
{ "Cache-Control",
|
|
"wsp.header.cache_control.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Cache-Control", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_cache_control_field_name,
|
|
{ "Field Name",
|
|
"wsp.header.cache_control.field_name",
|
|
FT_UINT8, BASE_HEX, VALS ( vals_field_names ), 0x00,
|
|
"Cache-Control field name", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_cache_control_field_name_str,
|
|
{ "Field Name",
|
|
"wsp.header.cache_control.field_name.str",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Cache-Control field name", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_connection,
|
|
{ "Connection",
|
|
"wsp.header.connection",
|
|
FT_UINT8, BASE_HEX, VALS ( vals_connection ), 0x00,
|
|
"Connection", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_connection_str,
|
|
{ "Connection",
|
|
"wsp.header.connection_str",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Connection", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_content_length,
|
|
{ "Content-Length",
|
|
"wsp.header.content_length",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Content-Length", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_date,
|
|
{ "Date",
|
|
"wsp.header.date",
|
|
FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
|
|
"Date", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_etag,
|
|
{ "Etag",
|
|
"wsp.header.etag",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Etag", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_expires,
|
|
{ "Expires",
|
|
"wsp.header.expires",
|
|
FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
|
|
"Expires", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_last_modified,
|
|
{ "Last-Modified",
|
|
"wsp.header.last_modified",
|
|
FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
|
|
"Last-Modified", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_location,
|
|
{ "Location",
|
|
"wsp.header.location",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Location", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_if_modified_since,
|
|
{ "If-Modified-Since",
|
|
"wsp.header.if_modified_since",
|
|
FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
|
|
"If-Modified-Since", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_pragma,
|
|
{ "Pragma",
|
|
"wsp.header.pragma",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"pragma", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_profile,
|
|
{ "Profile",
|
|
"wsp.header.profile",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Profile", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_server,
|
|
{ "Server",
|
|
"wsp.header.server",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Server", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_transfer_encoding,
|
|
{ "Transfer Encoding",
|
|
"wsp.header.transfer_enc",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_UINT8, BASE_HEX, VALS ( vals_transfer_encoding ), 0x00,
|
|
"Transfer Encoding", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_transfer_encoding_str,
|
|
{ "Transfer Encoding",
|
|
"wsp.header.transfer_enc_str",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Transfer Encoding", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_user_agent,
|
|
{ "User-Agent",
|
|
"wsp.header.user_agent",
|
|
/*FT_NONE, BASE_DEC, NULL, 0x00,*/
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"User-Agent", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_via,
|
|
{ "Via",
|
|
"wsp.header.via",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Via", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_wap_application_id,
|
|
{ "X-Wap-Application-Id",
|
|
"wsp.header.wap_application_id",
|
|
FT_UINT8, BASE_HEX, NULL, 0x00,
|
|
"WAP application id", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_wap_application_id_str,
|
|
{ "X-Wap-Application-Id",
|
|
"wsp.header.wap_application_id.string",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"WAP application id", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_warning,
|
|
{ "Warning",
|
|
"wsp.header.warning",
|
|
FT_NONE, BASE_NONE, NULL, 0x00,
|
|
"Warning", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_warning_code,
|
|
{ "Warning Code",
|
|
"wsp.header.warning.code",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"Warning Code", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_warning_agent,
|
|
{ "Warning Agent",
|
|
"wsp.header.warning.agent",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Warning Agent", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_warning_text,
|
|
{ "Warning Text",
|
|
"wsp.header.warning.text",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Warning Text", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_application_header,
|
|
{ "Application Header",
|
|
"wsp.header.application_header",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Application Header", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_application_value,
|
|
{ "Application Header Value",
|
|
"wsp.header.application_header.value",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Application Header Value", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_content_ID,
|
|
{ "Content-ID",
|
|
"wsp.header.content-id",
|
|
FT_STRING, BASE_NONE, NULL, 0x00,
|
|
"Content-ID", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_header_x_wap_tod,
|
|
{ "X-WAP.TOD",
|
|
"wsp.header.x_wap_tod",
|
|
FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
|
|
"X-WAP.TOD", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_client_SDU,
|
|
{ "Client SDU",
|
|
"wsp.capabilities.client_SDU",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Client SDU", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_server_SDU,
|
|
{ "Server SDU",
|
|
"wsp.capabilities.server_SDU",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Server SDU", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_protocol_opt,
|
|
{ "Protocol Options",
|
|
"wsp.capabilities.protocol_opt",
|
|
FT_STRING, BASE_HEX, NULL, 0x00,
|
|
"Protocol Options", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_method_MOR,
|
|
{ "Method MOR",
|
|
"wsp.capabilities.method_mor",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Method MOR", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_push_MOR,
|
|
{ "Push MOR",
|
|
"wsp.capabilities.push_mor",
|
|
FT_UINT8, BASE_DEC, NULL, 0x00,
|
|
"Push MOR", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_extended_methods,
|
|
{ "Extended Methods",
|
|
"wsp.capabilities.extend_methods",
|
|
FT_STRING, BASE_HEX, NULL, 0x00,
|
|
"Extended Methods", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_header_code_pages,
|
|
{ "Header Code Pages",
|
|
"wsp.capabilities.code_pages",
|
|
FT_STRING, BASE_HEX, NULL, 0x00,
|
|
"Header Code Pages", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_capabilities_aliases,
|
|
{ "Aliases",
|
|
"wsp.capabilities.aliases",
|
|
FT_UINT8, BASE_HEX, NULL, 0x00,
|
|
"Aliases", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_post_data,
|
|
{ "Post Data",
|
|
"wsp.post.data",
|
|
FT_NONE, BASE_NONE, NULL, 0x00,
|
|
"Post Data", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_push_data,
|
|
{ "Push Data",
|
|
"wsp.push.data",
|
|
FT_NONE, BASE_NONE, NULL, 0x00,
|
|
"Push Data", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_multipart_data,
|
|
{ "Data in this part",
|
|
"wsp.multipart.data",
|
|
FT_NONE, BASE_NONE, NULL, 0x00,
|
|
"The data of 1 MIME-multipart part.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_mpart,
|
|
{ "Part",
|
|
"wsp.multipart",
|
|
FT_UINT32, BASE_DEC, NULL, 0x00,
|
|
"MIME part of multipart data.", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_flags,
|
|
{ "Flags",
|
|
"wsp.redirect_flags",
|
|
FT_UINT8, BASE_HEX, NULL, 0x00,
|
|
"Redirect Flags", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_permanent,
|
|
{ "Permanent Redirect",
|
|
"wsp.redirect_flags.permanent",
|
|
FT_BOOLEAN, 8, TFS(&yes_no_truth), PERMANENT_REDIRECT,
|
|
"Permanent Redirect", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_reuse_security_session,
|
|
{ "Reuse Security Session",
|
|
"wsp.redirect_flags.reuse_security_session",
|
|
FT_BOOLEAN, 8, TFS(&yes_no_truth), REUSE_SECURITY_SESSION,
|
|
"Permanent Redirect", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_afl,
|
|
{ "Flags/Length",
|
|
"wsp.redirect_afl",
|
|
FT_UINT8, BASE_HEX, NULL, 0x00,
|
|
"Redirect Address Flags/Length", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_afl_bearer_type_included,
|
|
{ "Bearer Type Included",
|
|
"wsp.redirect_afl.bearer_type_included",
|
|
FT_BOOLEAN, 8, TFS(&yes_no_truth), BEARER_TYPE_INCLUDED,
|
|
"Redirect Address bearer type included", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_afl_port_number_included,
|
|
{ "Port Number Included",
|
|
"wsp.redirect_afl.port_number_included",
|
|
FT_BOOLEAN, 8, TFS(&yes_no_truth), PORT_NUMBER_INCLUDED,
|
|
"Redirect Address port number included", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_afl_address_len,
|
|
{ "Address Len",
|
|
"wsp.redirect_afl.address_len",
|
|
FT_UINT8, BASE_DEC, NULL, ADDRESS_LEN,
|
|
"Redirect Address Length", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_bearer_type,
|
|
{ "Bearer Type",
|
|
"wsp.redirect_bearer_type",
|
|
FT_UINT8, BASE_HEX, VALS(vals_bearer_types), 0x0,
|
|
"Redirect Bearer Type", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_port_num,
|
|
{ "Port Number",
|
|
"wsp.redirect_port_num",
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"Redirect Port Number", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_ipv4_addr,
|
|
{ "IP Address",
|
|
"wsp.redirect_ipv4_addr",
|
|
FT_IPv4, BASE_NONE, NULL, 0x0,
|
|
"Redirect Address (IP)", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_ipv6_addr,
|
|
{ "IPv6 Address",
|
|
"wsp.redirect_ipv6_addr",
|
|
FT_IPv6, BASE_NONE, NULL, 0x0,
|
|
"Redirect Address (IPv6)", HFILL
|
|
}
|
|
},
|
|
{ &hf_wsp_redirect_addr,
|
|
{ "Address",
|
|
"wsp.redirect_addr",
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
"Redirect Address", HFILL
|
|
}
|
|
},
|
|
};
|
|
|
|
/* Setup protocol subtree array */
|
|
static gint *ett[] = {
|
|
&ett_wsp,
|
|
&ett_content_type_parameters,
|
|
&ett_header,
|
|
&ett_headers,
|
|
&ett_header_warning,
|
|
&ett_header_cache_control_parameters,
|
|
&ett_header_cache_control_field_names,
|
|
&ett_capabilities,
|
|
&ett_content_type,
|
|
&ett_redirect_flags,
|
|
&ett_redirect_afl,
|
|
&ett_multiparts,
|
|
&ett_mpartlist
|
|
};
|
|
|
|
/* Register the protocol name and description */
|
|
proto_wsp = proto_register_protocol(
|
|
"Wireless Session Protocol", /* protocol name for use by ethereal */
|
|
"WSP", /* short version of name */
|
|
"wap-wsp" /* Abbreviated protocol name, should Match IANA
|
|
< URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
|
|
*/
|
|
);
|
|
|
|
/* Required function calls to register the header fields and subtrees used */
|
|
proto_register_field_array(proto_wsp, hf, array_length(hf));
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
register_dissector("wsp-co", dissect_wsp_fromwap_co, proto_wsp);
|
|
register_dissector("wsp-cl", dissect_wsp_fromwap_cl, proto_wsp);
|
|
wsp_dissector_table = register_dissector_table("wsp.content_type.type",
|
|
"WSP content type", FT_UINT8, BASE_HEX);
|
|
register_heur_dissector_list("wsp", &heur_subdissector_list);
|
|
|
|
wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
|
|
proto_wsp);
|
|
};
|
|
|
|
void
|
|
proto_reg_handoff_wsp(void)
|
|
{
|
|
/*
|
|
* Get a handle for the WMLC dissector.
|
|
*/
|
|
wmlc_handle = find_dissector("wmlc"); /* Coming soon :) */
|
|
|
|
/*
|
|
* And get a handle for the WTP-over-UDP dissector.
|
|
*/
|
|
wtp_fromudp_handle = find_dissector("wtp-udp");
|
|
|
|
/* Only connection-less WSP has no previous handler */
|
|
dissector_add("udp.port", UDP_PORT_WSP, wsp_fromudp_handle);
|
|
dissector_add("udp.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
|
|
|
|
/* This dissector is also called from the WTP and WTLS dissectors */
|
|
}
|