wireshark/packet-wsp.c

5425 lines
156 KiB
C
Raw Normal View History

/* packet-wsp.c
*
* Routines to dissect WSP component of WAP traffic.
*
* $Id: packet-wsp.c,v 1.79 2003/10/28 17:59:29 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 NEED_SNPRINTF_H
# 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"
/* Statistics (see doc/README.tapping) */
#include "tap.h"
static int wsp_tap = -1;
/* 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_sec = HF_EMPTY;
static int hf_wsp_parameter_mac = 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_proxy_authenticate = HF_EMPTY;
static int hf_wsp_header_www_authenticate = HF_EMPTY;
static int hf_wsp_header_proxy_authorization = HF_EMPTY;
static int hf_wsp_header_proxy_authorization_scheme = HF_EMPTY;
static int hf_wsp_header_proxy_authorization_user_id = HF_EMPTY;
static int hf_wsp_header_proxy_authorization_password = HF_EMPTY;
static int hf_wsp_header_authorization = HF_EMPTY;
static int hf_wsp_header_authorization_scheme = HF_EMPTY;
static int hf_wsp_header_authorization_user_id = HF_EMPTY;
static int hf_wsp_header_authorization_password = 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;
/* Push-specific WSP headers */
static int hf_wsp_header_push_flag = HF_EMPTY;
static int hf_wsp_header_push_flag_auth = HF_EMPTY;
static int hf_wsp_header_push_flag_trust = HF_EMPTY;
static int hf_wsp_header_push_flag_last = 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_post = 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;
static gint ett_header_credentials = ETT_EMPTY;
static gint ett_push_flags = 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 WBXML dissector */
static dissector_handle_t wbxml_handle;
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) */
{ 0x50, "Extended Get Method 0"},
{ 0x51, "Extended Get Method 1"},
{ 0x52, "Extended Get Method 2"},
{ 0x53, "Extended Get Method 3"},
{ 0x54, "Extended Get Method 4"},
{ 0x55, "Extended Get Method 5"},
{ 0x56, "Extended Get Method 6"},
{ 0x57, "Extended Get Method 7"},
{ 0x58, "Extended Get Method 8"},
{ 0x59, "Extended Get Method 9"},
{ 0x5A, "Extended Get Method 10"},
{ 0x5B, "Extended Get Method 11"},
{ 0x5C, "Extended Get Method 12"},
{ 0x5D, "Extended Get Method 13"},
{ 0x5E, "Extended Get Method 14"},
{ 0x5F, "Extended Get Method 15"},
{ 0x60, "Post" },
{ 0x61, "Put" },
/* 0x62 - 0x6F Unassigned (Post PDU) */
/* 0x70 - 0x7F Extended method (Post PDU) */
{ 0x70, "Extended Post Method 0"},
{ 0x71, "Extended Post Method 1"},
{ 0x72, "Extended Post Method 2"},
{ 0x73, "Extended Post Method 3"},
{ 0x74, "Extended Post Method 4"},
{ 0x75, "Extended Post Method 5"},
{ 0x76, "Extended Post Method 6"},
{ 0x77, "Extended Post Method 7"},
{ 0x78, "Extended Post Method 8"},
{ 0x79, "Extended Post Method 9"},
{ 0x7A, "Extended Post Method 10"},
{ 0x7B, "Extended Post Method 11"},
{ 0x7C, "Extended Post Method 12"},
{ 0x7D, "Extended Post Method 13"},
{ 0x7E, "Extended Post Method 14"},
{ 0x7F, "Extended Post Method 15"},
/* 0x80 - 0xFF Reserved */
{ 0x00, NULL }
};
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 }
};
const value_string vals_wsp_reason_codes[] = {
{ 0xE0, "Protocol Error (Illegal PDU)" },
{ 0xE1, "Session disconnected" },
{ 0xE2, "Session suspended" },
{ 0xE3, "Session resumed" },
{ 0xE4, "Peer congested" },
{ 0xE5, "Session connect failed" },
{ 0xE6, "Maximum receive unit size exceeded" },
{ 0xE7, "Maximum outstanding requests exceeded" },
{ 0xE8, "Peer request" },
{ 0xE9, "Network error" },
{ 0xEA, "User request" },
{ 0xEB, "No specific cause, no retries" },
{ 0xEC, "Push message cannot be delivered" },
{ 0xED, "Push message discarded" },
{ 0xEE, "Content type cannot be processed" },
};
/*
* 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 }
};
/* Parameters and well-known encodings */
static const value_string vals_wsp_parameter_sec[] = {
{ 0x00, "NETWPIN" },
{ 0x01, "USERPIN" },
{ 0x02, "USERNETWPIN" },
{ 0x03, "USERPINMAC" },
{ 0x00, NULL }
};
/* Warning codes and mappings */
static const value_string vals_wsp_warning_code[] = {
{ 10, "110 Response is stale" },
{ 11, "111 Revalidation failed" },
{ 12, "112 Disconnected operation" },
{ 13, "113 Heuristic expiration" },
{ 14, "214 Transformation applied" },
{ 99, "199/299 Miscellaneous warning" },
{ 0, NULL }
};
static const value_string vals_wsp_warning_code_short[] = {
{ 10, "110" },
{ 11, "111" },
{ 12, "112" },
{ 13, "113" },
{ 14, "214" },
{ 99, "199/299" },
{ 0, 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"
};
static const value_string vals_false_true[] = {
{ 0, "False" },
{ 1, "True" },
{ 0, NULL },
};
enum {
WSP_PDU_RESERVED = 0x00,
WSP_PDU_CONNECT = 0x01,
WSP_PDU_CONNECTREPLY = 0x02,
WSP_PDU_REDIRECT = 0x03, /* No sample data */
WSP_PDU_REPLY = 0x04,
WSP_PDU_DISCONNECT = 0x05,
WSP_PDU_PUSH = 0x06, /* No sample data */
WSP_PDU_CONFIRMEDPUSH = 0x07, /* No sample data */
WSP_PDU_SUSPEND = 0x08, /* No sample data */
WSP_PDU_RESUME = 0x09, /* No sample data */
WSP_PDU_GET = 0x40,
WSP_PDU_OPTIONS = 0x41, /* No sample data */
WSP_PDU_HEAD = 0x42, /* No sample data */
WSP_PDU_DELETE = 0x43, /* No sample data */
WSP_PDU_TRACE = 0x44, /* No sample data */
WSP_PDU_POST = 0x60,
WSP_PDU_PUT = 0x61, /* No sample data */
};
#define VAL_STRING_SIZE 200
typedef enum {
VALUE_LEN_SUPPLIED,
VALUE_IS_TEXT_STRING,
VALUE_IN_LEN,
} value_type_t;
static dissector_table_t wsp_dissector_table;
static dissector_table_t wsp_dissector_table_text;
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_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
static void add_multipart_data (proto_tree *, tvbuff_t *);
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_credentials_value_header (proto_tree *tree,
tvbuff_t *header_buff, int headerLen, tvbuff_t *value_buff,
value_type_t valueType, int valueLen,
int hf_main, int hf_scheme, int hf_basic_user_id, int hf_basic_password);
static void add_push_flag_header (proto_tree *tree,
tvbuff_t *header_buff, int headerLen, tvbuff_t *value_buff,
value_type_t valueType, int valueLen);
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;
guint8 reply_status;
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;
gboolean found_match;
/* 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; */
wsp_info_value_t *stat_info;
stat_info = g_malloc( sizeof(wsp_info_value_t) );
stat_info->status_code = 0;
/* 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",
Remove more "CHECK_DISPLAY_AS_DATA()" calls and "pinfo->current_proto =" statements. Move the setting of the Protocol column in various dissectors before anything is fetched from the packet, and also clear the Info column at that point in those and some other dissectors, so that if an exception is thrown, the columns don't reflect the previous protocol. Don't use col_add_fstr(..., "%s", string); Use col_add_str(..., string); as it does the same thing, but doesn't drag all the heavy *printf machinery in. Fix the DDTP dissector to set the Info column regardless of whether we're building a protocol tree or not, and to set it to "Encrypted payload" if the payload is encrypted. Also fix a typo in a field name. Register the FTP data dissector as being associated with the FTP data protocol, not the FTP protocol (the removed "CHECK_DISPLAY_AS_DATA()" call checked "proto_ftp_data", and the removed "pinfo->current_proto =" line set it to "FTP-DATA", so it should be associated with "proto_ftp_data"). Make the H1 dissector check whether the frame has at least 2 bytes in it before checking the first two bytes; heuristic dissectors must not throw exceptions until they've accepted the packet as one of theirs. Use "tvb_format_text()" rather than "tvb_get_ptr()" and "format_text()" in some dissectors where the result of "tvb_get_ptr()" is used only in the "format_text()" call. In the Quake dissector, don't check whether there are at least 4 bytes in the packet - if we return, the packet won't be dissected at all (it's not as if some other dissector will get to handle it), and, if we don't return, we'll throw an exception if there aren't at least 4 bytes in the packet, so the packet will be marked as short or malformed, as appropriate. In the RIPng dissector, associate the table of strings for the command field with the command field, so that the dissector doesn't have to format the string for the protocol tree entry itself, and so that the filter construction dialog box can let you select "Request" or "Response" from a list rather than requiring you to know the values for "Request" and "Response". Make "dissect_rpc()" static, as it's called only through a heuristic dissector list. Use "col_set_str()" to set the COL_PROTOCOL column for RPC protocols; the string used is from a table provided by the dissector, and is a string constant. Don't format the Info column for WSP into a buffer and then format that buffer into the column with "%s" - "col_add_fstr()" can do the formatting for you, without having to allocate your own buffer (or run through the *printf machinery twice). Don't fetch fields from the WTP packet until you're ready to use them, so that you don't throw an exception before you even set the Protocol column or clear the Info column. Use "pinfo->destport", not "pi.destport", in the Zebra dissector when checking whether the packet is a request or reply, and do the check by comparing with "pinfo->match_port" rather than TCP_PORT_ZEBRA (so that if the dissector is ever registered on another port, it still correctly determines whether the packet is a request or reply - the Network Monitor HTTP dissector has port 80 wired into its brain, which is a bit irritating if you're trying to get it to dissect HTTP proxy traffic on port 3128 or proxy administration UI traffic on port 3132). svn path=/trunk/; revision=2931
2001-01-22 08:03:46 +00:00
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++;
/* Map extended methods to the main method now the Column info has been written;
* this way we can dissect the extended method PDUs. */
if ((pdut >= 0x50) && (pdut <= 0x5F))
pdut = WSP_PDU_GET;
else if ((pdut >= 0x70) && (pdut <= 0x7F))
pdut = WSP_PDU_POST;
switch (pdut)
{
case WSP_PDU_CONNECT:
case WSP_PDU_CONNECTREPLY:
case WSP_PDU_RESUME:
if (tree) {
if (pdut == WSP_PDU_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 != WSP_PDU_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 WSP_PDU_REDIRECT:
dissect_redirect(tvb, offset, pinfo, wsp_tree,
dissector_handle);
break;
case WSP_PDU_DISCONNECT:
case WSP_PDU_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 WSP_PDU_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 WSP_PDU_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);
offset += uriLength;
if (tree)
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);
if (tree) {
/* 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 = nextOffset+headerLength;
}
/* WSP_PDU_POST data - First check whether a subdissector exists for the content type */
if (tvb_reported_length_remaining(tvb, headerStart + count + uriLength + headersLength) > 0)
{
tmp_tvb = tvb_new_subset (tvb, headerStart + count + uriLength + headersLength, -1, -1);
/*
* Try finding a dissector for the content
* first, then fallback.
*/
if (contentTypeStr == NULL) {
/*
* Content type is numeric.
*/
found_match =
dissector_try_port(wsp_dissector_table,
contentType, tmp_tvb, pinfo, tree);
} else {
/*
* Content type is a string.
*/
found_match = dissector_try_string(wsp_dissector_table_text,
contentTypeStr, tmp_tvb, pinfo, tree);
}
if (!found_match) {
if (!dissector_try_heuristic(heur_subdissector_list,
tmp_tvb, pinfo, tree))
if (tree) /* Only display if needed */
add_post_data (wsp_tree, tmp_tvb,
contentType,
contentTypeStr);
}
}
break;
case WSP_PDU_REPLY:
count = 0; /* Initialise count */
headersLength = tvb_get_guintvar (tvb, offset+1, &count);
headerStart = offset + count + 1;
reply_status = tvb_get_guint8(tvb, offset);
if (tree)
ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,tvb,offset,1,bo_little_endian);
stat_info->status_code = (gint) tvb_get_guint8( tvb, offset);
if (check_col(pinfo->cinfo, COL_INFO))
{ /* Append status code to INFO column */
col_append_fstr(pinfo->cinfo, COL_INFO, ": \"0x%02x %s\"", reply_status,
val_to_str (reply_status, vals_status, "Unknown response status (0x%02x)"));
}
nextOffset = offset + 1 + count;
if (tree)
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);
if (tree) {
/* 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;
}
/* WSP_PDU_REPLY data - First check whether a subdissector exists for the content type */
if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
{
tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
/*
* Try finding a dissector for the content
* first, then fallback.
*/
if (contentTypeStr == NULL) {
/*
* Content type is numeric.
*/
found_match = dissector_try_port(wsp_dissector_table,
contentType, tmp_tvb, pinfo, tree);
} else {
/*
* Content type is a string.
*/
found_match = dissector_try_string(wsp_dissector_table_text,
contentTypeStr, tmp_tvb, pinfo, tree);
}
if (!found_match) {
if (!dissector_try_heuristic(heur_subdissector_list,
tmp_tvb, pinfo, tree))
if (tree) /* Only display if needed */
ti = proto_tree_add_item (wsp_tree,
hf_wsp_reply_data,
tmp_tvb, 0, -1,
bo_little_endian);
}
}
break;
case WSP_PDU_PUSH:
case WSP_PDU_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);
if (tree) {
/* 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;
}
/* WSP_PDU_PUSH data - First check whether a subdissector exists for the content type */
if (tvb_reported_length_remaining(tvb, headerStart + headersLength) > 0)
{
tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength, -1, -1);
/* Try finding a dissector for the content first, then fallback */
/*
* Try finding a dissector for the content
* first, then fallback.
*/
if (contentTypeStr == NULL) {
/*
* Content type is numeric.
*/
found_match = dissector_try_port(wsp_dissector_table,
contentType, tmp_tvb, pinfo, tree);
} else {
/*
* Content type is a string.
*/
found_match = dissector_try_string(wsp_dissector_table_text,
contentTypeStr, tmp_tvb, pinfo, tree);
}
if (!found_match) {
if (!dissector_try_heuristic(heur_subdissector_list,
tmp_tvb, pinfo, tree))
if (tree) /* Only display if needed */
ti = proto_tree_add_item (wsp_tree,
hf_wsp_push_data,
tmp_tvb, 0, -1,
bo_little_endian);
}
}
break;
}
stat_info->pdut = pdut ;
tap_queue_packet (wsp_tap, pinfo, stat_info);
}
/*
* 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);
tvb_ensure_bytes_exist(tvb, URIOffset, 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 (0x%04x)");
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 (0x%04x)");
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;
case FN_PUSH_FLAG: /* Push-Flag */
add_push_flag_header (tree, header_buff, headerLen,
value_buff, valueType, valueLen);
break;
case FN_AUTHORIZATION: /* Authorization */
add_credentials_value_header (tree, header_buff, headerLen,
value_buff, valueType, valueLen,
hf_wsp_header_authorization,
hf_wsp_header_authorization_scheme,
hf_wsp_header_authorization_user_id,
hf_wsp_header_authorization_password);
break;
case FN_PROXY_AUTHORIZATION: /* Proxy-Authorization */
add_credentials_value_header (tree, header_buff, headerLen,
value_buff, valueType, valueLen,
hf_wsp_header_proxy_authorization,
hf_wsp_header_proxy_authorization_scheme,
hf_wsp_header_proxy_authorization_user_id,
hf_wsp_header_proxy_authorization_password);
break;
case FN_WWW_AUTHENTICATE: /* WWW-Authenticate */
case FN_PROXY_AUTHENTICATE: /* Proxy-Authenticate */
default:
proto_tree_add_text (tree, header_buff, 0, headerLen,
"Undecoded 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,
"Undecoded 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,
"Undecoded 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 (valueType == VALUE_IS_TEXT_STRING)
{
proto_tree_add_text (tree, tvb, startOffset,
offset - startOffset, "%s: %s", token,
tvb_get_ptr (tvb, subvalueOffset, subvalueLen));
}
else
{
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 rather than an 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[VAL_STRING_SIZE];
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, VAL_STRING_SIZE, "%s", valMatch);
}
else
{
snprintf (valString, VAL_STRING_SIZE, "%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;
guint8 code;
/*
* 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 */
proto_item_append_text (ti, ": %s", match_strval(valueLen, vals_wsp_warning_code));
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;
}
code = subvalueLen;
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);
/* Now create the summary warning header */
proto_item_append_text (ti, ": %s %s",
val_to_str (code, vals_wsp_warning_code_short, "%u"),
tvb_get_ptr (value_buff, subvalueOffset, subvalueLen));
}
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_credentials_value_header (proto_tree *tree, tvbuff_t *header_buff,
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
int valueLen _U_ ,
int hf_main, int hf_scheme,
int hf_basic_user_id, int hf_basic_password)
{
char *s;
guint32 i, sLen;
proto_item *ti;
proto_tree *basic_tree;
ti = proto_tree_add_item (tree, hf_main, header_buff, 0, headerLen,
bo_little_endian);
if (valueType == VALUE_LEN_SUPPLIED)
{
if (tvb_get_guint8 (value_buff, 0) == 0x80)
{ /* Basic */
basic_tree = proto_item_add_subtree(ti, ett_header_credentials);
proto_tree_add_string (basic_tree, hf_scheme,
value_buff, 0, 1, "Basic" );
proto_item_append_text (ti, ": Basic");
/* Now process the Basic Cookie consisting of User-Id and Password */
i = 1;
while (tvb_get_guint8(value_buff, i))
i++; /* Count length of 1st string */
/* We reached End of String at offset = i.
* Get the user id including trailing '\0' (end - start + 1) */
s = (char *) tvb_get_ptr(value_buff, 1, i - 1 + 1);
proto_tree_add_string (basic_tree, hf_basic_user_id,
value_buff, 1, i - 1 + 1, s );
proto_item_append_text (ti, "; user-id='%s'", s);
sLen = ++i; /* Move to 1st byte of password string */
while (tvb_get_guint8(value_buff, i))
i++; /* Count length of 2nd string */
/* We reached End of String at offset = i.
* Get the password including trailing '\0' (end - start + 1) */
s = (char *) tvb_get_ptr(value_buff, sLen, i - sLen + 1);
proto_tree_add_string (basic_tree, hf_basic_password,
value_buff, sLen, i - sLen + 1, s );
proto_item_append_text (ti, "; password='%s'", s);
}
else
{ /* TODO: Authentication-scheme *Auth-param */
proto_item_append_text (ti, ": (General format not yet decoded)");
}
}
else
{
proto_item_append_text (ti, ": (Invalid header value format)");
}
return;
}
static void
add_push_flag_header (proto_tree *tree, tvbuff_t *header_buff,
int headerLen, tvbuff_t *value_buff, value_type_t valueType,
int valueLen)
{
proto_item *ti = NULL;
proto_tree *subtree = NULL;
if (valueType == VALUE_IN_LEN) {
valueLen &= 0x7F; /* Clear highest bit */
ti = proto_tree_add_uint (tree, hf_wsp_header_push_flag,
header_buff, 0, headerLen, valueLen);
subtree = proto_item_add_subtree (ti, ett_push_flags);
proto_tree_add_uint (subtree, hf_wsp_header_push_flag_auth,
value_buff, 1, 1, valueLen);
proto_tree_add_uint (subtree, hf_wsp_header_push_flag_trust,
value_buff, 1, 1, valueLen);
proto_tree_add_uint (subtree, hf_wsp_header_push_flag_last,
value_buff, 1, 1, valueLen);
if (valueLen & 0x01)
proto_item_append_text (ti, " (Initiator URI authenticated)");
if (valueLen & 0x02)
proto_item_append_text (ti, " (Content trusted)");
if (valueLen & 0x04)
proto_item_append_text (ti, " (Last push message)");
if (valueLen & 0x78)
proto_item_append_text (ti, " - Reserved flags set");
} else {
proto_tree_add_text (tree, header_buff, 0, headerLen,
"Push-Flag: (Invalid header value format)");
}
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[VAL_STRING_SIZE];
#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,VAL_STRING_SIZE-i,"%s","(Confirmed push facility) ");
if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
/*
* We've been truncated
*/
goto add_string;
}
i += ret;
}
if (value & 0x40)
{
if (i >= 200) {
/* No more room. */
goto add_string;
}
ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Push facility) ");
if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
/*
* We've been truncated
*/
goto add_string;
}
i += ret;
}
if (value & 0x20)
{
if (i >= 200) {
/* No more room. */
goto add_string;
}
ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Session resume facility) ");
if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
/*
* We've been truncated
*/
goto add_string;
}
i += ret;
}
if (value & 0x10)
{
if (i >= VAL_STRING_SIZE) {
/* No more room. */
goto add_string;
}
ret = snprintf(valString+i,VAL_STRING_SIZE-i,"%s","(Acknowledgement headers) ");
if (ret == -1 || (unsigned int) ret >= VAL_STRING_SIZE-i) {
/*
* We've been truncated
*/
goto add_string;
}
i += ret;
}
add_string:
valString[VAL_STRING_SIZE-1] = '\0';
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 == WSP_PDU_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 == WSP_PDU_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,
"Undecoded 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,
"(0x%02x - ",value);
}
else
{
ret = snprintf(valString+i,valStringSize-i,"(0x%02x) ",
value);
}
if (ret == -1 || (unsigned int) ret >= valStringSize-i) {
/*
* We've been truncated.
*/
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: /* WSP 1.1 encoding - Charset: Well-known-charset */
offset = add_parameter_charset (tree, value_buff, startOffset, offset);
break;
case 0x03: /* WSP 1.1 encoding - Type: Integer-value */
offset = add_parameter_type (tree, value_buff, startOffset, offset);
break;
case 0x05: /* WSP 1.1 encoding - Name: Text-string */
case 0x17: /* WSP 1.4 encoding - Name: Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_name, "Name");
break;
case 0x06: /* WSP 1.1 encoding - Filename: Text-string */
case 0x18: /* WSP 1.4 encoding - Filename: Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_filename, "Filename");
break;
case 0x09: /* WSP 1.2 encoding - Type (special): Constrained-encoding */
offset = add_constrained_encoding(tree, value_buff, startOffset, offset);
break;
case 0x0A: /* WSP 1.2 encoding - Start: Text-string */
case 0x19: /* WSP 1.4 encoding - Start (with multipart/related): Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_start, "Start");
break;
case 0x0B: /* WSP 1.2 encoding - Start-info: Text-string */
case 0x1A: /* WSP 1.4 encoding - Start-info (with multipart/related): Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_start_info, "Start-info");
break;
case 0x0C: /* WSP 1.3 encoding - Comment: Text-string */
case 0x1B: /* WSP 1.4 encoding - Comment: Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_comment, "Comment");
break;
case 0x0D: /* WSP 1.3 encoding - Domain: Text-string */
case 0x1C: /* WSP 1.4 encoding - Domain: Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_domain, "Domain");
break;
case 0x0F: /* WSP 1.3 encoding - Path: Text-string */
case 0x1D: /* WSP 1.4 encoding - Path: Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_path, "Path");
break;
case 0x11: /* WSP 1.4 encoding - SEC: Short-integer (OCTET) */
proto_tree_add_uint (tree, hf_wsp_parameter_sec, value_buff, startOffset, 2,
tvb_get_guint8 (value_buff, startOffset+1) & 0x7F);
offset++;
break;
case 0x12: /* WSP 1.4 encoding - MAC: Text-value */
offset = add_parameter_text (tree, value_buff, startOffset, offset,
hf_wsp_parameter_mac, "MAC");
break;
case 0x00: /* WSP 1.1 encoding - Q: Q-value */
case 0x02: /* WSP 1.1 encoding - Level: Version-value */
case 0x07: /* WSP 1.1 encoding - Differences: Field-name */
case 0x08: /* WSP 1.1 encoding - Padding: Short-integer */
case 0x0E: /* WSP 1.3 encoding - Max-Age: Delta-seconds-value */
case 0x10: /* WSP 1.3 encoding - Secure: No-value */
case 0x13: /* WSP 1.4 encoding - Creation-date: Date-value */
case 0x14: /* WSP 1.4 encoding - Modification-date: Date-value */
case 0x15: /* WSP 1.4 encoding - Read-date: Date-value */
case 0x16: /* WSP 1.4 encoding - Size: Integer-value */
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;
}
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;
proto_tree *sub_tree;
/* 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);
sub_tree = proto_item_add_subtree(ti, ett_post);
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 (sub_tree, 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 (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
}
}
else if ((contentType == 0x22) || (contentType == 0x23) || (contentType == 0x24) ||
(contentType == 0x25) || (contentType == 0x26) || (contentType == 0x33))
{
add_multipart_data(sub_tree, 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);
}
static 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,
{ "Transaction ID",
"wsp.TID",
FT_UINT8, BASE_HEX, NULL, 0x00,
"Transaction 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_sec,
{ "SEC",
"wsp.content_type.parameter.sec",
FT_UINT8, BASE_HEX, VALS (vals_wsp_parameter_sec), 0x00,
"SEC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
}
},
{ &hf_wsp_parameter_mac,
{ "MAC",
"wsp.content_type.parameter.mac",
FT_STRING, BASE_NONE, NULL, 0x00,
"MAC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", 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,
"Header code page 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_authorization,
{ "Authorization",
"wsp.header.authorization",
FT_NONE, BASE_NONE, NULL, 0x00,
"Authorization", HFILL
}
},
{ &hf_wsp_header_authorization_scheme,
{ "Authentication scheme",
"wsp.header.authorization.scheme",
FT_STRING, BASE_NONE, NULL, 0x00,
"Authorization: Authentication Scheme", HFILL
}
},
{ &hf_wsp_header_authorization_user_id,
{ "User-ID",
"wsp.header.authorization.user_id",
FT_STRING, BASE_NONE, NULL, 0x00,
"Authorization: Basic: User-ID", HFILL
}
},
{ &hf_wsp_header_authorization_password,
{ "Password",
"wsp.header.authorization.password",
FT_STRING, BASE_NONE, NULL, 0x00,
"Authorization: Basic: Password", HFILL
}
},
{ &hf_wsp_header_proxy_authorization,
{ "Proxy-Authorization",
"wsp.header.proxy_authorization",
FT_NONE, BASE_NONE, NULL, 0x00,
"Proxy-Authorization", HFILL
}
},
{ &hf_wsp_header_proxy_authorization_scheme,
{ "Authentication scheme",
"wsp.header.proxy_authorization.scheme",
FT_STRING, BASE_NONE, NULL, 0x00,
"Proxy-Authorization: Authentication Scheme", HFILL
}
},
{ &hf_wsp_header_proxy_authorization_user_id,
{ "User-Id",
"wsp.header.proxy_authorization.user_id",
FT_STRING, BASE_NONE, NULL, 0x00,
"Proxy-Authorization: Basic: User-ID", HFILL
}
},
{ &hf_wsp_header_proxy_authorization_password,
{ "Password",
"wsp.header.proxy_authorization.password",
FT_STRING, BASE_NONE, NULL, 0x00,
"Proxy-Authorization: Basic: Password", HFILL
}
},
{ &hf_wsp_header_www_authenticate,
{ "WWW-Authenticate",
"wsp.header.www-authenticate",
FT_STRING, BASE_NONE, NULL, 0x00,
"Authenticate", HFILL
}
},
{ &hf_wsp_header_proxy_authenticate,
{ "Proxy-Authenticate",
"wsp.header.proxy_authenticate",
FT_STRING, BASE_NONE, NULL, 0x00,
"Proxy-Authenticate", 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_push_flag,
{ "Push-Flag",
"wsp.header.push_flag",
FT_UINT8, BASE_HEX, NULL, 0x00,
"Push-Flag (OTA-WSP header)", HFILL
}
},
{ &hf_wsp_header_push_flag_auth,
{ "Initiator URI is authenticated",
"wsp.header.push_flag.authenticated",
FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x01,
"The X-Wap-Initiator-URI has been authenticated.", HFILL
}
},
{ &hf_wsp_header_push_flag_trust,
{ "Content is trusted",
"wsp.header.push_flag.trusted",
FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x02,
"The push content is trusted.", HFILL
}
},
{ &hf_wsp_header_push_flag_last,
{ "Last push message",
"wsp.header.push_flag.last",
FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x04,
"Indicates whether this is the last push message.", 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_UINT8, BASE_DEC, VALS (vals_wsp_warning_code), 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,
{ "Data (Post)",
"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_post,
&ett_content_type,
&ett_redirect_flags,
&ett_redirect_afl,
&ett_multiparts,
&ett_mpartlist,
&ett_header_credentials,
&ett_push_flags,
};
/* 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/ >
*/
);
wsp_tap = register_tap("wsp");
/* Init the hash table */
/* wsp_sessions = g_hash_table_new(
(GHashFunc) wsp_session_hash,
(GEqualFunc)wsp_session_equal);*/
/* 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.integer",
"WSP content type (well-known integer value)",
FT_UINT32, BASE_HEX);
wsp_dissector_table_text = register_dissector_table(
"wsp.content_type.literal",
"WSP content type (textual value)",
FT_STRING, BASE_NONE);
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 WBXML dissector.
*/
wbxml_handle = find_dissector("wbxml");
/*
* 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);
/* SMPP dissector can also carry WSP */
dissector_add("smpp.udh.port", UDP_PORT_WSP, wsp_fromudp_handle);
dissector_add("smpp.udh.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
/* This dissector is also called from the WTP and WTLS dissectors */
}