1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* packet-spdy.c 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Routines for SPDY packet disassembly 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * For now, the protocol spec can be found at 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * http://dev.chromium.org/spdy/spdy-protocol 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Copyright 2010, Google Inc. 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Eric Shienbrood <ers@google.com> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * $Id$ 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Wireshark - Network traffic analyzer 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * By Gerald Combs <gerald@wireshark.org> 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Copyright 1998 Gerald Combs 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Originally based on packet-http.c 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * This program is free software; you can redistribute it and/or 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * modify it under the terms of the GNU General Public License 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * as published by the Free Software Foundation; either version 2 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * of the License, or (at your option) any later version. 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * This program is distributed in the hope that it will be useful, 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * GNU General Public License for more details. 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * You should have received a copy of the GNU General Public License 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * along with this program; if not, write to the Free Software 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifdef HAVE_CONFIG_H 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "config.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string.h> 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <ctype.h> 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <glib.h> 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/conversation.h> 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/packet.h> 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/strutil.h> 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/base64.h> 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/emem.h> 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/stats_tree.h> 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/req_resp_hdrs.h> 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "packet-spdy.h" 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/dissectors/packet-tcp.h> 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/dissectors/packet-ssl.h> 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/prefs.h> 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/expert.h> 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/uat.h> 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define SPDY_FIN 0x01 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* The types of SPDY control frames */ 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef enum _spdy_type { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_DATA, 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_SYN_STREAM, 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_SYN_REPLY, 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_FIN_STREAM, 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_HELLO, 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_NOOP, 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_PING, 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_INVALID 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} spdy_frame_type_t; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char *frame_type_names[] = { 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "DATA", "SYN_STREAM", "SYN_REPLY", "FIN_STREAM", "HELLO", "NOOP", 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "PING", "INVALID" 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * This structure will be tied to each SPDY frame. 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Note that there may be multiple SPDY frames 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * in one packet. 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct _spdy_frame_info_t { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 stream_id; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *header_block; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint header_block_len; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint16 frame_type; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} spdy_frame_info_t; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * This structures keeps track of all the data frames 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * associated with a stream, so that they can be 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * reassembled into a single chunk. 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct _spdy_data_frame_t { 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *data; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 length; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 framenum; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} spdy_data_frame_t; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct _spdy_stream_info_t { 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_type; 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_type_parameters; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_encoding; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GSList *data_frames; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvbuff_t *assembled_data; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint num_data_frames; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} spdy_stream_info_t; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <epan/tap.h> 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int spdy_tap = -1; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int spdy_eo_tap = -1; 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int proto_spdy = -1; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_syn_stream = -1; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_syn_reply = -1; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_control_bit = -1; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_version = -1; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_type = -1; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_flags = -1; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_flags_fin = -1; 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_length = -1; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_header = -1; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_header_name = -1; 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_header_name_text = -1; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_header_value = -1; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_header_value_text = -1; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_streamid = -1; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_associated_streamid = -1; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_priority = -1; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_num_headers = -1; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int hf_spdy_num_headers_string = -1; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy = -1; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_syn_stream = -1; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_syn_reply = -1; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_fin_stream = -1; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_flags = -1; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_header = -1; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_header_name = -1; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_header_value = -1; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_spdy_encoded_entity = -1; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic dissector_handle_t data_handle; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic dissector_handle_t media_handle; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic dissector_handle_t spdy_handle; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* Stuff for generation/handling of fields for custom HTTP headers */ 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct _header_field_t { 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar* header_name; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar* header_desc; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} header_field_t; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * desegmentation of SPDY control frames 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * (when we are over TCP or another protocol providing the desegmentation API) 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_desegment_control_frames = TRUE; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * desegmentation of SPDY data frames bodies 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * (when we are over TCP or another protocol providing the desegmentation API) 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * TODO let the user filter on content-type the bodies he wants desegmented 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_desegment_data_frames = TRUE; 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_assemble_entity_bodies = TRUE; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Decompression of zlib encoded entities. 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifdef HAVE_LIBZ 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_decompress_body = TRUE; 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_decompress_headers = TRUE; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_decompress_body = FALSE; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_decompress_headers = FALSE; 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean spdy_debug = FALSE; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define TCP_PORT_DAAP 3689 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * SSDP is implemented atop HTTP (yes, it really *does* run over UDP). 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define TCP_PORT_SSDP 1900 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define UDP_PORT_SSDP 1900 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * tcp and ssl ports 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define TCP_DEFAULT_RANGE "80,8080" 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define SSL_DEFAULT_RANGE "443" 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic range_t *global_spdy_tcp_range = NULL; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic range_t *global_spdy_ssl_range = NULL; 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic range_t *spdy_tcp_range = NULL; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic range_t *spdy_ssl_range = NULL; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const value_string vals_status_code[] = { 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 100, "Continue" }, 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 101, "Switching Protocols" }, 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 102, "Processing" }, 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 199, "Informational - Others" }, 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 200, "OK"}, 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 201, "Created"}, 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 202, "Accepted"}, 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 203, "Non-authoritative Information"}, 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 204, "No Content"}, 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 205, "Reset Content"}, 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 206, "Partial Content"}, 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 207, "Multi-Status"}, 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 299, "Success - Others"}, 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 300, "Multiple Choices"}, 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 301, "Moved Permanently"}, 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 302, "Found"}, 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 303, "See Other"}, 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 304, "Not Modified"}, 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 305, "Use Proxy"}, 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 307, "Temporary Redirect"}, 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 399, "Redirection - Others"}, 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 400, "Bad Request"}, 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 401, "Unauthorized"}, 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 402, "Payment Required"}, 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 403, "Forbidden"}, 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 404, "Not Found"}, 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 405, "Method Not Allowed"}, 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 406, "Not Acceptable"}, 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 407, "Proxy Authentication Required"}, 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 408, "Request Time-out"}, 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 409, "Conflict"}, 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 410, "Gone"}, 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 411, "Length Required"}, 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 412, "Precondition Failed"}, 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 413, "Request Entity Too Large"}, 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 414, "Request-URI Too Long"}, 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 415, "Unsupported Media Type"}, 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 416, "Requested Range Not Satisfiable"}, 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 417, "Expectation Failed"}, 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 418, "I'm a teapot"}, /* RFC 2324 */ 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 422, "Unprocessable Entity"}, 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 423, "Locked"}, 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 424, "Failed Dependency"}, 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 499, "Client Error - Others"}, 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 500, "Internal Server Error"}, 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 501, "Not Implemented"}, 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 502, "Bad Gateway"}, 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 503, "Service Unavailable"}, 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 504, "Gateway Time-out"}, 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 505, "HTTP Version not supported"}, 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 507, "Insufficient Storage"}, 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 599, "Server Error - Others"}, 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 0, NULL} 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char spdy_dictionary[] = 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "-agent10010120020120220320420520630030130230330430530630740040140240340440" 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ".1statusversionurl"; 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void reset_decompressors(void) 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) printf("Should reset SPDY decompressors\n"); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic spdy_conv_t * 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochget_spdy_conversation_data(packet_info *pinfo) 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conversation_t *conversation; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_conv_t *conv_data; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int retcode; 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) { 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("\n===========================================\n\n"); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Conversation for frame #%d is %p\n", pinfo->fd->num, conversation); 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (conversation) 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf(" conv_data=%p\n", conversation_get_proto_data(conversation, proto_spdy)); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if(!conversation) /* Conversation does not exist yet - create it */ 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Retrieve information from conversation 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data = conversation_get_proto_data(conversation, proto_spdy); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if(!conv_data) { 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Setup the conversation structure itself */ 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data = se_alloc0(sizeof(spdy_conv_t)); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->streams = NULL; 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_decompress_headers) { 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->rqst_decompressor = se_alloc0(sizeof(z_stream)); 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->rply_decompressor = se_alloc0(sizeof(z_stream)); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch retcode = inflateInit(conv_data->rqst_decompressor); 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (retcode == Z_OK) 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch retcode = inflateInit(conv_data->rply_decompressor); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (retcode != Z_OK) 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("frame #%d: inflateInit() failed: %d\n", pinfo->fd->num, retcode); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else if (spdy_debug) 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("created decompressor\n"); 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->dictionary_id = adler32(0L, Z_NULL, 0); 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->dictionary_id = adler32(conv_data->dictionary_id, 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_dictionary, 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(spdy_dictionary)); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conversation_add_proto_data(conversation, proto_spdy, conv_data); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch register_postseq_cleanup_routine(reset_decompressors); 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return conv_data; 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_save_stream_info(spdy_conv_t *conv_data, 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 stream_id, 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_type, 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_type_params, 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_encoding) 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_stream_info_t *si; 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (conv_data->streams == NULL) 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->streams = g_array_new(FALSE, TRUE, sizeof(spdy_stream_info_t *)); 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_id < conv_data->streams->len) 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISSECTOR_ASSERT(g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id) == NULL); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_array_set_size(conv_data->streams, stream_id+1); 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si = se_alloc(sizeof(spdy_stream_info_t)); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->content_type = content_type; 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->content_type_parameters = content_type_params; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->content_encoding = content_encoding; 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->data_frames = NULL; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->num_data_frames = 0; 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->assembled_data = NULL; 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id) = si; 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Saved stream info for ID %u, content type %s\n", stream_id, content_type); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic spdy_stream_info_t * 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_get_stream_info(spdy_conv_t *conv_data, guint32 stream_id) 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (conv_data->streams == NULL || stream_id >= conv_data->streams->len) 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_add_data_chunk(spdy_conv_t *conv_data, guint32 stream_id, guint32 frame, 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *data, guint32 length) 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si == NULL) { 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) printf("No stream_info found for stream %d\n", stream_id); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_data_frame_t *df = g_malloc(sizeof(spdy_data_frame_t)); 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df->data = data; 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df->length = length; 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df->framenum = frame; 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->data_frames = g_slist_append(si->data_frames, df); 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++si->num_data_frames; 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Saved %u bytes of data for stream %u frame %u\n", 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length, stream_id, df->framenum); 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_increment_data_chunk_count(spdy_conv_t *conv_data, guint32 stream_id) 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si != NULL) 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++si->num_data_frames; 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Return the number of data frames saved so far for the specified stream. 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic guint 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_get_num_data_frames(spdy_conv_t *conv_data, guint32 stream_id) 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return si == NULL ? 0 : si->num_data_frames; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic spdy_stream_info_t * 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_assemble_data_frames(spdy_conv_t *conv_data, guint32 stream_id) 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id); 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvbuff_t *tvb; 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si == NULL) 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Compute the total amount of data and concatenate the 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * data chunks, if it hasn't already been done. 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si->assembled_data == NULL) { 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_data_frame_t *df; 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *data; 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 datalen; 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 offset; 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 framenum; 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GSList *dflist = si->data_frames; 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dflist == NULL) 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return si; 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dflist = si->data_frames; 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch datalen = 0; 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * I'd like to use a composite tvbuff here, but since 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * only a real-data tvbuff can be the child of another 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * tvb, I can't. It would be nice if this limitation 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * could be fixed. 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (dflist != NULL) { 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df = dflist->data; 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch datalen += df->length; 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dflist = g_slist_next(dflist); 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (datalen != 0) { 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data = se_alloc(datalen); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dflist = si->data_frames; 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset = 0; 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framenum = 0; 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (dflist != NULL) { 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df = dflist->data; 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(data+offset, df->data, df->length); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += df->length; 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dflist = g_slist_next(dflist); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb = tvb_new_real_data(data, datalen, datalen); 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->assembled_data = tvb; 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return si; 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_discard_data_frames(spdy_stream_info_t *si) 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GSList *dflist = si->data_frames; 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_data_frame_t *df; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dflist == NULL) 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (dflist != NULL) { 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df = dflist->data; 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (df->data != NULL) { 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_free(df->data); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df->data = NULL; 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dflist = g_slist_next(dflist); 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /*g_slist_free(si->data_frames); 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->data_frames = NULL; */ 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(cbentzel): tvb_child_uncompress should be exported by wireshark. 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic tvbuff_t* spdy_tvb_child_uncompress(tvbuff_t *parent _U_, tvbuff_t *tvb, 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset, int comprlen) 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_tvb) 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb_set_child_real_data_tvbuff (parent, new_tvb); 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new_tvb; 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdissect_spdy_data_frame(tvbuff_t *tvb, int offset, 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch packet_info *pinfo, 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *top_level_tree, 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *spdy_tree, 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *spdy_proto, 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_conv_t *conv_data) 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 stream_id; 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 flags; 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 frame_length; 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *ti; 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *flags_tree; 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 reported_datalen; 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 datalen; 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dissector_table_t media_type_subdissector_table; 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dissector_table_t port_subdissector_table; 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dissector_handle_t handle; 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint num_data_frames; 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gboolean dissected; 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags = tvb_get_guint8(tvb, offset+4); 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_length = tvb_get_ntoh24(tvb, offset+5); 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Data frame [stream_id=%u flags=0x%x length=%d]\n", 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id, flags, frame_length); 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_tree) proto_item_append_text(spdy_tree, ", data frame"); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_add_fstr(pinfo->cinfo, COL_INFO, "DATA[%u] length=%d", 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id, frame_length); 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(spdy_proto, ":%s stream=%d length=%d", 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags & SPDY_FIN ? " [FIN]" : "", 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id, frame_length); 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_boolean(spdy_tree, hf_spdy_control_bit, tvb, offset, 1, 0); 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(spdy_tree, hf_spdy_streamid, tvb, offset, 4, stream_id); 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_uint_format(spdy_tree, hf_spdy_flags, tvb, offset+4, 1, flags, 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Flags: 0x%02x%s", flags, flags&SPDY_FIN ? " (FIN)" : ""); 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_tree = proto_item_add_subtree(ti, ett_spdy_flags); 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_boolean(flags_tree, hf_spdy_flags_fin, tvb, offset+4, 1, flags); 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(spdy_tree, hf_spdy_length, tvb, offset+5, 3, frame_length); 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch datalen = tvb_length_remaining(tvb, offset); 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (datalen > frame_length) 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch datalen = frame_length; 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reported_datalen = tvb_reported_length_remaining(tvb, offset); 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (reported_datalen > frame_length) 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reported_datalen = frame_length; 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch num_data_frames = spdy_get_num_data_frames(conv_data, stream_id); 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (datalen != 0 || num_data_frames != 0) { 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * There's stuff left over; process it. 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvbuff_t *next_tvb = NULL; 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvbuff_t *data_tvb = NULL; 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_stream_info_t *si = NULL; 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void *save_private_data = NULL; 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *copied_data; 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gboolean private_data_changed = FALSE; 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gboolean is_single_chunk = FALSE; 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gboolean have_entire_body; 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Create a tvbuff for the payload. 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (datalen != 0) { 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_tvb = tvb_new_subset(tvb, offset+8, datalen, 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reported_datalen); 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_single_chunk = num_data_frames == 0 && (flags & SPDY_FIN) != 0; 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pinfo->fd->flags.visited) { 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!is_single_chunk) { 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_assemble_entity_bodies) { 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch copied_data = tvb_memdup(next_tvb, 0, datalen); 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_add_data_chunk(conv_data, stream_id, pinfo->fd->num, 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch copied_data, datalen); 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_increment_data_chunk_count(conv_data, stream_id); 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_single_chunk = (num_data_frames == 1); 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(flags & SPDY_FIN)) { 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_set_fence(pinfo->cinfo, COL_INFO); 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_add_fstr(pinfo->cinfo, COL_INFO, " (partial entity)"); 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(spdy_proto, " (partial entity body)"); 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* would like the proto item to say */ 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* " (entity body fragment N of M)" */ 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch goto body_dissected; 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch have_entire_body = is_single_chunk; 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * On seeing the last data frame in a stream, we can 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * reassemble the frames into one data block. 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si = spdy_assemble_data_frames(conv_data, stream_id); 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si == NULL) 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch goto body_dissected; 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_tvb = si->assembled_data; 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_assemble_entity_bodies) 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch have_entire_body = TRUE; 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!have_entire_body) 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch goto body_dissected; 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data_tvb == NULL) 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_tvb = next_tvb; 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch add_new_data_source(pinfo, data_tvb, "Assembled entity body"); 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (have_entire_body && si->content_encoding != NULL && 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_ascii_strcasecmp(si->content_encoding, "identity") != 0) { 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * We currently can't handle, for example, "compress"; 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * just handle them as data for now. 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * After July 7, 2004 the LZW patent expires, so support 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * might be added then. However, I don't think that 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * anybody ever really implemented "compress", due to 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * the aforementioned patent. 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvbuff_t *uncomp_tvb = NULL; 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *e_ti = NULL; 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *ce_ti = NULL; 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *e_tree = NULL; 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_decompress_body && 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (g_ascii_strcasecmp(si->content_encoding, "gzip") == 0 || 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_ascii_strcasecmp(si->content_encoding, "deflate") 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch == 0)) { 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uncomp_tvb = spdy_tvb_child_uncompress(tvb, data_tvb, 0, 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb_length(data_tvb)); 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Add the encoded entity to the protocol tree 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch e_ti = proto_tree_add_text(top_level_tree, data_tvb, 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0, tvb_length(data_tvb), 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Content-encoded entity body (%s): %u bytes", 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->content_encoding, 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb_length(data_tvb)); 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch e_tree = proto_item_add_subtree(e_ti, ett_spdy_encoded_entity); 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si->num_data_frames > 1) { 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GSList *dflist; 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_data_frame_t *df; 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 framenum; 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ce_ti = proto_tree_add_text(e_tree, data_tvb, 0, 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb_length(data_tvb), 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Assembled from %d frames in packet(s)", si->num_data_frames); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dflist = si->data_frames; 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framenum = 0; 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (dflist != NULL) { 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df = dflist->data; 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (framenum != df->framenum) { 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(ce_ti, " #%u", df->framenum); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framenum = df->framenum; 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dflist = g_slist_next(dflist); 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (uncomp_tvb != NULL) { 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Decompression worked 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* XXX - Don't free this, since it's possible 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * that the data was only partially 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * decompressed, such as when desegmentation 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * isn't enabled. 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb_free(next_tvb); 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(e_ti, " -> %u bytes", tvb_length(uncomp_tvb)); 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_tvb = uncomp_tvb; 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch add_new_data_source(pinfo, data_tvb, "Uncompressed entity body"); 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_decompress_body) 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(e_ti, " [Error: Decompression failed]"); 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch call_dissector(data_handle, data_tvb, pinfo, e_tree); 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch goto body_dissected; 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si != NULL) 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_discard_data_frames(si); 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Do subdissector checks. 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * First, check whether some subdissector asked that they 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * be called if something was on some particular port. 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch port_subdissector_table = find_dissector_table("http.port"); 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch media_type_subdissector_table = find_dissector_table("media_type"); 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (have_entire_body && port_subdissector_table != NULL) 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handle = dissector_get_port_handle(port_subdissector_table, 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pinfo->match_port); 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handle = NULL; 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (handle == NULL && have_entire_body && si->content_type != NULL && 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch media_type_subdissector_table != NULL) { 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * We didn't find any subdissector that 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * registered for the port, and we have a 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Content-Type value. Is there any subdissector 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * for that content type? 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch save_private_data = pinfo->private_data; 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private_data_changed = TRUE; 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (si->content_type_parameters) 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pinfo->private_data = ep_strdup(si->content_type_parameters); 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pinfo->private_data = NULL; 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Calling the string handle for the media type 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * dissector table will set pinfo->match_string 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * to si->content_type for us. 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pinfo->match_string = si->content_type; 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handle = dissector_get_string_handle( 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch media_type_subdissector_table, 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch si->content_type); 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (handle != NULL) { 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * We have a subdissector - call it. 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dissected = call_dissector(handle, data_tvb, pinfo, top_level_tree); 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dissected = FALSE; 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dissected) { 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * The subdissector dissected the body. 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Fix up the top-level item so that it doesn't 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * include the stuff for that protocol. 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ti != NULL) 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_set_len(ti, offset); 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (have_entire_body && si->content_type != NULL) { 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Calling the default media handle if there is a content-type that 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * wasn't handled above. 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch call_dissector(media_handle, next_tvb, pinfo, top_level_tree); 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Call the default data dissector */ 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch call_dissector(data_handle, next_tvb, pinfo, top_level_tree); 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbody_dissected: 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Do *not* attempt at freeing the private data; 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * it may be in use by subdissectors. 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (private_data_changed) /*restore even NULL value*/ 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pinfo->private_data = save_private_data; 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * We've processed "datalen" bytes worth of data 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * (which may be no data at all); advance the 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * offset past whatever data we've processed. 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return frame_length + 8; 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic guint8 * 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_decompress_header_block(tvbuff_t *tvb, z_streamp decomp, 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 dictionary_id, int offset, 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 length, guint *uncomp_length) 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int retcode; 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t bufsize = 16384; 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const guint8 *hptr = tvb_get_ptr(tvb, offset, length); 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *uncomp_block = ep_alloc(bufsize); 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decomp->next_in = (Bytef *)hptr; 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decomp->avail_in = length; 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decomp->next_out = uncomp_block; 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decomp->avail_out = bufsize; 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch retcode = inflate(decomp, Z_SYNC_FLUSH); 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (retcode == Z_NEED_DICT) { 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (decomp->adler != dictionary_id) { 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("decompressor wants dictionary %#x, but we have %#x\n", 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (guint)decomp->adler, dictionary_id); 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch retcode = inflateSetDictionary(decomp, 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_dictionary, 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(spdy_dictionary)); 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (retcode == Z_OK) 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch retcode = inflate(decomp, Z_SYNC_FLUSH); 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (retcode != Z_OK) { 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *uncomp_length = bufsize - decomp->avail_out; 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Inflation SUCCEEDED. uncompressed size=%d\n", *uncomp_length); 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (decomp->avail_in != 0) 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf(" but there were %d input bytes left over\n", decomp->avail_in); 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return se_memdup(uncomp_block, *uncomp_length); 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Try to determine heuristically whether the header block is 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * compressed. For an uncompressed block, the first two bytes 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * gives the number of headers. Each header name and value is 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * a two-byte length followed by ASCII characters. 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_check_header_compression(tvbuff_t *tvb, 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset, 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 frame_length) 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint16 length; 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!tvb_bytes_exist(tvb, offset, 6)) 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 1; 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length = tvb_get_ntohs(tvb, offset); 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (length > frame_length) 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 1; 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length = tvb_get_ntohs(tvb, offset+2); 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (length > frame_length) 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 1; 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) printf("Looks like the header block is not compressed\n"); 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(cbentzel): Change wireshark to export p_remove_proto_data, rather 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// than duplicating code here. 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct _spdy_frame_proto_data { 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int proto; 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void *proto_data; 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} spdy_frame_proto_data; 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint spdy_p_compare(gconstpointer a, gconstpointer b) 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const spdy_frame_proto_data *ap = (const spdy_frame_proto_data *)a; 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const spdy_frame_proto_data *bp = (const spdy_frame_proto_data *)b; 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ap -> proto > bp -> proto) 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 1; 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else if (ap -> proto == bp -> proto) 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void spdy_p_remove_proto_data(frame_data *fd, int proto) 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_frame_proto_data temp; 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GSList *item; 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch temp.proto = proto; 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch temp.proto_data = NULL; 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, spdy_p_compare); 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (item) { 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fd->pfd = g_slist_remove(fd->pfd, item->data); 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic spdy_frame_info_t * 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_save_header_block(frame_data *fd, 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 stream_id, 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint frame_type, 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *header, 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint length) 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GSList *filist = p_get_proto_data(fd, proto_spdy); 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_frame_info_t *frame_info = se_alloc(sizeof(spdy_frame_info_t)); 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (filist != NULL) 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_p_remove_proto_data(fd, proto_spdy); 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_info->stream_id = stream_id; 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_info->header_block = header; 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_info->header_block_len = length; 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_info->frame_type = frame_type; 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch filist = g_slist_append(filist, frame_info); 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch p_add_proto_data(fd, proto_spdy, filist); 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return frame_info; 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* TODO(ers) these need to get deleted when no longer needed */ 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic spdy_frame_info_t * 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_find_saved_header_block(frame_data *fd, 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 stream_id, 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint16 frame_type) 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GSList *filist = p_get_proto_data(fd, proto_spdy); 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (filist != NULL) { 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_frame_info_t *fi = filist->data; 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (fi->stream_id == stream_id && fi->frame_type == frame_type) 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return fi; 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch filist = g_slist_next(filist); 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Given a content type string that may contain optional parameters, 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * return the parameter string, if any, otherwise return NULL. This 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * also has the side effect of null terminating the content type 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * part of the original string. 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gchar * 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy_parse_content_type(gchar *content_type) 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *cp = content_type; 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (*cp != '\0' && *cp != ';' && !isspace(*cp)) { 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *cp = tolower(*cp); 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++cp; 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*cp == '\0') 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cp = NULL; 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cp != NULL) { 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *cp++ = '\0'; 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (*cp == ';' || isspace(*cp)) 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++cp; 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*cp != '\0') 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return cp; 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdissect_spdy_message(tvbuff_t *tvb, int offset, packet_info *pinfo, 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *tree, spdy_conv_t *conv_data) 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 control_bit; 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint16 version; 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint16 frame_type; 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 flags; 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 frame_length; 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 stream_id; 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 associated_stream_id; 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint priority; 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint16 num_headers; 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint32 fin_status; 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *frame_header; 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char *proto_tag; 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char *frame_type_name; 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *spdy_tree = NULL; 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *ti = NULL; 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *spdy_proto = NULL; 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int orig_offset; 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int hoffset; 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int hdr_offset = 0; 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_frame_type_t spdy_type; 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *sub_tree; 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *flags_tree; 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvbuff_t *header_tvb = NULL; 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gboolean headers_compressed; 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *hdr_verb = NULL; 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *hdr_url = NULL; 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *hdr_version = NULL; 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_type = NULL; 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_encoding = NULL; 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Minimum size for a SPDY frame is 8 bytes. 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tvb_reported_length_remaining(tvb, offset) < 8) 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tag = "SPDY"; 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (check_col(pinfo->cinfo, COL_PROTOCOL)) 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag); 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Is this a control frame or a data frame? 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch orig_offset = offset; 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch control_bit = tvb_get_bits8(tvb, offset << 3, 1); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (control_bit) { 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch version = tvb_get_bits16(tvb, (offset << 3) + 1, 15, FALSE); 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type = tvb_get_ntohs(tvb, offset+2); 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame_type >= SPDY_INVALID) { 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_header = ep_tvb_memdup(tvb, offset, 16); 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch version = 1; /* avoid gcc warning */ 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type = SPDY_DATA; 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_header = NULL; /* avoid gcc warning */ 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type_name = frame_type_names[frame_type]; 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += 4; 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags = tvb_get_guint8(tvb, offset); 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_length = tvb_get_ntoh24(tvb, offset+1); 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += 4; 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Make sure there's as much data as the frame header says there is. 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((guint)tvb_reported_length_remaining(tvb, offset) < frame_length) { 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Not enough header data: %d vs. %d\n", 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_length, tvb_reported_length_remaining(tvb, offset)); 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tree) { 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_proto = proto_tree_add_item(tree, proto_spdy, tvb, orig_offset, frame_length+8, FALSE); 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_tree = proto_item_add_subtree(spdy_proto, ett_spdy); 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (control_bit) { 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Control frame [version=%d type=%d flags=0x%x length=%d]\n", 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch version, frame_type, flags, frame_length); 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tree) proto_item_append_text(spdy_tree, ", control frame"); 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return dissect_spdy_data_frame(tvb, orig_offset, pinfo, tree, 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_tree, spdy_proto, conv_data); 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch num_headers = 0; 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sub_tree = NULL; /* avoid gcc warning */ 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (frame_type) { 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_SYN_STREAM: 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_SYN_REPLY: 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tree) { 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int hf; 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hf = frame_type == SPDY_SYN_STREAM ? hf_spdy_syn_stream : hf_spdy_syn_reply; 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_bytes(spdy_tree, hf, tvb, 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch orig_offset, 16, frame_header); 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sub_tree = proto_item_add_subtree(ti, ett_spdy_syn_stream); 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE); 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += 4; 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame_type == SPDY_SYN_STREAM) { 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch associated_stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE); 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += 4; 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch priority = tvb_get_bits8(tvb, offset << 3, 2); 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += 2; 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The next two bytes have no meaning in SYN_REPLY 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += 2; 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tree) { 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_boolean(sub_tree, hf_spdy_control_bit, tvb, orig_offset, 1, control_bit); 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(sub_tree, hf_spdy_version, tvb, orig_offset, 2, version); 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(sub_tree, hf_spdy_type, tvb, orig_offset+2, 2, frame_type); 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_uint_format(sub_tree, hf_spdy_flags, tvb, orig_offset+4, 1, flags, 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Flags: 0x%02x%s", flags, flags&SPDY_FIN ? " (FIN)" : ""); 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_tree = proto_item_add_subtree(ti, ett_spdy_flags); 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_boolean(flags_tree, hf_spdy_flags_fin, tvb, orig_offset+4, 1, flags); 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(sub_tree, hf_spdy_length, tvb, orig_offset+5, 3, frame_length); 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(sub_tree, hf_spdy_streamid, tvb, orig_offset+8, 4, stream_id); 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame_type == SPDY_SYN_STREAM) { 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(sub_tree, hf_spdy_associated_streamid, tvb, orig_offset+12, 4, associated_stream_id); 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(sub_tree, hf_spdy_priority, tvb, orig_offset+16, 1, priority); 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(spdy_proto, ": %s%s stream=%d length=%d", 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type_name, 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags & SPDY_FIN ? " [FIN]" : "", 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id, frame_length); 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf(" stream ID=%u priority=%d\n", stream_id, priority); 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_FIN_STREAM: 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE); 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fin_status = tvb_get_ntohl(tvb, offset); 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ers) fill in tree and summary 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += 8; 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_HELLO: 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ers) fill in tree and summary 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id = 0; /* avoid gcc warning */ 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id = 0; /* avoid gcc warning */ 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Process the name-value pairs one at a time, after possibly 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * decompressing the header block. 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (frame_type == SPDY_SYN_STREAM || frame_type == SPDY_SYN_REPLY) { 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers_compressed = spdy_check_header_compression(tvb, offset, frame_length); 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!spdy_decompress_headers || !headers_compressed) { 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_tvb = tvb; 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset = offset; 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_frame_info_t *per_frame_info = 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_find_saved_header_block(pinfo->fd, 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id, 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type == SPDY_SYN_REPLY); 1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (per_frame_info == NULL) { 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint uncomp_length; 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_streamp decomp = frame_type == SPDY_SYN_STREAM ? 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->rqst_decompressor : conv_data->rply_decompressor; 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 *uncomp_ptr = 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_decompress_header_block(tvb, decomp, 1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data->dictionary_id, 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset, 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_length + 8 - (offset - orig_offset), 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &uncomp_length); 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (uncomp_ptr == NULL) { /* decompression failed */ 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Frame #%d: Inflation failed\n", pinfo->fd->num); 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(spdy_proto, " [Error: Header decompression failed]"); 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Should we just bail here? 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Saving %u bytes of uncomp hdr\n", uncomp_length); 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch per_frame_info = 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_save_header_block(pinfo->fd, stream_id, frame_type == SPDY_SYN_REPLY, 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uncomp_ptr, uncomp_length); 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (spdy_debug) { 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Found uncompressed header block len %u for stream %u frame_type=%d\n", 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch per_frame_info->header_block_len, 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch per_frame_info->stream_id, 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch per_frame_info->frame_type); 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (per_frame_info != NULL) { 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_tvb = tvb_new_child_real_data(tvb, 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch per_frame_info->header_block, 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch per_frame_info->header_block_len, 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch per_frame_info->header_block_len); 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch add_new_data_source(pinfo, header_tvb, "Uncompressed headers"); 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset = 0; 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset = orig_offset + 8 + frame_length; 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch num_headers = tvb_get_ntohs(header_tvb, hdr_offset); 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset += 2; 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (header_tvb == NULL || 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (headers_compressed && !spdy_decompress_headers)) { 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch num_headers = 0; 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_string(sub_tree, hf_spdy_num_headers_string, 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb, 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type == SPDY_SYN_STREAM ? orig_offset+18 : orig_offset + 14, 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2, 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Unknown (header block is compressed)"); 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_uint(sub_tree, hf_spdy_num_headers, 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb, 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type == SPDY_SYN_STREAM ? orig_offset+18 : orig_offset +14, 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2, num_headers); 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_type = SPDY_INVALID; /* type not known yet */ 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf(" %d Headers:\n", num_headers); 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (num_headers > frame_length) { 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch printf("Number of headers is greater than frame length!\n"); 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(ti, " [Error: Number of headers is larger than frame length]"); 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]", frame_type_name, stream_id); 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return frame_length+8; 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_verb = hdr_url = hdr_version = content_type = content_encoding = NULL; 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (num_headers-- && tvb_reported_length_remaining(header_tvb, hdr_offset) != 0) { 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *header_name; 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *header_value; 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *header_tree; 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *name_tree; 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *value_tree; 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *header; 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint16 length; 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint header_length = 0; 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hoffset = hdr_offset; 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header = proto_tree_add_item(spdy_tree, hf_spdy_header, header_tvb, 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset, frame_length, FALSE); 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_tree = proto_item_add_subtree(header, ett_spdy_header); 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length = tvb_get_ntohs(header_tvb, hdr_offset); 1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset += 2; 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_name = (gchar *)tvb_get_ephemeral_string(header_tvb, hdr_offset, length); 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset += length; 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_length += hdr_offset - hoffset; 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tree) { 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_text(header_tree, header_tvb, hoffset, length+2, "Name: %s", 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_name); 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch name_tree = proto_item_add_subtree(ti, ett_spdy_header_name); 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(name_tree, hf_spdy_length, header_tvb, hoffset, 2, length); 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_string_format(name_tree, hf_spdy_header_name_text, header_tvb, hoffset+2, length, 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_name, "Text: %s", format_text(header_name, length)); 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hoffset = hdr_offset; 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length = tvb_get_ntohs(header_tvb, hdr_offset); 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset += 2; 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_value = (gchar *)tvb_get_ephemeral_string(header_tvb, hdr_offset, length); 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_offset += length; 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_length += hdr_offset - hoffset; 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tree) { 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_text(header_tree, header_tvb, hoffset, length+2, "Value: %s", 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_value); 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value_tree = proto_item_add_subtree(ti, ett_spdy_header_value); 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_uint(value_tree, hf_spdy_length, header_tvb, hoffset, 2, length); 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_string_format(value_tree, hf_spdy_header_value_text, header_tvb, hoffset+2, length, 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_value, "Text: %s", format_text(header_value, length)); 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_append_text(header, ": %s: %s", header_name, header_value); 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item_set_len(header, header_length); 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_debug) printf(" %s: %s\n", header_name, header_value); 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * TODO(ers) check that the header name contains only legal characters. 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (g_ascii_strcasecmp(header_name, "method") == 0 || 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_ascii_strcasecmp(header_name, "status") == 0) { 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_verb = header_value; 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (g_ascii_strcasecmp(header_name, "url") == 0) { 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_url = header_value; 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (g_ascii_strcasecmp(header_name, "version") == 0) { 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hdr_version = header_value; 1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (g_ascii_strcasecmp(header_name, "content-type") == 0) { 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_type = se_strdup(header_value); 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (g_ascii_strcasecmp(header_name, "content-encoding") == 0) { 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_encoding = se_strdup(header_value); 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (hdr_version != NULL) { 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (hdr_url != NULL) { 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: %s %s %s", 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type_name, stream_id, hdr_verb, hdr_url, hdr_version); 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: %s %s", 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame_type_name, stream_id, hdr_verb, hdr_version); 1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]", frame_type_name, stream_id); 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * If we expect data on this stream, we need to remember the content 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * type and content encoding. 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (content_type != NULL && !pinfo->fd->flags.visited) { 1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gchar *content_type_params = spdy_parse_content_type(content_type); 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_save_stream_info(conv_data, stream_id, content_type, 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch content_type_params, content_encoding); 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return offset - orig_offset; 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdissect_spdy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_conv_t *conv_data; 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset = 0; 1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int len; 1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int firstpkt = 1; 1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 1254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * The first byte of a SPDY packet must be either 0 or 1255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 0x80. If it's not, assume that this is not SPDY. 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * (In theory, a data frame could have a stream ID 1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * >= 2^24, in which case it won't have 0 for a first 1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * byte, but this is a pretty reliable heuristic for 1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * now.) 1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch guint8 first_byte = tvb_get_guint8(tvb, 0); 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (first_byte != 0x80 && first_byte != 0x0) 1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch conv_data = get_spdy_conversation_data(pinfo); 1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (tvb_reported_length_remaining(tvb, offset) != 0) { 1268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!firstpkt) { 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_add_fstr(pinfo->cinfo, COL_INFO, " >> "); 1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_set_fence(pinfo->cinfo, COL_INFO); 1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch len = dissect_spdy_message(tvb, offset, pinfo, tree, conv_data); 1273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (len <= 0) 1274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset += len; 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * OK, we've set the Protocol and Info columns for the 1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * first SPDY message; set a fence so that subsequent 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * SPDY messages don't overwrite the Info column. 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_set_fence(pinfo->cinfo, COL_INFO); 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch firstpkt = 0; 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 1; 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gboolean 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdissect_spdy_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!value_is_in_range(global_spdy_tcp_range, pinfo->destport) && 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !value_is_in_range(global_spdy_tcp_range, pinfo->srcport)) 1292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return dissect_spdy(tvb, pinfo, tree) != 0; 1294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void reinit_spdy(void) 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// NMAKE complains about flags_set_truth not being constant. Duplicate 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the values inside of it. 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const true_false_string tfs_spdy_set_notset = { "Set", "Not set" }; 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochproto_register_spdy(void) 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static hf_register_info hf[] = { 1308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_syn_stream, 1309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Syn Stream", "spdy.syn_stream", 1310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_BYTES, BASE_NONE, NULL, 0x0, 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_syn_reply, 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Syn Reply", "spdy.syn_reply", 1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_BYTES, BASE_NONE, NULL, 0x0, 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_control_bit, 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Control bit", "spdy.control_bit", 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_BOOLEAN, BASE_NONE, NULL, 0x0, 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "TRUE if SPDY control frame", HFILL }}, 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_version, 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Version", "spdy.version", 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT16, BASE_DEC, NULL, 0x0, 1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_type, 1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Type", "spdy.type", 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT16, BASE_DEC, NULL, 0x0, 1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_flags, 1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Flags", "spdy.flags", 1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT8, BASE_HEX, NULL, 0x0, 1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_flags_fin, 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Fin", "spdy.flags.fin", 1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_BOOLEAN, 8, TFS(&tfs_spdy_set_notset), 1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPDY_FIN, "", HFILL }}, 1336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_length, 1337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Length", "spdy.length", 1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT24, BASE_DEC, NULL, 0x0, 1339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_header, 1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Header", "spdy.header", 1342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_NONE, BASE_NONE, NULL, 0x0, 1343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_header_name, 1345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Name", "spdy.header.name", 1346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_NONE, BASE_NONE, NULL, 0x0, 1347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_header_name_text, 1349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Text", "spdy.header.name.text", 1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_STRING, BASE_NONE, NULL, 0x0, 1351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_header_value, 1353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Value", "spdy.header.value", 1354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_NONE, BASE_NONE, NULL, 0x0, 1355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_header_value_text, 1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Text", "spdy.header.value.text", 1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_STRING, BASE_NONE, NULL, 0x0, 1359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_streamid, 1361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Stream ID", "spdy.streamid", 1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT32, BASE_DEC, NULL, 0x0, 1363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_associated_streamid, 1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Associated Stream ID", "spdy.associated.streamid", 1366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT32, BASE_DEC, NULL, 0x0, 1367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_priority, 1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Priority", "spdy.priority", 1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT8, BASE_DEC, NULL, 0x0, 1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_num_headers, 1373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Number of headers", "spdy.numheaders", 1374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_UINT16, BASE_DEC, NULL, 0x0, 1375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { &hf_spdy_num_headers_string, 1377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { "Number of headers", "spdy.numheaders", 1378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FT_STRING, BASE_NONE, NULL, 0x0, 1379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", HFILL }}, 1380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static gint *ett[] = { 1382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy, 1383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_syn_stream, 1384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_syn_reply, 1385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_fin_stream, 1386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_flags, 1387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_header, 1388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_header_name, 1389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_header_value, 1390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_spdy_encoded_entity, 1391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch module_t *spdy_module; 1394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_spdy = proto_register_protocol("SPDY", "SPDY", "spdy"); 1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_register_field_array(proto_spdy, hf, array_length(hf)); 1397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_register_subtree_array(ett, array_length(ett)); 1398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_register_dissector("spdy", dissect_spdy, proto_spdy); 1399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_module = prefs_register_protocol(proto_spdy, reinit_spdy); 1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_bool_preference(spdy_module, "desegment_headers", 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Reassemble SPDY control frames spanning multiple TCP segments", 1402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Whether the SPDY dissector should reassemble control frames " 1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "spanning multiple TCP segments. " 1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "To use this option, you must also enable " 1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", 1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &spdy_desegment_control_frames); 1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_bool_preference(spdy_module, "desegment_body", 1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Reassemble SPDY bodies spanning multiple TCP segments", 1409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Whether the SPDY dissector should reassemble " 1410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "data frames spanning multiple TCP segments. " 1411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "To use this option, you must also enable " 1412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", 1413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &spdy_desegment_data_frames); 1414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_bool_preference(spdy_module, "assemble_data_frames", 1415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Assemble SPDY bodies that consist of multiple DATA frames", 1416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Whether the SPDY dissector should reassemble multiple " 1417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "data frames into an entity body.", 1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &spdy_assemble_entity_bodies); 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifdef HAVE_LIBZ 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_bool_preference(spdy_module, "decompress_headers", 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Uncompress SPDY headers", 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Whether to uncompress SPDY headers.", 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &spdy_decompress_headers); 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_bool_preference(spdy_module, "decompress_body", 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Uncompress entity bodies", 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Whether to uncompress entity bodies that are compressed " 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "using \"Content-Encoding: \"", 1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &spdy_decompress_body); 1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_bool_preference(spdy_module, "debug_output", 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Print debug info on stdout", 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Print debug info on stdout", 1433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &spdy_debug); 1434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if 0 1435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_string_preference(ssl_module, "debug_file", "SPDY debug file", 1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Redirect SPDY debug to file name; " 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "leave empty to disable debugging, " 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "or use \"" SPDY_DEBUG_USE_STDOUT "\"" 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch " to redirect output to stdout\n", 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (const gchar **)&sdpy_debug_file_name); 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_obsolete_preference(spdy_module, "tcp_alternate_port"); 1443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch range_convert_str(&global_spdy_tcp_range, TCP_DEFAULT_RANGE, 65535); 1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_tcp_range = range_empty(); 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_range_preference(spdy_module, "tcp.port", "TCP Ports", 1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "TCP Ports range", 1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &global_spdy_tcp_range, 65535); 1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch range_convert_str(&global_spdy_ssl_range, SSL_DEFAULT_RANGE, 65535); 1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_ssl_range = range_empty(); 1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_register_range_preference(spdy_module, "ssl.port", "SSL/TLS Ports", 1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SSL/TLS Ports range", 1454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &global_spdy_ssl_range, 65535); 1455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_handle = new_create_dissector_handle(dissect_spdy, proto_spdy); 1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 1458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Register for tapping 1459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 1460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_tap = register_tap("spdy"); /* SPDY statistics tap */ 1461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_eo_tap = register_tap("spdy_eo"); /* SPDY Export Object tap */ 1462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid 1465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochproto_reg_handoff_spdy(void) 1466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_handle = find_dissector("data"); 1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch media_handle = find_dissector("media"); 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch heur_dissector_add("tcp", dissect_spdy_heur, proto_spdy); 1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Content-Type: message/http 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint proto_message_spdy = -1; 1477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gint ett_message_spdy = -1; 1478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void 1480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdissect_message_spdy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 1481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree *subtree; 1483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_item *ti; 1484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint offset = 0, next_offset; 1485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint len; 1486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (check_col(pinfo->cinfo, COL_INFO)) 1488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch col_append_str(pinfo->cinfo, COL_INFO, " (message/spdy)"); 1489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tree) { 1490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ti = proto_tree_add_item(tree, proto_message_spdy, 1491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb, 0, -1, FALSE); 1492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch subtree = proto_item_add_subtree(ti, ett_message_spdy); 1493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (tvb_reported_length_remaining(tvb, offset) != 0) { 1494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch len = tvb_find_line_end(tvb, offset, 1495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tvb_ensure_length_remaining(tvb, offset), 1496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &next_offset, FALSE); 1497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (len == -1) 1498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_tree_add_text(subtree, tvb, offset, next_offset - offset, 1500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "%s", tvb_format_text(tvb, offset, len)); 1501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset = next_offset; 1502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid 1507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochproto_register_message_spdy(void) 1508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static gint *ett[] = { 1510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ett_message_spdy, 1511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_message_spdy = proto_register_protocol( 1514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Media Type: message/spdy", 1515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "message/spdy", 1516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "message-spdy" 1517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ); 1518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_register_subtree_array(ett, array_length(ett)); 1519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid 1522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochproto_reg_handoff_message_spdy(void) 1523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 1524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dissector_handle_t message_spdy_handle; 1525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch message_spdy_handle = create_dissector_handle(dissect_message_spdy, 1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch proto_message_spdy); 1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dissector_add_string("media_type", "message/spdy", message_spdy_handle); 1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinit_spdy(); 1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1533