2013-08-30 11:14:09 +00:00
/* packet-http2.c
* Routines for HTTP2 dissection
* Copyright 2013 , Alexis La Goutte < alexis . lagoutte @ gmail . com >
* Copyright 2013 , Stephen Ludin < sludin @ ludin . org >
2014-04-25 14:29:10 +00:00
* Copyright 2014 , Daniel Stenberg < daniel @ haxx . se >
2014-06-23 14:21:15 +00:00
* Copyright 2014 , Tatsuhiro Tsujikawa < tatsuhiro . t @ gmail . com >
2013-08-30 11:14:09 +00:00
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
2018-02-12 11:23:27 +00:00
* SPDX - License - Identifier : GPL - 2.0 - or - later
2013-08-30 11:14:09 +00:00
*/
/*
* The information used comes from :
2015-05-15 17:07:38 +00:00
* RFC7540 : Hypertext Transfer Protocol version 2 ( HTTP / 2 )
* RFC7541 : HTTP Header Compression for HTTP / 2
2016-04-15 16:35:39 +00:00
* RFC7838 : HTTP Alternative Services
2013-08-30 11:14:09 +00:00
*
* TODO
* Enhance display of Data
* Reassembling of continuation frame ( and other frame )
* Add same tap and ping / pong time response
*/
# include "config.h"
# include <epan/packet.h>
2016-02-05 14:41:57 +00:00
# include <epan/expert.h>
2013-08-30 11:14:09 +00:00
# include <epan/prefs.h>
2016-01-25 01:10:20 +00:00
# include <epan/proto_data.h>
2018-07-22 18:51:06 +00:00
# include <epan/exceptions.h>
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
# include <epan/dissectors/packet-http.h> /* for getting status reason-phrase */
2016-08-18 06:07:00 +00:00
# include <epan/dissectors/packet-http2.h>
2014-05-06 15:54:47 +00:00
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2017-11-18 02:09:50 +00:00
# include <epan/uat.h>
2016-08-26 13:18:29 +00:00
# include <nghttp2/nghttp2.h>
2017-11-18 02:09:50 +00:00
2016-08-26 13:18:29 +00:00
# endif
2013-08-30 11:14:09 +00:00
# include "packet-tcp.h"
2015-01-08 16:35:58 +00:00
# include <epan/tap.h>
# include <epan/stats_tree.h>
2017-03-27 10:48:26 +00:00
# include <epan/reassemble.h>
2013-08-30 11:14:09 +00:00
2015-01-20 21:20:54 +00:00
# include "wsutil/pint.h"
2017-11-18 02:09:50 +00:00
# include "wsutil/strtoi.h"
2015-01-20 21:20:54 +00:00
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-08-04 12:06:14 +00:00
# define http2_header_repr_type_VALUE_STRING_LIST(XXX) \
XXX ( HTTP2_HD_NONE , 0x00 , " " ) \
XXX ( HTTP2_HD_INDEXED , 0x01 , " Indexed Header Field " ) \
XXX ( HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME , 0x02 , " Literal Header Field with Incremental Indexing - Indexed Name " ) \
XXX ( HTTP2_HD_LITERAL_INDEXING_NEW_NAME , 0x03 , " Literal Header Field with Incremental Indexing - New Name " ) \
XXX ( HTTP2_HD_LITERAL_INDEXED_NAME , 0x04 , " Literal Header Field without Indexing - Indexed Name " ) \
XXX ( HTTP2_HD_LITERAL_NEW_NAME , 0x05 , " Literal Header Field without Indexing - New Name " ) \
XXX ( HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME , 0x06 , " Literal Header Field never Indexed - Indexed Name " ) \
XXX ( HTTP2_HD_LITERAL_NEVER_INDEXING_NEW_NAME , 0x07 , " Literal Header Field never Indexed - New Name " ) \
XXX ( HTTP2_HD_HEADER_TABLE_SIZE_UPDATE , 0x08 , " Maximum Header Table Size Change " )
VALUE_STRING_ENUM ( http2_header_repr_type ) ;
VALUE_STRING_ARRAY ( http2_header_repr_type ) ;
2017-03-27 10:48:26 +00:00
/*
* Decompression of zlib encoded entities .
*/
# ifdef HAVE_ZLIB
static gboolean http2_decompress_body = TRUE ;
# else
static gboolean http2_decompress_body = FALSE ;
# endif
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
/* Try to dissect reassembled http2.data.data according to content-type later */
static dissector_table_t media_type_dissector_table ;
2016-08-26 13:18:29 +00:00
# endif
2014-08-04 12:06:14 +00:00
2014-06-23 10:25:33 +00:00
/* Decompressed header field */
typedef struct {
2014-08-04 12:06:14 +00:00
/* one of http2_header_repr_type */
gint type ;
/* encoded (compressed) length */
gint length ;
union {
struct {
/* header data */
char * data ;
/* length of data */
guint datalen ;
/* name index or name/value index if type is one of
HTTP2_HD_INDEXED and HTTP2_HD_ * _INDEXED_NAMEs */
2015-09-03 02:53:05 +00:00
guint idx ;
2014-08-13 00:39:07 +00:00
} data ;
2014-08-04 12:06:14 +00:00
/* header table size if type == HTTP2_HD_HEADER_TABLE_SIZE_UPDATE */
guint header_table_size ;
2014-08-13 00:39:07 +00:00
} table ;
2014-06-23 10:25:33 +00:00
} http2_header_t ;
2014-08-04 12:06:14 +00:00
/* Context to decode header representation */
typedef struct {
/* one of http2_header_repr_type */
gint type ;
/* final or temporal result of decoding integer */
guint integer ;
/* next bit shift to made when decoding integer */
guint next_shift ;
/* TRUE if integer decoding was completed */
gboolean complete ;
} http2_header_repr_info_t ;
2014-06-23 10:25:33 +00:00
/* Cached decompressed header data in one packet_info */
typedef struct {
/* list of pointer to wmem_array_t, which is array of
http2_header_t */
wmem_list_t * header_list ;
/* This points to the list frame containing current decompressed
2016-02-05 14:41:57 +00:00
header for dissecting later . */
2014-06-23 10:25:33 +00:00
wmem_list_frame_t * current ;
2016-02-05 14:41:57 +00:00
/* Bytes decompressed if we exceeded MAX_HTTP2_HEADER_SIZE */
guint header_size_reached ;
/* Bytes decompressed if we had not exceeded MAX_HTTP2_HEADER_SIZE */
guint header_size_attempted ;
/* TRUE if we found >= MAX_HTTP2_HEADER_LINES */
gboolean header_lines_exceeded ;
2014-06-23 10:25:33 +00:00
} http2_header_data_t ;
/* In-flight SETTINGS data. */
typedef struct {
2014-08-02 07:22:28 +00:00
/* header table size last seen in SETTINGS */
guint32 header_table_size ;
/* minimum header table size in SETTINGS */
guint32 min_header_table_size ;
2014-06-23 10:25:33 +00:00
/* nonzero if header_table_size has effective value. */
int has_header_table_size ;
} http2_settings_t ;
2017-03-27 10:48:26 +00:00
# ifdef HAVE_NGHTTP2
typedef guint64 http2_frame_num_t ;
/* struct for per-stream, per-direction DATA frame reassembly */
typedef struct {
http2_frame_num_t data_initiated_in ;
gboolean has_transfer_encoded_body ;
} http2_data_stream_reassembly_info_t ;
/* struct for per-stream, per-direction entity body info */
typedef struct {
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
gchar * content_type ;
2017-08-20 05:15:28 +00:00
gchar * content_type_parameters ;
2017-03-27 10:48:26 +00:00
gchar * content_encoding ;
gboolean is_partial_content ;
} http2_data_stream_body_info_t ;
/* struct to track header state, so we know if continuation frames are part
* of a HEADERS frame or a PUSH_PROMISE . Note : does not take into account
* trailing headers */
typedef struct {
http2_frame_num_t header_start_in ;
http2_frame_num_t header_end_in ;
2017-07-30 13:39:11 +00:00
/* list of pointer to wmem_array_t, which is array of http2_header_t
* that come from all HEADERS and CONTINUATION frames . */
wmem_list_t * stream_header_list ;
2017-03-27 10:48:26 +00:00
} http2_header_stream_info_t ;
/* struct to reference uni-directional per-stream info */
typedef struct {
http2_data_stream_body_info_t data_stream_body_info ;
http2_data_stream_reassembly_info_t data_stream_reassembly_info ;
http2_header_stream_info_t header_stream_info ;
} http2_oneway_stream_info_t ;
/* struct to hold per-stream information for both directions */
typedef struct {
/* index into http2_oneway_stream_info_t struct is based off
* http2_session_t . fwd_flow , available by calling select_http2_flow_index ( ) .
* The index could be for either client or server , depending on when
* the capture is started but the index will be consistent for the lifetime
* of the http2_session_t */
http2_oneway_stream_info_t oneway_stream_info [ 2 ] ;
gboolean is_stream_http_connect ;
guint32 stream_id ;
} http2_stream_info_t ;
# endif
2014-05-06 15:54:47 +00:00
/* struct to hold data per HTTP/2 session */
typedef struct {
2014-06-23 10:25:33 +00:00
/* We need to distinguish the direction of the flow to keep track
of in - flight SETTINGS and HPACK inflater objects . To achieve
this , we use fwd member of tcp_analysis . In the first packet ,
we record fwd of tcp_analysis . Later , if processing
packet_info has fwd of tcp_analysis equal to the recorded fwd ,
we use index 0 of settings_queue and hd_inflater . We keep
track of SETTINGS frame sent in this direction in
settings_queue [ 0 ] and inflate header block using
hd_inflater [ 0 ] . Otherwise , we use settings_queue [ 1 ] and
hd_inflater [ 1 ] . */
wmem_queue_t * settings_queue [ 2 ] ;
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-05-06 15:54:47 +00:00
nghttp2_hd_inflater * hd_inflater [ 2 ] ;
2014-08-04 12:06:14 +00:00
http2_header_repr_info_t header_repr_info [ 2 ] ;
2017-03-27 10:48:26 +00:00
wmem_map_t * per_stream_info ;
guint32 current_stream_id ;
2016-08-26 13:18:29 +00:00
# endif
2014-06-23 10:25:33 +00:00
tcp_flow_t * fwd_flow ;
2014-05-06 15:54:47 +00:00
} http2_session_t ;
2013-12-15 23:44:12 +00:00
void proto_register_http2 ( void ) ;
void proto_reg_handoff_http2 ( void ) ;
2015-01-08 16:35:58 +00:00
struct HTTP2Tap {
guint8 type ;
} ;
static int http2_tap = - 1 ;
static const guint8 * st_str_http2 = " HTTP2 " ;
static const guint8 * st_str_http2_type = " Type " ;
static int st_node_http2 = - 1 ;
static int st_node_http2_type = - 1 ;
2014-08-02 10:00:59 +00:00
2013-08-30 11:14:09 +00:00
/* Packet Header */
static int proto_http2 = - 1 ;
2016-02-03 06:06:07 +00:00
static int hf_http2_stream = - 1 ;
2013-08-30 11:14:09 +00:00
static int hf_http2_length = - 1 ;
static int hf_http2_type = - 1 ;
static int hf_http2_r = - 1 ;
static int hf_http2_streamid = - 1 ;
static int hf_http2_magic = - 1 ;
static int hf_http2_unknown = - 1 ;
/* Flags */
static int hf_http2_flags = - 1 ;
static int hf_http2_flags_end_stream = - 1 ;
static int hf_http2_flags_end_headers = - 1 ;
2014-06-23 14:21:15 +00:00
static int hf_http2_flags_padded = - 1 ;
2013-08-30 11:14:09 +00:00
static int hf_http2_flags_priority = - 1 ;
2013-12-15 19:07:40 +00:00
static int hf_http2_flags_settings_ack = - 1 ;
static int hf_http2_flags_ping_ack = - 1 ;
2014-05-12 07:00:52 +00:00
static int hf_http2_flags_unused = - 1 ;
2014-06-23 14:21:15 +00:00
static int hf_http2_flags_unused_settings = - 1 ;
static int hf_http2_flags_unused_ping = - 1 ;
static int hf_http2_flags_unused_continuation = - 1 ;
static int hf_http2_flags_unused_push_promise = - 1 ;
2014-05-12 07:00:52 +00:00
static int hf_http2_flags_unused_data = - 1 ;
2014-06-23 14:21:15 +00:00
static int hf_http2_flags_unused_headers = - 1 ;
2014-04-25 14:29:10 +00:00
/* generic */
2014-06-23 14:21:15 +00:00
static int hf_http2_padding = - 1 ;
2014-05-12 07:00:52 +00:00
static int hf_http2_pad_length = - 1 ;
2014-04-25 14:29:10 +00:00
static int hf_http2_weight = - 1 ;
2014-05-13 15:49:24 +00:00
static int hf_http2_weight_real = - 1 ;
2014-04-25 14:29:10 +00:00
static int hf_http2_stream_dependency = - 1 ;
static int hf_http2_excl_dependency = - 1 ;
/* Data */
static int hf_http2_data_data = - 1 ;
static int hf_http2_data_padding = - 1 ;
2017-03-27 10:48:26 +00:00
static int hf_http2_body_fragments = - 1 ;
static int hf_http2_body_fragment = - 1 ;
static int hf_http2_body_fragment_overlap = - 1 ;
static int hf_http2_body_fragment_overlap_conflicts = - 1 ;
static int hf_http2_body_fragment_multiple_tails = - 1 ;
static int hf_http2_body_fragment_too_long_fragment = - 1 ;
static int hf_http2_body_fragment_error = - 1 ;
static int hf_http2_body_fragment_count = - 1 ;
static int hf_http2_body_reassembled_in = - 1 ;
static int hf_http2_body_reassembled_length = - 1 ;
2013-08-30 11:14:09 +00:00
/* Headers */
2014-05-06 15:54:47 +00:00
static int hf_http2_headers = - 1 ;
2014-04-25 14:29:10 +00:00
static int hf_http2_headers_padding = - 1 ;
2014-05-06 15:54:47 +00:00
static int hf_http2_header = - 1 ;
static int hf_http2_header_length = - 1 ;
2016-02-05 14:41:57 +00:00
static int hf_http2_header_count = - 1 ;
2014-05-06 15:54:47 +00:00
static int hf_http2_header_name_length = - 1 ;
static int hf_http2_header_name = - 1 ;
static int hf_http2_header_value_length = - 1 ;
static int hf_http2_header_value = - 1 ;
2018-12-19 12:08:41 +00:00
static int hf_http2_header_unescaped = - 1 ;
2014-08-04 12:06:14 +00:00
static int hf_http2_header_repr = - 1 ;
static int hf_http2_header_index = - 1 ;
static int hf_http2_header_table_size_update = - 1 ;
static int hf_http2_header_table_size = - 1 ;
2013-08-30 11:14:09 +00:00
/* RST Stream */
static int hf_http2_rst_stream_error = - 1 ;
/* Settings */
static int hf_http2_settings = - 1 ;
static int hf_http2_settings_identifier = - 1 ;
2013-12-15 19:07:40 +00:00
static int hf_http2_settings_header_table_size = - 1 ;
static int hf_http2_settings_enable_push = - 1 ;
2013-08-30 11:14:09 +00:00
static int hf_http2_settings_max_concurrent_streams = - 1 ;
static int hf_http2_settings_initial_window_size = - 1 ;
2014-08-02 07:22:28 +00:00
static int hf_http2_settings_max_frame_size = - 1 ;
static int hf_http2_settings_max_header_list_size = - 1 ;
2013-08-30 11:14:09 +00:00
static int hf_http2_settings_unknown = - 1 ;
/* Push Promise */
static int hf_http2_push_promise_r = - 1 ;
static int hf_http2_push_promise_promised_stream_id = - 1 ;
static int hf_http2_push_promise_header = - 1 ;
2014-04-25 14:29:10 +00:00
static int hf_http2_push_promise_padding = - 1 ;
2013-08-30 11:14:09 +00:00
/* Ping */
static int hf_http2_ping = - 1 ;
static int hf_http2_pong = - 1 ;
2014-04-25 14:29:10 +00:00
/* Goaway */
2013-08-30 11:14:09 +00:00
static int hf_http2_goaway_r = - 1 ;
static int hf_http2_goaway_last_stream_id = - 1 ;
static int hf_http2_goaway_error = - 1 ;
static int hf_http2_goaway_addata = - 1 ;
/* Window Update */
static int hf_http2_window_update_r = - 1 ;
static int hf_http2_window_update_window_size_increment = - 1 ;
/* Continuation */
static int hf_http2_continuation_header = - 1 ;
2014-05-12 07:00:52 +00:00
static int hf_http2_continuation_padding = - 1 ;
2014-04-25 14:29:10 +00:00
/* Altsvc */
2016-04-15 16:35:39 +00:00
static int hf_http2_altsvc_origin_len = - 1 ;
2014-04-25 14:29:10 +00:00
static int hf_http2_altsvc_origin = - 1 ;
2016-04-15 16:35:39 +00:00
static int hf_http2_altsvc_field_value = - 1 ;
2017-11-18 02:09:50 +00:00
# if HAVE_NGHTTP2
/* HTTP2 header static fields */
static int hf_http2_headers_status = - 1 ;
static int hf_http2_headers_path = - 1 ;
static int hf_http2_headers_method = - 1 ;
static int hf_http2_headers_scheme = - 1 ;
static int hf_http2_headers_accept = - 1 ;
static int hf_http2_headers_accept_charset = - 1 ;
static int hf_http2_headers_accept_encoding = - 1 ;
static int hf_http2_headers_accept_language = - 1 ;
static int hf_http2_headers_accept_ranges = - 1 ;
static int hf_http2_headers_access_control_allow_origin = - 1 ;
static int hf_http2_headers_age = - 1 ;
static int hf_http2_headers_allow = - 1 ;
static int hf_http2_headers_authorization = - 1 ;
static int hf_http2_headers_authority = - 1 ;
static int hf_http2_headers_cache_control = - 1 ;
static int hf_http2_headers_content_disposition = - 1 ;
static int hf_http2_headers_content_encoding = - 1 ;
static int hf_http2_headers_content_language = - 1 ;
static int hf_http2_headers_content_length = - 1 ;
static int hf_http2_headers_content_location = - 1 ;
static int hf_http2_headers_content_range = - 1 ;
static int hf_http2_headers_content_type = - 1 ;
static int hf_http2_headers_cookie = - 1 ;
static int hf_http2_headers_date = - 1 ;
static int hf_http2_headers_etag = - 1 ;
static int hf_http2_headers_expect = - 1 ;
static int hf_http2_headers_expires = - 1 ;
static int hf_http2_headers_from = - 1 ;
static int hf_http2_headers_if_match = - 1 ;
static int hf_http2_headers_if_modified_since = - 1 ;
static int hf_http2_headers_if_none_match = - 1 ;
static int hf_http2_headers_if_range = - 1 ;
static int hf_http2_headers_if_unmodified_since = - 1 ;
static int hf_http2_headers_last_modified = - 1 ;
static int hf_http2_headers_link = - 1 ;
static int hf_http2_headers_location = - 1 ;
static int hf_http2_headers_max_forwards = - 1 ;
static int hf_http2_headers_proxy_authenticate = - 1 ;
static int hf_http2_headers_proxy_authorization = - 1 ;
static int hf_http2_headers_range = - 1 ;
static int hf_http2_headers_referer = - 1 ;
static int hf_http2_headers_refresh = - 1 ;
static int hf_http2_headers_retry_after = - 1 ;
static int hf_http2_headers_server = - 1 ;
static int hf_http2_headers_set_cookie = - 1 ;
static int hf_http2_headers_strict_transport_security = - 1 ;
static int hf_http2_headers_user_agent = - 1 ;
static int hf_http2_headers_vary = - 1 ;
static int hf_http2_headers_via = - 1 ;
static int hf_http2_headers_www_authenticate = - 1 ;
# endif
2014-04-25 14:29:10 +00:00
/* Blocked */
2016-02-05 14:41:57 +00:00
/*
* These values * should * be large enough to handle most use cases while
* keeping hostile traffic from consuming too many resources . If that ' s
* not the case we can convert them to preferences . Current ( Feb 2016 )
* client and server limits :
*
* Apache : 8 K ( LimitRequestFieldSize ) , 100 lines ( LimitRequestFields )
* Chrome : 256 K ?
* Firefox : Unknown
* IIS : 16 K ( MaxRequestBytes )
* Nginx : 8 K ( large_client_header_buffers )
* Safari : Unknown
* Tomcat : 8 K ( maxHttpHeaderSize )
*/
# define MAX_HTTP2_HEADER_SIZE (256 * 1024)
# define MAX_HTTP2_HEADER_LINES 200
static expert_field ei_http2_header_size = EI_INIT ;
static expert_field ei_http2_header_lines = EI_INIT ;
2017-03-27 10:48:26 +00:00
static expert_field ei_http2_body_decompression_failed = EI_INIT ;
2013-08-30 11:14:09 +00:00
static gint ett_http2 = - 1 ;
static gint ett_http2_header = - 1 ;
2014-05-06 15:54:47 +00:00
static gint ett_http2_headers = - 1 ;
2013-08-30 11:14:09 +00:00
static gint ett_http2_flags = - 1 ;
static gint ett_http2_settings = - 1 ;
2017-03-27 10:48:26 +00:00
static gint ett_http2_encoded_entity = - 1 ;
static gint ett_http2_body_fragment = - 1 ;
static gint ett_http2_body_fragments = - 1 ;
2017-06-22 19:38:17 +00:00
# ifdef HAVE_NGHTTP2
2017-03-27 10:48:26 +00:00
static const fragment_items http2_body_fragment_items = {
/* Fragment subtrees */
& ett_http2_body_fragment ,
& ett_http2_body_fragments ,
/* Fragment fields */
& hf_http2_body_fragments ,
& hf_http2_body_fragment ,
& hf_http2_body_fragment_overlap ,
& hf_http2_body_fragment_overlap_conflicts ,
& hf_http2_body_fragment_multiple_tails ,
& hf_http2_body_fragment_too_long_fragment ,
& hf_http2_body_fragment_error ,
& hf_http2_body_fragment_count ,
& hf_http2_body_reassembled_in ,
& hf_http2_body_reassembled_length ,
NULL ,
" Body fragments "
} ;
2013-08-30 11:14:09 +00:00
2016-02-05 14:41:57 +00:00
/* Due to HPACK compression, we may get lots of relatively large
header fields ( e . g . , 4 KiB ) . Allocating each of them requires lots
of memory . The maximum compression is achieved in HPACK by
referencing header field stored in dynamic table by one or two
bytes . We reduce memory usage by caching header field in this
wmem_map_t to reuse its memory region when we see the same header
field next time . */
static wmem_map_t * http2_hdrcache_map = NULL ;
/* Header name_length + name + value_length + value */
static char * http2_header_pstr = NULL ;
2016-08-26 13:18:29 +00:00
# endif
2016-02-05 14:41:57 +00:00
2017-11-18 02:09:50 +00:00
# ifdef HAVE_NGHTTP2
/* Stuff for generation/handling of fields for HTTP2 headers */
enum header_field_type {
val_string ,
val_uint64
} ;
typedef struct _header_field_t {
gchar * header_name ;
enum header_field_type header_type ;
gchar * header_desc ;
} header_field_t ;
static header_field_t * header_fields = NULL ;
static guint num_header_fields = 0 ;
static guint num_header_fields_cleanup = 0 ;
static GHashTable * header_fields_hash = NULL ;
static gboolean
header_fields_update_cb ( void * r , char * * err )
{
header_field_t * rec = ( header_field_t * ) r ;
char c ;
if ( rec - > header_name = = NULL ) {
* err = g_strdup ( " Header name can't be empty " ) ;
return FALSE ;
}
g_strstrip ( rec - > header_name ) ;
if ( rec - > header_name [ 0 ] = = 0 ) {
* err = g_strdup ( " Header name can't be empty " ) ;
return FALSE ;
}
/* Check for invalid characters (to avoid asserting out when
* registering the field ) .
*/
c = proto_check_field_name ( rec - > header_name ) ;
if ( c ) {
* err = g_strdup_printf ( " Header name can't contain '%c' " , c ) ;
return FALSE ;
}
/* If the hash table is empty(e.g. on startup), do not try to check a value */
if ( header_fields_hash ! = NULL ) {
const gint * entry = ( const gint * ) g_hash_table_lookup ( header_fields_hash , rec - > header_name ) ;
if ( entry ! = NULL ) {
* err = g_strdup_printf ( " This header field is already defined in UAT or it is a static header field " ) ;
return FALSE ;
}
}
* err = NULL ;
return TRUE ;
}
static void *
header_fields_copy_cb ( void * n , const void * o , size_t siz _U_ )
{
header_field_t * new_rec = ( header_field_t * ) n ;
const header_field_t * old_rec = ( const header_field_t * ) o ;
new_rec - > header_name = g_strdup ( old_rec - > header_name ) ;
new_rec - > header_type = old_rec - > header_type ;
new_rec - > header_desc = g_strdup ( old_rec - > header_desc ) ;
return new_rec ;
}
static void
header_fields_free_cb ( void * r )
{
header_field_t * rec = ( header_field_t * ) r ;
g_hash_table_remove ( header_fields_hash , rec - > header_name ) ;
g_free ( rec - > header_name ) ;
g_free ( rec - > header_desc ) ;
}
static void
register_static_headers ( void ) {
header_fields_hash = g_hash_table_new_full ( g_str_hash , g_str_equal ,
g_free , NULL ) ;
/* Here hf[x].hfinfo.name is a header method which is used as key
* for matching ids while processing HTTP2 packets */
static hf_register_info hf [ ] = {
{
& hf_http2_headers_authority ,
{ " :authority " , " http2.headers.authority " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Authority portion of the target URI " , HFILL }
} ,
{
& hf_http2_headers_status ,
{ " :status " , " http2.headers.status " ,
FT_UINT16 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
{
& hf_http2_headers_path ,
{ " :path " , " http2.headers.path " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
NULL , HFILL }
} ,
{
& hf_http2_headers_method ,
{ " :method " , " http2.headers.method " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
NULL , HFILL }
} ,
{
& hf_http2_headers_scheme ,
{ " :scheme " , " http2.headers.scheme " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
NULL , HFILL }
} ,
{
& hf_http2_headers_accept ,
{ " accept " , " http2.headers.accept " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Media types that are acceptable to the user agent " , HFILL }
} ,
{
& hf_http2_headers_accept_charset ,
2018-01-26 13:19:38 +00:00
{ " accept-charset " , " http2.headers.accept_charset " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Acceptable charsets in textual responses for the user agent " , HFILL }
} ,
{
& hf_http2_headers_accept_encoding ,
2018-01-26 13:19:38 +00:00
{ " accept-encoding " , " http2.headers.accept_encoding " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Acceptable content codings (like compression) in responses for the user agent " , HFILL }
} ,
{
& hf_http2_headers_accept_language ,
2018-01-26 13:19:38 +00:00
{ " accept-language " , " http2.headers.accept_language " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Preferred natural languages for the user agent " , HFILL }
} ,
{
& hf_http2_headers_accept_ranges ,
2018-01-26 13:19:38 +00:00
{ " accept-ranges " , " http2.headers.accept_ranges " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Bytes range which server may use for partial data transfer " , HFILL }
} ,
{
& hf_http2_headers_access_control_allow_origin ,
2018-01-26 13:19:38 +00:00
{ " access-control-allow-origin " , " http2.headers.access_control_allow_origin " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Origin control for cross-origin resource sharing " , HFILL }
} ,
{
& hf_http2_headers_age ,
{ " age " , " http2.headers.age " ,
FT_UINT64 , BASE_DEC , NULL , 0x0 ,
" Time in seconds which was spent for transferring data through proxy " , HFILL }
} ,
{
& hf_http2_headers_allow ,
{ " allow " , " http2.headers.allow " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" List of allowed methods for request " , HFILL }
} ,
{
& hf_http2_headers_authorization ,
{ " authorization " , " http2.headers.authorization " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Credentials for a server-side authorization " , HFILL }
} ,
{
& hf_http2_headers_cache_control ,
2018-01-26 13:19:38 +00:00
{ " cache-control " , " http2.headers.cache_control " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Request or response directives for a cache control " , HFILL }
} ,
{
& hf_http2_headers_content_disposition ,
2018-01-26 13:19:38 +00:00
{ " content-disposition " , " http2.headers.content_disposition " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Indicates that response will be displayed as page or downloaded with dialog box " , HFILL }
} ,
{
& hf_http2_headers_content_encoding ,
2018-01-26 13:19:38 +00:00
{ " content-encoding " , " http2.headers.content_encoding " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
NULL , HFILL }
} ,
{
& hf_http2_headers_content_language ,
2018-01-26 13:19:38 +00:00
{ " content-language " , " http2.headers.content_language " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
NULL , HFILL }
} ,
{
& hf_http2_headers_content_length ,
2018-01-26 13:19:38 +00:00
{ " content-length " , " http2.headers.content_length " ,
2017-11-18 02:09:50 +00:00
FT_UINT64 , BASE_DEC , NULL , 0x0 ,
" Size of body in bytes " , HFILL }
} ,
{
& hf_http2_headers_content_location ,
2018-01-26 13:19:38 +00:00
{ " content-location " , " http2.headers.content_location " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Alternative URL for a response data " , HFILL }
} ,
{
& hf_http2_headers_content_range ,
2018-01-26 13:19:38 +00:00
{ " content-range " , " http2.headers.content_range " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Range of bytes which was sent by server for partial data transfer " , HFILL }
} ,
{
& hf_http2_headers_content_type ,
2018-01-26 13:19:38 +00:00
{ " content-type " , " http2.headers.content_type " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" MIME type of response " , HFILL }
} ,
{
& hf_http2_headers_cookie ,
{ " cookie " , " http2.headers.cookie " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Stored cookies " , HFILL }
} ,
{
& hf_http2_headers_date ,
{ " date " , " http2.headers.date " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Date and time at which the data was originated " , HFILL }
} ,
{
& hf_http2_headers_etag ,
{ " etag " , " http2.headers.etag " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Directive for version indication of resource " , HFILL }
} ,
{
& hf_http2_headers_expect ,
{ " expect " , " http2.headers.expect " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Expectations that need to be fulfilled for correct request " , HFILL }
} ,
{
& hf_http2_headers_expires ,
{ " expires " , " http2.headers.expires " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Data after which resource will be stale " , HFILL }
} ,
{
& hf_http2_headers_from ,
{ " from " , " http2.headers.from " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Email of a person who responsible for a requesting data " , HFILL }
} ,
{
& hf_http2_headers_if_match ,
2018-01-26 13:19:38 +00:00
{ " if-match " , " http2.headers.if_match " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Mechanism for requesting data matched by a list of ETags " , HFILL }
} ,
{
& hf_http2_headers_if_modified_since ,
2018-01-26 13:19:38 +00:00
{ " if-modified-since " , " http2.headers.if_modified_since " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Resource will be sent with status code 200 if it was modified otherwise with status code 304 " , HFILL }
} ,
{
& hf_http2_headers_if_none_match ,
2018-01-26 13:19:38 +00:00
{ " if-none-match " , " http2.headers.if_none_match " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Mechanism for requesting data not matched by a list of ETags " , HFILL }
} ,
{
& hf_http2_headers_if_range ,
2018-01-26 13:19:38 +00:00
{ " if-range " , " http2.headers.if_range " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Mechanism for a range request which is used to check if a resource was modified " , HFILL }
} ,
{
& hf_http2_headers_if_unmodified_since ,
2018-01-26 13:19:38 +00:00
{ " if-unmodified-since " , " http2.headers.if_unmodified_since " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Resource will be processed if it was not modified otherwise 412 error will be returned " , HFILL }
} ,
{
& hf_http2_headers_last_modified ,
2018-01-26 13:19:38 +00:00
{ " last-modified " , " http2.headers.last_modified " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Date and time at which the origin server believes the resource was last modified " , HFILL }
} ,
{
& hf_http2_headers_link ,
{ " link " , " http2.headers.link " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Mechanism for indicating that resource will be preloaded " , HFILL }
} ,
{
& hf_http2_headers_location ,
{ " location " , " http2.headers.location " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Mechanism for indicating that client will be redirected " , HFILL }
} ,
{
& hf_http2_headers_max_forwards ,
2018-01-26 13:19:38 +00:00
{ " max-forwards " , " http2.headers.max_forwards " ,
2017-11-18 02:09:50 +00:00
FT_UINT64 , BASE_DEC , NULL , 0x0 ,
" Mechanism for limiting the number of proxies " , HFILL }
} ,
{
& hf_http2_headers_proxy_authenticate ,
2018-01-26 13:19:38 +00:00
{ " proxy-authenticate " , " http2.headers.proxy_authenticate " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Authentication method that should be used to gain access to a resource behind a proxy server " , HFILL }
} ,
{
& hf_http2_headers_proxy_authorization ,
2018-01-26 13:19:38 +00:00
{ " proxy-authorization " , " http2.headers.proxy_authorization " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Credentials for a proxy-side authorization " , HFILL }
} ,
{
& hf_http2_headers_range ,
{ " range " , " http2.headers.range " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Range of resource bytes that server should return " , HFILL }
} ,
{
& hf_http2_headers_referer ,
{ " referer " , " http2.headers.referer " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Address of the previous web page " , HFILL }
} ,
{
& hf_http2_headers_refresh ,
{ " refresh " , " http2.headers.refresh " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Time in seconds after which client will be redirected by given url " , HFILL }
} ,
{
& hf_http2_headers_retry_after ,
2018-01-26 13:19:38 +00:00
{ " retry-after " , " http2.headers.retry_after " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Mechanism to indicate when resource expected to be available " , HFILL }
} ,
{
& hf_http2_headers_server ,
{ " server " , " http2.headers.server " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Information about server software " , HFILL }
} ,
{
& hf_http2_headers_set_cookie ,
2018-01-26 13:19:38 +00:00
{ " set-cookie " , " http2.headers.set_cookie " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Send a cookie to the client " , HFILL }
} ,
{
& hf_http2_headers_strict_transport_security ,
2018-01-26 13:19:38 +00:00
{ " strict-transport-security " , " http2.headers.strict_transport_security " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" HSTS indicates that resource should be accessed only using HTTPS " , HFILL }
} ,
{
& hf_http2_headers_user_agent ,
2018-01-26 13:19:38 +00:00
{ " user-agent " , " http2.headers.user_agent " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Information about client software " , HFILL }
} ,
{
& hf_http2_headers_vary ,
{ " vary " , " http2.headers.vary " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Mechanism for selecting which header will be used for content negotiation algorithm " , HFILL }
} ,
{
& hf_http2_headers_via ,
{ " via " , " http2.headers.via " ,
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Additional information for loop detection and protocol capabilities in proxy requests " , HFILL }
} ,
{
& hf_http2_headers_www_authenticate ,
2018-01-26 13:19:38 +00:00
{ " www-authenticate " , " http2.headers.www_authenticate " ,
2017-11-18 02:09:50 +00:00
FT_STRING , STR_UNICODE , NULL , 0x0 ,
" Authentication method that should be used to gain access to a resource " , HFILL }
}
} ;
gchar * header_name ;
for ( guint i = 0 ; i < G_N_ELEMENTS ( hf ) ; + + i ) {
header_name = g_strdup ( hf [ i ] . hfinfo . name ) ;
g_hash_table_insert ( header_fields_hash , header_name , & hf [ i ] . hfinfo . id ) ;
}
proto_register_field_array ( proto_http2 , hf , G_N_ELEMENTS ( hf ) ) ;
}
UAT_CSTRING_CB_DEF ( header_fields , header_name , header_field_t )
UAT_VS_DEF ( header_fields , header_type , header_field_t , enum header_field_type , val_string , " string " )
UAT_CSTRING_CB_DEF ( header_fields , header_desc , header_field_t )
static hf_register_info * hf_uat = NULL ;
# endif
static void
http2_init_protocol ( void )
{
# if HAVE_NGHTTP2
gint * hf_id ;
guint i ;
gchar * header_name ;
gchar * header_name_key ;
/* Add to hash table headers from UAT */
if ( num_header_fields ) {
hf_uat = g_new0 ( hf_register_info , num_header_fields ) ;
num_header_fields_cleanup = num_header_fields ;
for ( i = 0 ; i < num_header_fields ; i + + ) {
hf_id = g_new ( gint , 1 ) ;
* hf_id = - 1 ;
header_name = g_strdup ( header_fields [ i ] . header_name ) ;
header_name_key = g_ascii_strdown ( header_name , - 1 ) ;
hf_uat [ i ] . p_id = hf_id ;
hf_uat [ i ] . hfinfo . name = header_name ;
hf_uat [ i ] . hfinfo . abbrev = g_strdup_printf ( " http2.headers.%s " , header_name ) ;
switch ( header_fields [ i ] . header_type ) {
case val_uint64 :
hf_uat [ i ] . hfinfo . type = FT_UINT64 ;
hf_uat [ i ] . hfinfo . display = BASE_DEC ;
break ;
default : // string
hf_uat [ i ] . hfinfo . type = FT_STRING ;
hf_uat [ i ] . hfinfo . display = BASE_NONE ;
break ;
}
hf_uat [ i ] . hfinfo . strings = NULL ;
hf_uat [ i ] . hfinfo . bitmask = 0 ;
hf_uat [ i ] . hfinfo . blurb = g_strdup ( header_fields [ i ] . header_desc ) ;
HFILL_INIT ( hf_uat [ i ] ) ;
g_hash_table_insert ( header_fields_hash , header_name_key , hf_id ) ;
}
proto_register_field_array ( proto_http2 , hf_uat , num_header_fields ) ;
}
# endif
}
static void
http2_cleanup_protocol ( void ) {
# if HAVE_NGHTTP2
for ( guint i = 0 ; i < num_header_fields_cleanup ; + + i ) {
proto_deregister_field ( proto_http2 , * ( hf_uat [ i ] . p_id ) ) ;
}
proto_add_deregistered_data ( hf_uat ) ;
proto_free_deregistered_fields ( ) ;
# endif
}
2013-12-15 19:07:40 +00:00
static dissector_handle_t http2_handle ;
2013-08-30 11:14:09 +00:00
2017-03-27 10:48:26 +00:00
static reassembly_table http2_body_reassembly_table ;
2014-08-02 07:22:28 +00:00
# define FRAME_HEADER_LENGTH 9
2013-08-30 11:14:09 +00:00
# define MAGIC_FRAME_LENGTH 24
# define MASK_HTTP2_RESERVED 0x80000000
# define MASK_HTTP2_STREAMID 0X7FFFFFFF
# define MASK_HTTP2_PRIORITY 0X7FFFFFFF
/* Header Type Code */
# define HTTP2_DATA 0
# define HTTP2_HEADERS 1
# define HTTP2_PRIORITY 2
# define HTTP2_RST_STREAM 3
# define HTTP2_SETTINGS 4
# define HTTP2_PUSH_PROMISE 5
# define HTTP2_PING 6
# define HTTP2_GOAWAY 7
2014-04-25 14:29:10 +00:00
# define HTTP2_WINDOW_UPDATE 8
# define HTTP2_CONTINUATION 9
# define HTTP2_ALTSVC 0xA
# define HTTP2_BLOCKED 0xB
2013-08-30 11:14:09 +00:00
static const value_string http2_type_vals [ ] = {
{ HTTP2_DATA , " DATA " } ,
{ HTTP2_HEADERS , " HEADERS " } ,
{ HTTP2_PRIORITY , " PRIORITY " } ,
{ HTTP2_RST_STREAM , " RST_STREAM " } ,
{ HTTP2_SETTINGS , " SETTINGS " } ,
{ HTTP2_PUSH_PROMISE , " PUSH_PROMISE " } ,
{ HTTP2_PING , " PING " } ,
{ HTTP2_GOAWAY , " GOAWAY " } ,
{ HTTP2_WINDOW_UPDATE , " WINDOW_UPDATE " } ,
{ HTTP2_CONTINUATION , " CONTINUATION " } ,
2014-04-25 14:29:10 +00:00
{ HTTP2_ALTSVC , " ALTSVC " } ,
{ HTTP2_BLOCKED , " BLOCKED " } ,
2013-08-30 11:14:09 +00:00
{ 0 , NULL }
} ;
/* Flags */
2014-04-25 14:29:10 +00:00
# define HTTP2_FLAGS_ACK 0x01 /* for PING and SETTINGS */
# define HTTP2_FLAGS_END_STREAM 0x01
# define HTTP2_FLAGS_END_HEADERS 0x04
2014-06-23 14:21:15 +00:00
# define HTTP2_FLAGS_PADDED 0x08
2014-04-25 14:29:10 +00:00
# define HTTP2_FLAGS_PRIORITY 0x20
2014-08-02 07:22:28 +00:00
# define HTTP2_FLAGS_UNUSED 0xFF
# define HTTP2_FLAGS_UNUSED_SETTINGS (~HTTP2_FLAGS_ACK & 0xFF)
# define HTTP2_FLAGS_UNUSED_PING (~HTTP2_FLAGS_ACK & 0xFF)
# define HTTP2_FLAGS_UNUSED_CONTINUATION (~HTTP2_FLAGS_END_HEADERS & 0xFF)
# define HTTP2_FLAGS_UNUSED_PUSH_PROMISE \
( ~ ( HTTP2_FLAGS_END_HEADERS | HTTP2_FLAGS_PADDED ) & 0xFF )
# define HTTP2_FLAGS_UNUSED_DATA \
( ~ ( HTTP2_FLAGS_END_STREAM | HTTP2_FLAGS_PADDED ) & 0xFF )
# define HTTP2_FLAGS_UNUSED_HEADERS \
( ~ ( HTTP2_FLAGS_END_STREAM | HTTP2_FLAGS_END_HEADERS | \
HTTP2_FLAGS_PADDED | HTTP2_FLAGS_PRIORITY ) & 0xFF )
2013-08-30 11:14:09 +00:00
# define HTTP2_FLAGS_R 0xFF
# define HTTP2_FLAGS_R1 0xFE
# define HTTP2_FLAGS_R2 0xFA
# define HTTP2_FLAGS_R4 0xFB
2017-03-27 10:48:26 +00:00
/* http header keys and values */
# define HTTP2_HEADER_CONTENT_ENCODING "content-encoding"
# define HTTP2_HEADER_STATUS ":status"
# define HTTP2_HEADER_STATUS_PARTIAL_CONTENT "206"
# define HTTP2_HEADER_METHOD ":method"
# define HTTP2_HEADER_METHOD_CONNECT "CONNECT"
# define HTTP2_HEADER_TRANSFER_ENCODING "transfer-encoding"
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
# define HTTP2_HEADER_PATH ":path"
# define HTTP2_HEADER_CONTENT_TYPE "content-type"
2017-03-27 10:48:26 +00:00
/* header matching helpers */
# define IS_HTTP2_END_STREAM(flags) (flags & HTTP2_FLAGS_END_STREAM)
2013-08-30 11:14:09 +00:00
/* Magic Header : PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n */
static guint8 kMagicHello [ ] = {
0x50 , 0x52 , 0x49 , 0x20 , 0x2a , 0x20 , 0x48 , 0x54 ,
0x54 , 0x50 , 0x2f , 0x32 , 0x2e , 0x30 , 0x0d , 0x0a ,
0x0d , 0x0a , 0x53 , 0x4d , 0x0d , 0x0a , 0x0d , 0x0a
} ;
/* Error Codes */
2014-10-30 08:33:36 +00:00
# define EC_NO_ERROR 0x0
# define EC_PROTOCOL_ERROR 0x1
# define EC_INTERNAL_ERROR 0x2
# define EC_FLOW_CONTROL_ERROR 0x3
# define EC_SETTINGS_TIMEOUT 0x4
# define EC_STREAM_CLOSED 0x5
# define EC_FRAME_SIZE_ERROR 0x6
# define EC_REFUSED_STREAM 0x7
# define EC_CANCEL 0x8
# define EC_COMPRESSION_ERROR 0x9
# define EC_CONNECT_ERROR 0xa
# define EC_ENHANCE_YOUR_CALM 0xb
# define EC_INADEQUATE_SECURITY 0xc
# define EC_HTTP_1_1_REQUIRED 0xd
2013-08-30 11:14:09 +00:00
static const value_string http2_error_codes_vals [ ] = {
2014-04-25 14:29:10 +00:00
{ EC_NO_ERROR , " NO_ERROR " } ,
2013-08-30 11:14:09 +00:00
{ EC_PROTOCOL_ERROR , " PROTOCOL_ERROR " } ,
{ EC_INTERNAL_ERROR , " INTERNAL_ERROR " } ,
{ EC_FLOW_CONTROL_ERROR , " FLOW_CONTROL_ERROR " } ,
2013-12-15 19:07:40 +00:00
{ EC_SETTINGS_TIMEOUT , " SETTINGS_TIMEOUT " } ,
2013-08-30 11:14:09 +00:00
{ EC_STREAM_CLOSED , " STREAM_CLOSED " } ,
2013-12-15 19:07:40 +00:00
{ EC_FRAME_SIZE_ERROR , " FRAME_SIZE_ERROR " } ,
2013-08-30 11:14:09 +00:00
{ EC_REFUSED_STREAM , " REFUSED_STREAM " } ,
{ EC_CANCEL , " CANCEL " } ,
{ EC_COMPRESSION_ERROR , " COMPRESSION_ERROR " } ,
2013-12-15 19:07:40 +00:00
{ EC_CONNECT_ERROR , " CONNECT_ERROR " } ,
{ EC_ENHANCE_YOUR_CALM , " ENHANCE_YOUR_CALM " } ,
2014-06-23 14:21:15 +00:00
{ EC_INADEQUATE_SECURITY , " INADEQUATE_SECURITY " } ,
2014-10-30 08:33:36 +00:00
{ EC_HTTP_1_1_REQUIRED , " HTTP_1_1_REQUIRED " } ,
2013-08-30 11:14:09 +00:00
{ 0 , NULL }
} ;
/* Settings */
2013-12-15 19:07:40 +00:00
# define HTTP2_SETTINGS_HEADER_TABLE_SIZE 1
# define HTTP2_SETTINGS_ENABLE_PUSH 2
2014-04-25 14:29:10 +00:00
# define HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS 3
# define HTTP2_SETTINGS_INITIAL_WINDOW_SIZE 4
2014-08-02 07:22:28 +00:00
# define HTTP2_SETTINGS_MAX_FRAME_SIZE 5
# define HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE 6
2013-08-30 11:14:09 +00:00
static const value_string http2_settings_vals [ ] = {
2013-12-15 19:07:40 +00:00
{ HTTP2_SETTINGS_HEADER_TABLE_SIZE , " Header table size " } ,
{ HTTP2_SETTINGS_ENABLE_PUSH , " Enable PUSH " } ,
2013-08-30 11:14:09 +00:00
{ HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS , " Max concurrent streams " } ,
{ HTTP2_SETTINGS_INITIAL_WINDOW_SIZE , " Initial Windows size " } ,
2014-08-02 07:22:28 +00:00
{ HTTP2_SETTINGS_MAX_FRAME_SIZE , " Max frame size " } ,
{ HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE , " Max header list size " } ,
2013-08-30 11:14:09 +00:00
{ 0 , NULL }
} ;
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-06-23 10:25:33 +00:00
static gboolean
hd_inflate_del_cb ( wmem_allocator_t * allocator _U_ , wmem_cb_event_t event _U_ , void * user_data )
{
nghttp2_hd_inflate_del ( ( nghttp2_hd_inflater * ) user_data ) ;
2016-02-05 14:41:57 +00:00
http2_hdrcache_map = NULL ;
http2_header_pstr = NULL ;
2014-06-23 10:25:33 +00:00
return FALSE ;
}
2017-03-27 10:48:26 +00:00
static http2_stream_info_t *
get_stream_info ( http2_session_t * http2_session )
{
guint32 stream_id = http2_session - > current_stream_id ;
wmem_map_t * stream_map = http2_session - > per_stream_info ;
http2_stream_info_t * stream_info = ( http2_stream_info_t * ) wmem_map_lookup ( stream_map , GINT_TO_POINTER ( stream_id ) ) ;
if ( stream_info = = NULL ) {
stream_info = wmem_new0 ( wmem_file_scope ( ) , http2_stream_info_t ) ;
2017-07-30 13:39:11 +00:00
stream_info - > oneway_stream_info [ 0 ] . header_stream_info . stream_header_list = wmem_list_new ( wmem_file_scope ( ) ) ;
stream_info - > oneway_stream_info [ 1 ] . header_stream_info . stream_header_list = wmem_list_new ( wmem_file_scope ( ) ) ;
2017-03-27 10:48:26 +00:00
stream_info - > stream_id = stream_id ;
wmem_map_insert ( stream_map , GINT_TO_POINTER ( stream_id ) , stream_info ) ;
}
return stream_info ;
}
2016-08-26 13:18:29 +00:00
# endif
2014-06-23 10:25:33 +00:00
2014-05-06 15:54:47 +00:00
static http2_session_t *
2014-06-23 10:25:33 +00:00
get_http2_session ( packet_info * pinfo )
2014-05-06 15:54:47 +00:00
{
conversation_t * conversation ;
http2_session_t * h2session ;
conversation = find_or_create_conversation ( pinfo ) ;
2014-06-23 10:25:33 +00:00
h2session = ( http2_session_t * ) conversation_get_proto_data ( conversation ,
proto_http2 ) ;
if ( ! h2session ) {
struct tcp_analysis * tcpd ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
tcpd = get_tcp_conversation_data ( NULL , pinfo ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
h2session = wmem_new0 ( wmem_file_scope ( ) , http2_session_t ) ;
2014-05-06 15:54:47 +00:00
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-06-23 10:25:33 +00:00
nghttp2_hd_inflate_new ( & h2session - > hd_inflater [ 0 ] ) ;
nghttp2_hd_inflate_new ( & h2session - > hd_inflater [ 1 ] ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
wmem_register_callback ( wmem_file_scope ( ) , hd_inflate_del_cb ,
h2session - > hd_inflater [ 0 ] ) ;
wmem_register_callback ( wmem_file_scope ( ) , hd_inflate_del_cb ,
h2session - > hd_inflater [ 1 ] ) ;
2017-03-27 10:48:26 +00:00
h2session - > per_stream_info = wmem_map_new ( wmem_file_scope ( ) ,
g_direct_hash ,
g_direct_equal ) ;
2016-08-26 13:18:29 +00:00
# endif
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
h2session - > fwd_flow = tcpd - > fwd ;
h2session - > settings_queue [ 0 ] = wmem_queue_new ( wmem_file_scope ( ) ) ;
h2session - > settings_queue [ 1 ] = wmem_queue_new ( wmem_file_scope ( ) ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
conversation_add_proto_data ( conversation , proto_http2 , h2session ) ;
}
2014-05-06 15:54:47 +00:00
return h2session ;
}
2018-09-27 22:56:09 +00:00
# ifdef HAVE_NGHTTP2
2018-09-27 10:58:46 +00:00
guint32
http2_get_stream_id ( packet_info * pinfo )
{
conversation_t * conversation ;
http2_session_t * h2session ;
conversation = find_conversation_pinfo ( pinfo , 0 ) ;
if ( ! conversation ) {
return 0 ;
}
h2session = ( http2_session_t * ) conversation_get_proto_data ( conversation , proto_http2 ) ;
if ( ! h2session ) {
return 0 ;
}
return h2session - > current_stream_id ;
}
2018-09-27 22:56:09 +00:00
# else /* ! HAVE_NGHTTP2 */
guint32
http2_get_stream_id ( packet_info * pinfo _U_ )
{
return 0 ;
}
# endif /* ! HAVE_NGHTTP2 */
2018-09-27 10:58:46 +00:00
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2018-04-19 15:48:19 +00:00
static guint32
2014-06-23 10:25:33 +00:00
select_http2_flow_index ( packet_info * pinfo , http2_session_t * h2session )
2014-05-06 15:54:47 +00:00
{
struct tcp_analysis * tcpd ;
2014-06-23 10:25:33 +00:00
tcpd = get_tcp_conversation_data ( NULL , pinfo ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
if ( tcpd - > fwd = = h2session - > fwd_flow ) {
return 0 ;
} else {
return 1 ;
2014-05-06 15:54:47 +00:00
}
2014-06-23 10:25:33 +00:00
}
2014-05-06 15:54:47 +00:00
2017-03-27 10:48:26 +00:00
static http2_frame_num_t
get_http2_frame_num ( tvbuff_t * tvb , packet_info * pinfo )
{
/* HTTP2 frames are identified as follows:
*
* + - - - 32 bits - - - + - - - - - - - - - 8 bits - - - - - - - + - - - - - 24 bits - - - - - +
* | pinfo - > num | pinfo - > curr_layer_num | tvb - > raw_offset |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*
* This allows for a single HTTP2 frame to be uniquely identified across a capture with the
* added benefit that the number will always be increasing from the previous HTTP2 frame so
* we can use " < " and " > " comparisons to determine before and after in time .
*
* pinfo - > curr_layer_num is used to deliberate when we have multiple TLS records in a
* single ( non - http2 ) frame . This ends up being dissected using two separate TVBs
* ( so tvb - > raw_offset isn ' t useful ) and then end up being the same pinfo - > num .
*
* I have seen instances where the pinfo - > curr_layer_num can change between the first and second
* pass of a packet so this needs to be taken into account when this is used as an identifier .
*/
return ( ( ( guint64 ) pinfo - > num ) < < 32 ) + ( ( ( guint64 ) pinfo - > curr_layer_num ) < < 24 ) + ( ( guint64 ) tvb_raw_offset ( tvb ) ) ;
}
static http2_oneway_stream_info_t *
2017-07-30 13:39:11 +00:00
get_oneway_stream_info ( packet_info * pinfo , gboolean the_other_direction )
2017-03-27 10:48:26 +00:00
{
http2_session_t * http2_session = get_http2_session ( pinfo ) ;
http2_stream_info_t * http2_stream_info = get_stream_info ( http2_session ) ;
2018-04-19 15:48:19 +00:00
guint32 flow_index = select_http2_flow_index ( pinfo , http2_session ) ;
2017-07-30 13:39:11 +00:00
if ( the_other_direction ) {
/* need stream info of the other direction,
so set index from 0 to 1 , or from 1 to 0 */
flow_index ^ = 1 ;
}
2017-03-27 10:48:26 +00:00
return & http2_stream_info - > oneway_stream_info [ flow_index ] ;
}
static http2_data_stream_body_info_t *
get_data_stream_body_info ( packet_info * pinfo )
{
2017-07-30 13:39:11 +00:00
return & ( get_oneway_stream_info ( pinfo , FALSE ) - > data_stream_body_info ) ;
2017-03-27 10:48:26 +00:00
}
static http2_data_stream_reassembly_info_t *
get_data_reassembly_info ( packet_info * pinfo )
{
2017-07-30 13:39:11 +00:00
return & ( get_oneway_stream_info ( pinfo , FALSE ) - > data_stream_reassembly_info ) ;
2017-03-27 10:48:26 +00:00
}
static http2_header_stream_info_t *
2017-07-30 13:39:11 +00:00
get_header_stream_info ( packet_info * pinfo , gboolean the_other_direction )
2017-03-27 10:48:26 +00:00
{
2017-07-30 13:39:11 +00:00
return & ( get_oneway_stream_info ( pinfo , the_other_direction ) - > header_stream_info ) ;
2017-03-27 10:48:26 +00:00
}
2014-06-23 10:25:33 +00:00
static void
push_settings ( packet_info * pinfo , http2_session_t * h2session ,
http2_settings_t * settings )
{
wmem_queue_t * queue ;
2018-04-19 15:48:19 +00:00
guint32 flow_index ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
flow_index = select_http2_flow_index ( pinfo , h2session ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
queue = h2session - > settings_queue [ flow_index ] ;
wmem_queue_push ( queue , settings ) ;
2014-05-06 15:54:47 +00:00
}
2014-06-23 10:25:33 +00:00
static void
apply_and_pop_settings ( packet_info * pinfo , http2_session_t * h2session )
2014-05-06 15:54:47 +00:00
{
2014-06-23 10:25:33 +00:00
wmem_queue_t * queue ;
http2_settings_t * settings ;
nghttp2_hd_inflater * inflater ;
2018-04-19 15:48:19 +00:00
guint32 flow_index ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
/* When header table size is applied, it affects the inflater of
opposite side . */
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
flow_index = select_http2_flow_index ( pinfo , h2session ) ;
inflater = h2session - > hd_inflater [ flow_index ] ;
queue = h2session - > settings_queue [ flow_index ^ 1 ] ;
if ( wmem_queue_count ( queue ) = = 0 ) {
return ;
}
settings = ( http2_settings_t * ) wmem_queue_pop ( queue ) ;
if ( settings - > has_header_table_size ) {
2014-08-02 07:22:28 +00:00
if ( settings - > min_header_table_size < settings - > header_table_size ) {
nghttp2_hd_inflate_change_table_size
( inflater , settings - > min_header_table_size ) ;
}
2014-06-23 10:25:33 +00:00
nghttp2_hd_inflate_change_table_size ( inflater ,
settings - > header_table_size ) ;
2014-05-06 15:54:47 +00:00
}
}
2014-08-04 12:06:14 +00:00
/* Decode integer from buf at position p, using prefix bits. This
function can be called several times if buf does not contain whole
integer . header_repr_info remembers the result of previous call .
Returns the number bytes processed . */
static guint read_integer ( http2_header_repr_info_t * header_repr_info ,
const guint8 * buf , guint len , guint p , guint prefix )
{
guint k = ( 1 < < prefix ) - 1 ;
guint n = header_repr_info - > integer ;
guint shift = header_repr_info - > next_shift ;
if ( n = = 0 ) {
DISSECTOR_ASSERT ( p < len ) ;
if ( ( buf [ p ] & k ) ! = k ) {
header_repr_info - > integer = buf [ p ] & k ;
header_repr_info - > complete = TRUE ;
return p + 1 ;
}
n = k ;
+ + p ;
}
for ( ; p < len ; + + p , shift + = 7 ) {
DISSECTOR_ASSERT ( p < len ) ;
n + = ( buf [ p ] & 0x7F ) < < shift ;
if ( ( buf [ p ] & 0x80 ) = = 0 ) {
header_repr_info - > complete = TRUE ;
+ + p ;
break ;
}
}
header_repr_info - > integer = n ;
header_repr_info - > next_shift = shift ;
return p ;
}
static void
reset_http2_header_repr_info ( http2_header_repr_info_t * header_repr_info )
{
header_repr_info - > type = HTTP2_HD_NONE ;
header_repr_info - > integer = 0 ;
header_repr_info - > next_shift = 0 ;
header_repr_info - > complete = FALSE ;
}
/* Reads zero or more header table size update and optionally header
representation information . This function returns when first
header representation is decoded or buf is processed completely .
This function returns the number bytes processed for header table
size update . */
static guint
process_http2_header_repr_info ( wmem_array_t * headers ,
http2_header_repr_info_t * header_repr_info ,
const guint8 * buf , guint len )
{
guint i ;
guint start ;
if ( header_repr_info - > type ! = HTTP2_HD_NONE & &
header_repr_info - > type ! = HTTP2_HD_HEADER_TABLE_SIZE_UPDATE & &
header_repr_info - > complete ) {
return 0 ;
}
start = 0 ;
for ( i = 0 ; i < len ; ) {
if ( header_repr_info - > type = = HTTP2_HD_NONE ) {
guchar c = buf [ i ] ;
if ( ( c & 0xE0 ) = = 0x20 ) {
header_repr_info - > type = HTTP2_HD_HEADER_TABLE_SIZE_UPDATE ;
i = read_integer ( header_repr_info , buf , len , i , 5 ) ;
} else if ( c & 0x80 ) {
header_repr_info - > type = HTTP2_HD_INDEXED ;
i = read_integer ( header_repr_info , buf , len , i , 7 ) ;
} else if ( c = = 0x40 | | c = = 0 | | c = = 0x10 ) {
/* New name */
header_repr_info - > complete = TRUE ;
if ( c & 0x40 ) {
header_repr_info - > type = HTTP2_HD_LITERAL_INDEXING_NEW_NAME ;
} else if ( ( c & 0xF0 ) = = 0x10 ) {
header_repr_info - > type = HTTP2_HD_LITERAL_NEVER_INDEXING_NEW_NAME ;
} else {
header_repr_info - > type = HTTP2_HD_LITERAL_NEW_NAME ;
}
} else {
/* indexed name */
if ( c & 0x40 ) {
header_repr_info - > type = HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME ;
i = read_integer ( header_repr_info , buf , len , i , 6 ) ;
} else if ( ( c & 0xF0 ) = = 0x10 ) {
header_repr_info - > type = HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME ;
i = read_integer ( header_repr_info , buf , len , i , 4 ) ;
} else {
header_repr_info - > type = HTTP2_HD_LITERAL_INDEXED_NAME ;
i = read_integer ( header_repr_info , buf , len , i , 4 ) ;
}
}
} else {
i = read_integer ( header_repr_info , buf , len , i , 8 ) ;
}
if ( header_repr_info - > complete ) {
if ( header_repr_info - > type = = HTTP2_HD_HEADER_TABLE_SIZE_UPDATE ) {
http2_header_t * out ;
out = wmem_new ( wmem_file_scope ( ) , http2_header_t ) ;
out - > type = header_repr_info - > type ;
out - > length = i - start ;
2014-08-13 00:39:07 +00:00
out - > table . header_table_size = header_repr_info - > integer ;
2014-08-04 12:06:14 +00:00
wmem_array_append ( headers , out , 1 ) ;
reset_http2_header_repr_info ( header_repr_info ) ;
/* continue to decode header table size update or
first header encoding is encountered . */
start = i ;
} else {
/* Break on first header encoding */
break ;
}
}
}
return start ;
}
2016-02-05 14:41:57 +00:00
static size_t http2_hdrcache_length ( gconstpointer vv )
{
const guint8 * v = ( const guint8 * ) vv ;
guint32 namelen , valuelen ;
namelen = pntoh32 ( v ) ;
valuelen = pntoh32 ( v + sizeof ( namelen ) + namelen ) ;
return namelen + valuelen + sizeof ( namelen ) + sizeof ( valuelen ) ;
}
static guint http2_hdrcache_hash ( gconstpointer key )
{
return wmem_strong_hash ( ( const guint8 * ) key , http2_hdrcache_length ( key ) ) ;
}
static gboolean http2_hdrcache_equal ( gconstpointer lhs , gconstpointer rhs )
{
const guint8 * a = ( const guint8 * ) lhs ;
const guint8 * b = ( const guint8 * ) rhs ;
size_t alen = http2_hdrcache_length ( a ) ;
size_t blen = http2_hdrcache_length ( b ) ;
return alen = = blen & & memcmp ( a , b , alen ) = = 0 ;
}
2017-03-27 10:48:26 +00:00
static int
is_in_header_context ( tvbuff_t * tvb , packet_info * pinfo )
{
2017-07-30 13:39:11 +00:00
http2_header_stream_info_t * stream_info = get_header_stream_info ( pinfo , FALSE ) ;
2017-03-27 10:48:26 +00:00
if ( get_http2_frame_num ( tvb , pinfo ) > = stream_info - > header_start_in ) {
/* We either haven't established the frame that the headers end in so we are currently in the HEADERS context,
* or if we have , it should be equal or less that the current frame number */
if ( stream_info - > header_end_in = = 0 | | get_http2_frame_num ( tvb , pinfo ) < = stream_info - > header_end_in ) {
return TRUE ;
}
}
return FALSE ;
}
2017-08-20 05:15:28 +00:00
/* Extracts only the media-type from a content-type header. EG:
" text/html " returns " text/html "
" text/html; charset=utf-8 " returns " text/html "
Allocates file - scoped string when called as its only called when the header population is done .
*/
static gchar *
get_content_type_only ( const gchar * content_type , int content_type_str_len ) {
gchar * cp = wmem_strndup ( wmem_file_scope ( ) , content_type , content_type_str_len ) ;
gchar * start = cp ;
while ( * cp ! = ' \0 ' & & * cp ! = ' ; ' & & ! g_ascii_isspace ( * cp ) ) {
* cp = g_ascii_tolower ( * cp ) ;
+ + cp ;
}
* cp = ' \0 ' ;
return start ;
}
/* Extracts the parameters from a content-type or returns NULL. EG:
" text/html; charset=utf-8 " returns " charset=utf-8 "
" text/html " returns NULL
" text/html; " returns NULL
Allocates file - scoped string when called as its only called when the header population is done .
*/
static gchar *
get_content_type_parameters_only ( const gchar * content_type , int content_type_str_len ) {
gchar * cp = wmem_strndup ( wmem_file_scope ( ) , content_type , content_type_str_len ) ;
/* Get past the first part of the content type EG: "text/html" */
while ( * cp ! = ' \0 ' & & * cp ! = ' ; ' & & ! g_ascii_isspace ( * cp ) ) {
+ + cp ;
}
/* No parameters */
if ( * cp = = ' \0 ' ) {
return NULL ;
}
/* Move past the first ";" or any whitespace */
while ( * cp = = ' ; ' | | g_ascii_isspace ( * cp ) ) {
+ + cp ;
}
/* Didn't end up getting any parameters, we just had trailing whitespace or a semicolon after the content-type */
if ( * cp = = ' \0 ' ) {
return NULL ;
}
return cp ;
}
2017-03-27 10:48:26 +00:00
static void
populate_http_header_tracking ( tvbuff_t * tvb , packet_info * pinfo , http2_session_t * h2session , int header_value_length ,
const gchar * header_name , const gchar * header_value )
{
/* Populate the content encoding used so we can uncompress the body later if required */
if ( strcmp ( header_name , HTTP2_HEADER_CONTENT_ENCODING ) = = 0 ) {
http2_data_stream_body_info_t * body_info = get_data_stream_body_info ( pinfo ) ;
if ( body_info - > content_encoding = = NULL ) {
body_info - > content_encoding = wmem_strndup ( wmem_file_scope ( ) , header_value , header_value_length ) ;
}
}
/* Is this a partial content? */
if ( strcmp ( header_name , HTTP2_HEADER_STATUS ) = = 0 & &
strcmp ( header_value , HTTP2_HEADER_STATUS_PARTIAL_CONTENT ) = = 0 ) {
http2_data_stream_body_info_t * body_info = get_data_stream_body_info ( pinfo ) ;
body_info - > is_partial_content = TRUE ;
}
/* Was this header used to initiate transfer of data frames? We'll use this later for reassembly */
if ( strcmp ( header_name , HTTP2_HEADER_STATUS ) = = 0 | |
strcmp ( header_name , HTTP2_HEADER_METHOD ) = = 0 ) {
http2_data_stream_reassembly_info_t * reassembly_info = get_data_reassembly_info ( pinfo ) ;
if ( reassembly_info - > data_initiated_in = = 0 ) {
reassembly_info - > data_initiated_in = get_http2_frame_num ( tvb , pinfo ) ;
}
}
/* Do we have transfer encoding of bodies? We don't support reassembling these so mark it as such. */
if ( strcmp ( header_name , HTTP2_HEADER_TRANSFER_ENCODING ) = = 0 ) {
http2_data_stream_reassembly_info_t * reassembly_info = get_data_reassembly_info ( pinfo ) ;
reassembly_info - > has_transfer_encoded_body = TRUE ;
}
/* Store away if the stream is associated with a CONNECT request */
if ( strcmp ( header_name , HTTP2_HEADER_METHOD ) = = 0 & &
strcmp ( header_value , HTTP2_HEADER_METHOD_CONNECT ) = = 0 ) {
http2_stream_info_t * stream_info = get_stream_info ( h2session ) ;
stream_info - > is_stream_http_connect = TRUE ;
}
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
/* Populate the content type so we can dissect the body later */
if ( strcmp ( header_name , HTTP2_HEADER_CONTENT_TYPE ) = = 0 ) {
http2_data_stream_body_info_t * body_info = get_data_stream_body_info ( pinfo ) ;
if ( body_info - > content_type = = NULL ) {
2017-08-20 05:15:28 +00:00
body_info - > content_type = get_content_type_only ( header_value , header_value_length ) ;
body_info - > content_type_parameters = get_content_type_parameters_only ( header_value , header_value_length ) ;
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
}
}
}
static void
try_append_method_path_info ( packet_info * pinfo , proto_tree * tree ,
const gchar * method_header_value , const gchar * path_header_value )
{
if ( method_header_value ! = NULL & & path_header_value ! = NULL ) {
/* append request inforamtion to info column (for example, HEADERS: GET /demo/1.jpg) */
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " : " , " %s %s " , method_header_value , path_header_value ) ;
/* append request information to Stream node */
proto_item_append_text ( tree , " , %s %s " , method_header_value , path_header_value ) ;
}
2017-03-27 10:48:26 +00:00
}
2017-11-18 02:09:50 +00:00
static void
try_add_named_header_field ( proto_tree * tree , tvbuff_t * tvb , int offset , guint32 length , const char * header_name , const char * header_value )
{
int hf_id = - 1 ;
header_field_info * hfi ;
const gint * entry = ( const gint * ) g_hash_table_lookup ( header_fields_hash , header_name ) ;
if ( entry = = NULL ) {
return ;
}
hf_id = * entry ;
hfi = proto_registrar_get_nth ( hf_id ) ;
DISSECTOR_ASSERT ( hfi ! = NULL ) ;
if ( IS_FT_UINT32 ( hfi - > type ) ) {
guint32 value ;
if ( ws_strtou32 ( header_value , NULL , & value ) ) {
proto_tree_add_uint ( tree , hf_id , tvb , offset , length , value ) ;
}
} else if ( IS_FT_UINT ( hfi - > type ) ) {
guint64 value ;
if ( ws_strtou64 ( header_value , NULL , & value ) ) {
proto_tree_add_uint64 ( tree , hf_id , tvb , offset , length , value ) ;
}
} else {
proto_tree_add_item ( tree , hf_id , tvb , offset , length , ENC_BIG_ENDIAN ) ;
}
}
2014-05-06 15:54:47 +00:00
static void
inflate_http2_header_block ( tvbuff_t * tvb , packet_info * pinfo , guint offset ,
2018-07-22 18:51:06 +00:00
proto_tree * tree , guint headlen ,
2014-05-06 15:54:47 +00:00
http2_session_t * h2session , guint8 flags )
{
guint8 * headbuf ;
proto_tree * header_tree ;
proto_item * header , * ti ;
2017-11-30 03:39:14 +00:00
guint32 header_name_length ;
guint32 header_value_length ;
const guint8 * header_name ;
const guint8 * header_value ;
2014-05-06 15:54:47 +00:00
int hoffset = 0 ;
nghttp2_hd_inflater * hd_inflater ;
tvbuff_t * header_tvb = tvb_new_composite ( ) ;
int rv ;
2014-06-23 10:25:33 +00:00
int header_len = 0 ;
2014-05-06 15:54:47 +00:00
int final ;
2018-04-19 15:48:19 +00:00
guint32 flow_index ;
2014-06-23 10:25:33 +00:00
http2_header_data_t * header_data ;
2014-08-04 12:06:14 +00:00
http2_header_repr_info_t * header_repr_info ;
2014-06-23 10:25:33 +00:00
wmem_list_t * header_list ;
wmem_array_t * headers ;
guint i ;
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
const gchar * method_header_value = NULL ;
const gchar * path_header_value = NULL ;
2017-07-30 13:39:11 +00:00
http2_header_stream_info_t * header_stream_info ;
2018-12-19 12:08:41 +00:00
gchar * header_unescaped = NULL ;
2014-06-23 10:25:33 +00:00
2016-02-05 14:41:57 +00:00
if ( ! http2_hdrcache_map ) {
http2_hdrcache_map = wmem_map_new ( wmem_file_scope ( ) , http2_hdrcache_hash , http2_hdrcache_equal ) ;
}
2014-06-23 10:25:33 +00:00
header_data = ( http2_header_data_t * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_http2 , 0 ) ;
header_list = header_data - > header_list ;
if ( ! PINFO_FD_VISITED ( pinfo ) ) {
/* This packet has not been processed yet, which means this is
the first linear scan . We do header decompression only
once in linear scan and cache the result . If we don ' t
cache , already processed data will be fed into decompressor
again and again since dissector will be called randomly .
This makes context out - of - sync . */
2016-02-05 14:41:57 +00:00
int decompressed_bytes = 0 ;
2014-06-23 10:25:33 +00:00
2018-07-22 18:51:06 +00:00
/* Make sure the length isn't too large. */
tvb_ensure_bytes_exist ( tvb , offset , headlen ) ;
2014-06-23 10:25:33 +00:00
headbuf = ( guint8 * ) wmem_alloc ( wmem_packet_scope ( ) , headlen ) ;
tvb_memcpy ( tvb , headbuf , offset , headlen ) ;
flow_index = select_http2_flow_index ( pinfo , h2session ) ;
hd_inflater = h2session - > hd_inflater [ flow_index ] ;
2014-08-04 12:06:14 +00:00
header_repr_info = & h2session - > header_repr_info [ flow_index ] ;
2014-06-23 10:25:33 +00:00
final = flags & HTTP2_FLAGS_END_HEADERS ;
headers = wmem_array_sized_new ( wmem_file_scope ( ) , sizeof ( http2_header_t ) , 16 ) ;
for ( ; ; ) {
nghttp2_nv nv ;
int inflate_flags = 0 ;
2016-02-05 14:41:57 +00:00
if ( wmem_array_get_count ( headers ) > = MAX_HTTP2_HEADER_LINES ) {
header_data - > header_lines_exceeded = TRUE ;
break ;
}
2014-06-23 10:25:33 +00:00
rv = ( int ) nghttp2_hd_inflate_hd ( hd_inflater , & nv ,
& inflate_flags , headbuf , headlen , final ) ;
if ( rv < 0 ) {
break ;
}
headbuf + = rv ;
headlen - = rv ;
2014-08-04 12:06:14 +00:00
rv - = process_http2_header_repr_info ( headers , header_repr_info , headbuf - rv , rv ) ;
2014-06-23 10:25:33 +00:00
if ( inflate_flags & NGHTTP2_HD_INFLATE_EMIT ) {
2016-02-05 14:41:57 +00:00
char * cached_pstr ;
2014-08-02 07:22:28 +00:00
guint32 len ;
2016-02-05 14:41:57 +00:00
guint datalen = ( guint ) ( 4 + nv . namelen + 4 + nv . valuelen ) ;
2014-06-23 10:25:33 +00:00
http2_header_t * out ;
2016-02-05 14:41:57 +00:00
if ( decompressed_bytes + datalen > = MAX_HTTP2_HEADER_SIZE ) {
header_data - > header_size_reached = decompressed_bytes ;
header_data - > header_size_attempted = decompressed_bytes + datalen ;
break ;
}
2014-06-23 10:25:33 +00:00
out = wmem_new ( wmem_file_scope ( ) , http2_header_t ) ;
2014-08-04 12:06:14 +00:00
out - > type = header_repr_info - > type ;
out - > length = rv ;
2015-09-03 02:53:05 +00:00
out - > table . data . idx = header_repr_info - > integer ;
2014-08-04 12:06:14 +00:00
2016-02-05 14:41:57 +00:00
out - > table . data . datalen = datalen ;
decompressed_bytes + = datalen ;
2014-06-23 10:25:33 +00:00
/* Prepare buffer... with the following format
name length ( uint32 )
name ( string )
value length ( uint32 )
value ( string )
*/
2016-02-05 14:41:57 +00:00
http2_header_pstr = ( char * ) wmem_realloc ( wmem_file_scope ( ) , http2_header_pstr , out - > table . data . datalen ) ;
2014-06-23 10:25:33 +00:00
/* nv.namelen and nv.valuelen are of size_t. In order
to get length in 4 bytes , we have to copy it to
2014-08-02 07:22:28 +00:00
guint32 . */
len = ( guint32 ) nv . namelen ;
2016-02-05 14:41:57 +00:00
phton32 ( & http2_header_pstr [ 0 ] , len ) ;
memcpy ( & http2_header_pstr [ 4 ] , nv . name , nv . namelen ) ;
2014-06-23 10:25:33 +00:00
2014-08-02 07:22:28 +00:00
len = ( guint32 ) nv . valuelen ;
2016-02-05 14:41:57 +00:00
phton32 ( & http2_header_pstr [ 4 + nv . namelen ] , len ) ;
memcpy ( & http2_header_pstr [ 4 + nv . namelen + 4 ] , nv . value , nv . valuelen ) ;
2014-06-23 10:25:33 +00:00
2016-02-05 14:41:57 +00:00
cached_pstr = ( char * ) wmem_map_lookup ( http2_hdrcache_map , http2_header_pstr ) ;
if ( cached_pstr ) {
out - > table . data . data = cached_pstr ;
} else {
wmem_map_insert ( http2_hdrcache_map , http2_header_pstr , http2_header_pstr ) ;
out - > table . data . data = http2_header_pstr ;
http2_header_pstr = NULL ;
}
2014-06-23 10:25:33 +00:00
wmem_array_append ( headers , out , 1 ) ;
2014-08-04 12:06:14 +00:00
reset_http2_header_repr_info ( header_repr_info ) ;
2014-06-23 10:25:33 +00:00
}
if ( inflate_flags & NGHTTP2_HD_INFLATE_FINAL ) {
nghttp2_hd_inflate_end_headers ( hd_inflater ) ;
break ;
}
if ( ( inflate_flags & NGHTTP2_HD_INFLATE_EMIT ) = = 0 & &
headlen = = 0 ) {
break ;
}
}
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
wmem_list_append ( header_list , headers ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
if ( ! header_data - > current ) {
header_data - > current = wmem_list_head ( header_list ) ;
}
2014-05-06 15:54:47 +00:00
2017-07-30 13:39:11 +00:00
/* add this packet headers to stream header list */
header_stream_info = get_header_stream_info ( pinfo , FALSE ) ;
if ( header_stream_info ) {
wmem_list_append ( header_stream_info - > stream_header_list , headers ) ;
}
2018-06-13 10:12:38 +00:00
} else if ( header_data - > current ) {
2014-06-23 10:25:33 +00:00
headers = ( wmem_array_t * ) wmem_list_frame_data ( header_data - > current ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
header_data - > current = wmem_list_frame_next ( header_data - > current ) ;
2014-05-06 15:54:47 +00:00
2014-06-23 10:25:33 +00:00
if ( ! header_data - > current ) {
header_data - > current = wmem_list_head ( header_list ) ;
2014-05-06 15:54:47 +00:00
}
2018-06-13 10:12:38 +00:00
} else {
return ;
2014-06-23 10:25:33 +00:00
}
2014-05-06 15:54:47 +00:00
2014-07-16 13:41:27 +00:00
if ( wmem_array_get_count ( headers ) = = 0 ) {
return ;
}
2014-06-23 10:25:33 +00:00
for ( i = 0 ; i < wmem_array_get_count ( headers ) ; + + i ) {
http2_header_t * in ;
tvbuff_t * next_tvb ;
in = ( http2_header_t * ) wmem_array_index ( headers , i ) ;
2014-08-04 12:06:14 +00:00
if ( in - > type = = HTTP2_HD_HEADER_TABLE_SIZE_UPDATE ) {
continue ;
}
2014-08-13 00:39:07 +00:00
header_len + = in - > table . data . datalen ;
2014-06-23 10:25:33 +00:00
/* Now setup the tvb buffer to have the new data */
2016-02-05 14:41:57 +00:00
next_tvb = tvb_new_child_real_data ( tvb , in - > table . data . data , in - > table . data . datalen , in - > table . data . datalen ) ;
2014-06-23 10:25:33 +00:00
tvb_composite_append ( header_tvb , next_tvb ) ;
2014-05-06 15:54:47 +00:00
}
2014-06-23 10:25:33 +00:00
2014-05-06 15:54:47 +00:00
tvb_composite_finalize ( header_tvb ) ;
add_new_data_source ( pinfo , header_tvb , " Decompressed Header " ) ;
ti = proto_tree_add_uint ( tree , hf_http2_header_length , header_tvb , hoffset , 1 , header_len ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2016-02-05 14:41:57 +00:00
if ( header_data - > header_size_attempted > 0 ) {
expert_add_info_format ( pinfo , ti , & ei_http2_header_size ,
" Decompression stopped after %u bytes (%u attempted). " ,
header_data - > header_size_reached ,
header_data - > header_size_attempted ) ;
}
ti = proto_tree_add_uint ( tree , hf_http2_header_count , header_tvb , hoffset , 1 , wmem_array_get_count ( headers ) ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
if ( header_data - > header_lines_exceeded ) {
expert_add_info ( pinfo , ti , & ei_http2_header_lines ) ;
}
2014-08-04 12:06:14 +00:00
for ( i = 0 ; i < wmem_array_get_count ( headers ) ; + + i ) {
http2_header_t * in = ( http2_header_t * ) wmem_array_index ( headers , i ) ;
if ( in - > type = = HTTP2_HD_HEADER_TABLE_SIZE_UPDATE ) {
header = proto_tree_add_item ( tree , hf_http2_header_table_size_update , tvb , offset , in - > length , ENC_NA ) ;
header_tree = proto_item_add_subtree ( header , ett_http2_headers ) ;
2014-08-13 00:39:07 +00:00
proto_tree_add_uint ( header_tree , hf_http2_header_table_size , tvb , offset , in - > length , in - > table . header_table_size ) ;
2014-08-04 12:06:14 +00:00
offset + = in - > length ;
continue ;
}
2014-05-06 15:54:47 +00:00
/* Populate tree with header name/value details. */
/* Add 'Header' subtree with description. */
2014-08-04 12:06:14 +00:00
header = proto_tree_add_item ( tree , hf_http2_header , tvb , offset , in - > length , ENC_NA ) ;
2014-05-06 15:54:47 +00:00
header_tree = proto_item_add_subtree ( header , ett_http2_headers ) ;
/* header value length */
2017-11-30 03:39:14 +00:00
proto_tree_add_item_ret_uint ( header_tree , hf_http2_header_name_length , header_tvb , hoffset , 4 , ENC_BIG_ENDIAN , & header_name_length ) ;
2014-05-06 15:54:47 +00:00
hoffset + = 4 ;
/* Add header name. */
2017-11-30 03:39:14 +00:00
proto_tree_add_item_ret_string ( header_tree , hf_http2_header_name , header_tvb , hoffset , header_name_length , ENC_ASCII | ENC_NA , wmem_packet_scope ( ) , & header_name ) ;
2014-05-06 15:54:47 +00:00
hoffset + = header_name_length ;
/* header value length */
2017-11-30 03:39:14 +00:00
proto_tree_add_item_ret_uint ( header_tree , hf_http2_header_value_length , header_tvb , hoffset , 4 , ENC_BIG_ENDIAN , & header_value_length ) ;
2014-05-06 15:54:47 +00:00
hoffset + = 4 ;
/* Add header value. */
2017-11-30 03:39:14 +00:00
proto_tree_add_item_ret_string ( header_tree , hf_http2_header_value , header_tvb , hoffset , header_value_length , ENC_ASCII | ENC_NA , wmem_packet_scope ( ) , & header_value ) ;
2017-11-18 02:09:50 +00:00
// check if field is http2 header https://tools.ietf.org/html/rfc7541#appendix-A
try_add_named_header_field ( header_tree , header_tvb , hoffset , header_value_length , header_name , header_value ) ;
2018-12-19 12:08:41 +00:00
/* Add header unescaped. */
header_unescaped = g_uri_unescape_string ( header_value , NULL ) ;
if ( header_unescaped ! = NULL ) {
ti = proto_tree_add_string ( header_tree , hf_http2_header_unescaped , header_tvb , hoffset , header_value_length , header_unescaped ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
g_free ( header_unescaped ) ;
}
2014-05-06 15:54:47 +00:00
hoffset + = header_value_length ;
2017-03-27 10:48:26 +00:00
/* Only track HEADER and CONTINUATION frames part there of. Don't look at PUSH_PROMISE and trailing CONTINUATION.
* Only do it for the first pass in case the current layer changes , altering where the headers frame number ,
* http2_frame_num_t points to . */
if ( is_in_header_context ( tvb , pinfo ) & & ! PINFO_FD_VISITED ( pinfo ) ) {
populate_http_header_tracking ( tvb , pinfo , h2session , header_value_length , header_name , header_value ) ;
}
2014-08-04 12:06:14 +00:00
/* Add encoding representation */
2017-11-30 03:39:14 +00:00
// This should probably be a bitmask for the first bits, see https://tools.ietf.org/html/rfc7541#section-6
proto_tree_add_string ( header_tree , hf_http2_header_repr , tvb , offset , 1 , http2_header_repr_type [ in - > type ] . strptr ) ;
2014-08-04 12:06:14 +00:00
if ( in - > type = = HTTP2_HD_INDEXED | |
in - > type = = HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME | |
in - > type = = HTTP2_HD_LITERAL_INDEXED_NAME | |
in - > type = = HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME ) {
2017-11-30 03:39:14 +00:00
/* Only for HTTP2_HD_INDEXED, the index value covers the full
* " in->length " . In other cases , it is a subset . For simplicity ,
* just select 1 octet ( this might not be accurate though ) . */
guint index_length = in - > length ;
if ( in - > type ! = HTTP2_HD_INDEXED ) {
index_length = 1 ;
}
proto_tree_add_uint ( header_tree , hf_http2_header_index , tvb , offset , index_length , in - > table . data . idx ) ;
2014-08-04 12:06:14 +00:00
}
2014-05-06 15:54:47 +00:00
proto_item_append_text ( header , " : %s: %s " , header_name , header_value ) ;
2014-08-04 12:06:14 +00:00
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
/* Display :method, :path and :status in info column (just like http1.1 dissector does)*/
if ( strcmp ( header_name , HTTP2_HEADER_METHOD ) = = 0 ) {
method_header_value = header_value ;
try_append_method_path_info ( pinfo , tree , method_header_value , path_header_value ) ;
}
else if ( strcmp ( header_name , HTTP2_HEADER_PATH ) = = 0 ) {
path_header_value = header_value ;
try_append_method_path_info ( pinfo , tree , method_header_value , path_header_value ) ;
}
else if ( strcmp ( header_name , HTTP2_HEADER_STATUS ) = = 0 ) {
const gchar * reason_phase = val_to_str ( ( guint ) strtoul ( header_value , NULL , 10 ) , vals_http_status_code , " Unknown " ) ;
/* append response status and reason phrase to info column (for example, HEADERS: 200 OK) */
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " : " , " %s %s " , header_value , reason_phase ) ;
/* append response status and reason phrase to header_tree and Stream node */
proto_item_append_text ( header_tree , " %s " , reason_phase ) ;
proto_item_append_text ( tree , " , %s %s " , header_value , reason_phase ) ;
}
2014-08-04 12:06:14 +00:00
offset + = in - > length ;
2014-05-06 15:54:47 +00:00
}
}
2016-08-26 13:18:29 +00:00
# endif
2014-05-06 15:54:47 +00:00
2013-08-30 11:14:09 +00:00
static guint8
2014-04-25 14:29:10 +00:00
dissect_http2_header_flags ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 type )
2013-08-30 11:14:09 +00:00
{
proto_item * ti_flags ;
proto_tree * flags_tree ;
guint8 flags ;
2014-12-13 17:52:20 +00:00
ti_flags = proto_tree_add_item ( http2_tree , hf_http2_flags , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
flags_tree = proto_item_add_subtree ( ti_flags , ett_http2_flags ) ;
flags = tvb_get_guint8 ( tvb , offset ) ;
switch ( type ) {
case HTTP2_DATA :
proto_tree_add_item ( flags_tree , hf_http2_flags_end_stream , tvb , offset , 1 , ENC_NA ) ;
2014-06-23 14:21:15 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_padded , tvb , offset , 1 , ENC_NA ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_unused_data , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
break ;
2013-08-30 11:14:09 +00:00
case HTTP2_HEADERS :
proto_tree_add_item ( flags_tree , hf_http2_flags_end_stream , tvb , offset , 1 , ENC_NA ) ;
proto_tree_add_item ( flags_tree , hf_http2_flags_end_headers , tvb , offset , 1 , ENC_NA ) ;
2014-06-23 14:21:15 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_padded , tvb , offset , 1 , ENC_NA ) ;
2013-08-30 11:14:09 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_priority , tvb , offset , 1 , ENC_NA ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_unused_headers , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
break ;
2013-08-30 11:14:09 +00:00
case HTTP2_SETTINGS :
2013-12-15 19:07:40 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_settings_ack , tvb , offset , 1 , ENC_NA ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_unused_settings , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
break ;
case HTTP2_PUSH_PROMISE :
2014-06-23 14:21:15 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_end_headers , tvb , offset , 1 , ENC_NA ) ;
proto_tree_add_item ( flags_tree , hf_http2_flags_padded , tvb , offset , 1 , ENC_NA ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_unused_push_promise , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-06-23 14:21:15 +00:00
break ;
2014-04-25 14:29:10 +00:00
case HTTP2_CONTINUATION :
proto_tree_add_item ( flags_tree , hf_http2_flags_end_headers , tvb , offset , 1 , ENC_NA ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_unused_continuation , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
break ;
case HTTP2_PING :
proto_tree_add_item ( flags_tree , hf_http2_flags_ping_ack , tvb , offset , 1 , ENC_NA ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_unused_ping , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
break ;
2014-05-12 07:00:52 +00:00
case HTTP2_PRIORITY :
case HTTP2_RST_STREAM :
2013-08-30 11:14:09 +00:00
case HTTP2_GOAWAY :
case HTTP2_WINDOW_UPDATE :
2014-04-25 14:29:10 +00:00
case HTTP2_ALTSVC :
case HTTP2_BLOCKED :
2013-08-30 11:14:09 +00:00
default :
2014-05-12 07:00:52 +00:00
/* Does not define any flags */
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( flags_tree , hf_http2_flags_unused , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
break ;
2013-08-30 11:14:09 +00:00
}
return flags ;
}
2014-04-25 14:29:10 +00:00
/* helper function to get the padding data for the frames that feature them */
static guint
dissect_frame_padding ( tvbuff_t * tvb , guint16 * padding , proto_tree * http2_tree ,
guint offset , guint8 flags )
2013-08-30 11:14:09 +00:00
{
2014-05-12 07:00:52 +00:00
proto_item * ti ;
guint pad_len = 0 ;
2014-04-25 14:29:10 +00:00
* padding = 0 ;
2013-08-30 11:14:09 +00:00
2014-06-23 14:21:15 +00:00
if ( flags & HTTP2_FLAGS_PADDED )
2013-08-30 11:14:09 +00:00
{
2014-06-23 14:21:15 +00:00
* padding = tvb_get_guint8 ( tvb , offset ) ; /* read a single octet */
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( http2_tree , hf_http2_padding , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
offset + + ;
2014-05-12 07:00:52 +00:00
pad_len + + ;
2013-08-30 11:14:09 +00:00
}
2014-05-12 07:00:52 +00:00
ti = proto_tree_add_uint ( http2_tree , hf_http2_pad_length , tvb , offset - pad_len , pad_len , * padding ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2013-08-30 11:14:09 +00:00
return offset ;
}
2014-04-25 14:29:10 +00:00
/* helper function to get the priority dependence for the frames that feature them:
HEADERS and PRIORITY */
static guint
dissect_frame_prio ( tvbuff_t * tvb , proto_tree * http2_tree , guint offset , guint8 flags )
{
2014-05-13 15:49:24 +00:00
proto_tree * ti ;
guint8 weight ;
2014-04-25 14:29:10 +00:00
if ( flags & HTTP2_FLAGS_PRIORITY )
{
2014-05-13 15:49:24 +00:00
proto_tree_add_item ( http2_tree , hf_http2_excl_dependency , tvb , offset , 4 , ENC_NA ) ;
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_stream_dependency , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
offset + = 4 ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( http2_tree , hf_http2_weight , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2014-05-13 15:49:24 +00:00
weight = tvb_get_guint8 ( tvb , offset ) ;
/* 6.2: Weight: An 8-bit weight for the stream; Add one to the value to obtain a weight between 1 and 256 */
ti = proto_tree_add_uint ( http2_tree , hf_http2_weight_real , tvb , offset , 1 , weight + 1 ) ;
PROTO_ITEM_SET_GENERATED ( ti ) ;
2014-04-25 14:29:10 +00:00
offset + + ;
}
return offset ;
}
2017-03-27 10:48:26 +00:00
# ifdef HAVE_NGHTTP2
static int
can_uncompress_body ( packet_info * pinfo )
{
http2_data_stream_body_info_t * body_info = get_data_stream_body_info ( pinfo ) ;
gchar * content_encoding = body_info - > content_encoding ;
/* Check we have a content-encoding header appropriate as well as checking if this is partial content.
* We can ' t decompress part of a gzip encoded entity */
return http2_decompress_body
& & body_info - > is_partial_content = = FALSE
& & content_encoding ! = NULL
& & ( strncmp ( content_encoding , " gzip " , 4 ) = = 0 | | strncmp ( content_encoding , " deflate " , 7 ) = = 0 ) ;
}
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
/* Try to dissect reassembled http2.data.data according to content_type. */
static void
dissect_body_data ( proto_tree * tree , packet_info * pinfo , tvbuff_t * tvb ,
const gint start , gint length , const guint encoding )
{
http2_data_stream_body_info_t * body_info = get_data_stream_body_info ( pinfo ) ;
gchar * content_type = body_info - > content_type ;
2019-01-21 15:41:53 +00:00
http_message_info_t metadata_used_for_media_type_handle = { HTTP_OTHERS , body_info - > content_type_parameters , NULL , NULL } ;
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
proto_tree_add_item ( tree , hf_http2_data_data , tvb , start , length , encoding ) ;
if ( content_type ! = NULL ) {
/* add it to STREAM level */
2017-07-24 15:47:53 +00:00
proto_tree * ptree = proto_tree_get_parent_tree ( tree ) ;
2017-08-20 05:15:28 +00:00
dissector_try_string ( media_type_dissector_table , content_type , tvb_new_subset_length ( tvb , start , length ) , pinfo ,
ptree , & metadata_used_for_media_type_handle ) ;
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
}
}
2017-03-27 10:48:26 +00:00
static void
dissect_http2_data_full_body ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * http2_tree )
{
if ( ! tvb ) {
return ;
}
gint datalen = tvb_reported_length ( tvb ) ;
if ( can_uncompress_body ( pinfo ) ) {
proto_item * compressed_proto_item = NULL ;
tvbuff_t * uncompressed_tvb = tvb_child_uncompress ( tvb , tvb , 0 , datalen ) ;
http2_data_stream_body_info_t * body_info = get_data_stream_body_info ( pinfo ) ;
gchar * compression_method = body_info - > content_encoding ;
proto_tree * compressed_entity_tree = proto_tree_add_subtree_format ( http2_tree , tvb , 0 , datalen , ett_http2_encoded_entity ,
& compressed_proto_item , " Content-encoded entity body (%s): %u bytes " ,
compression_method = = NULL ? " unknown " : compression_method , datalen
) ;
if ( uncompressed_tvb ! = NULL ) {
guint uncompressed_length = tvb_captured_length ( uncompressed_tvb ) ;
add_new_data_source ( pinfo , uncompressed_tvb , " Uncompressed entity body " ) ;
proto_item_append_text ( compressed_proto_item , " -> %u bytes " , uncompressed_length ) ;
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
dissect_body_data ( compressed_entity_tree , pinfo , uncompressed_tvb , 0 , uncompressed_length , ENC_NA ) ;
2017-03-27 10:48:26 +00:00
} else {
proto_tree_add_expert ( compressed_entity_tree , pinfo , & ei_http2_body_decompression_failed , tvb , 0 , datalen ) ;
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
dissect_body_data ( compressed_entity_tree , pinfo , tvb , 0 , datalen , ENC_NA ) ;
2017-03-27 10:48:26 +00:00
}
} else {
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
dissect_body_data ( http2_tree , pinfo , tvb , 0 , datalen , ENC_NA ) ;
2017-03-27 10:48:26 +00:00
}
}
static int
should_attempt_to_reassemble_data_frame ( http2_data_stream_reassembly_info_t * reassembly , packet_info * pinfo )
{
/* If we haven't captured the header frame with the request/response we don't know how many data
* frames we might have lost before processing */
if ( reassembly - > data_initiated_in = = 0 ) {
return FALSE ;
}
/* For now, do not reassemble transfer encoded bodies. Chunked encoding is explicitly disallowed by RFC7540,
* section 8.1 . Additionally , section 8.1 .2 .2 specifies that the only valid value for the TE header ( indicating
* which transfer - encoding is allowed ) is trailers , suggesting transfer coding other than chunked ( gzip ,
* deflate , etc ) are not allowed */
if ( reassembly - > has_transfer_encoded_body ) {
return FALSE ;
}
/* Is this data frame part of an established tunnel? Don't try to reassemble the data if that is the case */
http2_stream_info_t * stream_info = get_stream_info ( get_http2_session ( pinfo ) ) ;
if ( stream_info - > is_stream_http_connect ) {
return FALSE ;
}
return TRUE ;
}
static guint32
get_reassembly_id_from_stream ( packet_info * pinfo )
{
http2_session_t * session = get_http2_session ( pinfo ) ;
http2_stream_info_t * stream_info = get_stream_info ( session ) ;
2018-04-19 15:48:19 +00:00
guint32 flow_index = select_http2_flow_index ( pinfo , session ) ;
2017-03-27 10:48:26 +00:00
/* With a stream ID being 31 bits, use the most significant bit to determine the flow direction of the
* stream . We use this for the ID in the body reassembly using the reassemble API */
return stream_info - > stream_id | ( flow_index < < 31 ) ;
}
static tvbuff_t *
reassemble_http2_data_into_full_frame ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * http2_tree , guint offset ,
guint8 flags , guint datalen )
{
http2_data_stream_reassembly_info_t * reassembly = get_data_reassembly_info ( pinfo ) ;
/* There are a number of conditions as to why we may not want to reassemble DATA frames */
if ( ! should_attempt_to_reassemble_data_frame ( reassembly , pinfo ) ) {
return NULL ;
}
/* Continue to add fragments, checking if we have any more fragments */
guint32 reassembly_id = get_reassembly_id_from_stream ( pinfo ) ;
fragment_head * head = NULL ;
if ( IS_HTTP2_END_STREAM ( flags ) & & datalen = = 0 ) {
/* Workaround displaying "[Frame: N (no data)]" for a HTTP2 frame that contains no data but ends the stream */
head = fragment_end_seq_next ( & http2_body_reassembly_table , pinfo , reassembly_id , NULL ) ;
} else {
head = fragment_add_seq_next ( & http2_body_reassembly_table , tvb , offset , pinfo , reassembly_id , NULL ,
datalen , ! IS_HTTP2_END_STREAM ( flags ) ) ;
}
/* Only call this if its the last DATA frame (END_STREAM) as the check in process_reassembled_data() will
* incorrectly match for frames that exist in the same packet as the final DATA frame and incorrectly add
* reassembly information to those dissection trees */
if ( head & & IS_HTTP2_END_STREAM ( flags ) ) {
return process_reassembled_data ( tvb , offset , pinfo , " Reassembled body " , head ,
& http2_body_fragment_items , NULL , http2_tree ) ;
}
/* Add frame where reassembly happened. process_reassembled_data() does this automatically if the reassembled
* packet matches the packet that is calling the function , but makes some incorrect assumptions for multiple
* fragments contained in the same packet */
if ( head ) {
proto_tree_add_uint ( http2_tree , hf_http2_body_reassembled_in , tvb , 0 , 0 ,
head - > reassembled_in ) ;
}
/* Reassembly not complete yet*/
return NULL ;
}
static void
dissect_http2_data_partial_body ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * http2_tree , guint offset , gint length ,
guint8 flags )
{
http2_data_stream_reassembly_info_t * reassembly = get_data_reassembly_info ( pinfo ) ;
/* Is the frame part of a body that is going to be reassembled? */
if ( ! IS_HTTP2_END_STREAM ( flags ) ) {
proto_item_append_text ( http2_tree , " (partial entity body) " ) ;
}
/* If we somehow got a transfer-encoded body, display it here */
if ( reassembly - > has_transfer_encoded_body ) {
proto_item_append_text ( http2_tree , " (transfer-encoded body) " ) ;
}
/* Is this part of a tunneled connection? */
http2_stream_info_t * stream_info = get_stream_info ( get_http2_session ( pinfo ) ) ;
if ( stream_info - > is_stream_http_connect ) {
proto_item_append_text ( http2_tree , " (tunneled data) " ) ;
}
proto_tree_add_item ( http2_tree , hf_http2_data_data , tvb , offset , length , ENC_NA ) ;
}
static void
dissect_http2_data_body ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * http2_tree , guint offset , guint8 flags , gint length )
{
tvbuff_t * data_tvb = reassemble_http2_data_into_full_frame ( tvb , pinfo , http2_tree , offset , flags , length ) ;
if ( data_tvb ! = NULL ) {
dissect_http2_data_full_body ( data_tvb , pinfo , http2_tree ) ;
} else {
dissect_http2_data_partial_body ( tvb , pinfo , http2_tree , offset , length , flags ) ;
}
}
2017-07-30 13:39:11 +00:00
/* Get header value from current or the other direction stream_header_list */
const gchar *
http2_get_header_value ( packet_info * pinfo , const gchar * name , gboolean the_other_direction )
{
http2_header_stream_info_t * header_stream_info ;
wmem_list_frame_t * frame ;
wmem_array_t * headers ;
guint i ;
guint32 name_len ;
guint32 value_len ;
http2_header_t * hdr ;
gchar * data ;
header_stream_info = get_header_stream_info ( pinfo , the_other_direction ) ;
if ( ! header_stream_info ) {
return NULL ;
}
for ( frame = wmem_list_head ( header_stream_info - > stream_header_list ) ;
frame ;
frame = wmem_list_frame_next ( frame ) )
{ /* each frame contains one HEADERS or CONTINUATION frame's headers */
headers = ( wmem_array_t * ) wmem_list_frame_data ( frame ) ;
if ( ! headers ) {
continue ;
}
for ( i = 0 ; i < wmem_array_get_count ( headers ) ; + + i ) {
hdr = ( http2_header_t * ) wmem_array_index ( headers , i ) ;
if ( hdr - > type = = HTTP2_HD_HEADER_TABLE_SIZE_UPDATE ) {
continue ;
}
/* parsing data as format:
name length ( uint32 )
name ( string )
value length ( uint32 )
value ( string )
*/
data = ( gchar * ) hdr - > table . data . data ;
name_len = pntoh32 ( data ) ;
if ( strlen ( name ) = = name_len & & strncmp ( data + 4 , name , name_len ) = = 0 ) {
value_len = pntoh32 ( data + 4 + name_len ) ;
if ( 4 + name_len + 4 + value_len = = hdr - > table . data . datalen ) {
/* return value */
return wmem_strndup ( wmem_packet_scope ( ) , data + 4 + name_len + 4 , value_len ) ;
}
else {
return NULL ; /* unexpected error */
}
}
}
}
return NULL ;
}
2017-03-27 10:48:26 +00:00
# else
static void
dissect_http2_data_body ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 flags _U_ , gint datalen )
{
proto_tree_add_item ( http2_tree , hf_http2_data_data , tvb , offset , datalen , ENC_NA ) ;
}
2017-07-30 13:39:11 +00:00
const gchar *
http2_get_header_value ( packet_info * pinfo _U_ , const gchar * name _U_ , gboolean the_other_direction _U_ )
{
return NULL ;
}
2017-03-27 10:48:26 +00:00
# endif
2014-04-25 14:29:10 +00:00
/* Data (0) */
2013-08-30 11:14:09 +00:00
static int
2017-03-27 10:48:26 +00:00
dissect_http2_data ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * http2_tree ,
2014-04-25 14:29:10 +00:00
guint offset , guint8 flags )
2013-08-30 11:14:09 +00:00
{
2014-04-25 14:29:10 +00:00
guint16 padding ;
2014-04-28 03:16:19 +00:00
gint datalen ;
2013-08-30 11:14:09 +00:00
2014-04-25 14:29:10 +00:00
offset = dissect_frame_padding ( tvb , & padding , http2_tree , offset , flags ) ;
datalen = tvb_reported_length_remaining ( tvb , offset ) - padding ;
2017-03-27 10:48:26 +00:00
dissect_http2_data_body ( tvb , pinfo , http2_tree , offset , flags , datalen ) ;
2014-04-25 14:29:10 +00:00
offset + = datalen ;
2013-08-30 11:14:09 +00:00
2017-06-12 20:59:22 +00:00
if ( padding ) {
proto_tree_add_item ( http2_tree , hf_http2_data_padding , tvb , offset , padding , ENC_NA ) ;
offset + = padding ;
}
2014-04-25 14:29:10 +00:00
return offset ;
}
/* Headers */
static int
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2016-02-05 14:41:57 +00:00
dissect_http2_headers ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * http2_tree ,
2014-04-25 14:29:10 +00:00
guint offset , guint8 flags )
2016-08-26 13:18:29 +00:00
# else
dissect_http2_headers ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree ,
guint offset , guint8 flags )
# endif
2014-04-25 14:29:10 +00:00
{
guint16 padding ;
2014-04-28 03:16:19 +00:00
gint headlen ;
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-05-06 15:54:47 +00:00
http2_session_t * h2session ;
h2session = get_http2_session ( pinfo ) ;
2017-03-27 10:48:26 +00:00
/* Trailing headers coming after a DATA stream should have END_STREAM set. DATA should be complete
* so try to reassemble DATA fragments if that is the case */
if ( IS_HTTP2_END_STREAM ( flags ) ) {
fragment_head * head = fragment_end_seq_next ( & http2_body_reassembly_table , pinfo , get_reassembly_id_from_stream ( pinfo ) , NULL ) ;
if ( head ) {
tvbuff_t * reassembled_data = process_reassembled_data ( tvb , 0 , pinfo , " Reassembled body " , head ,
& http2_body_fragment_items , NULL , http2_tree ) ;
dissect_http2_data_full_body ( reassembled_data , pinfo , http2_tree ) ;
}
}
/* Mark this frame as the first header frame seen and last if the END_HEADERS flag
* is set . We use this to ensure when we read header values , we are not reading ones
* that have come from a PUSH_PROMISE header ( and associated CONTINUATION frames ) */
2017-07-30 13:39:11 +00:00
http2_header_stream_info_t * stream_info = get_header_stream_info ( pinfo , FALSE ) ;
2017-03-27 10:48:26 +00:00
if ( stream_info - > header_start_in = = 0 ) {
stream_info - > header_start_in = get_http2_frame_num ( tvb , pinfo ) ;
}
if ( stream_info - > header_end_in = = 0 & & flags & HTTP2_FLAGS_END_HEADERS ) {
stream_info - > header_end_in = get_http2_frame_num ( tvb , pinfo ) ;
}
2016-08-26 13:18:29 +00:00
# endif
2014-04-25 14:29:10 +00:00
offset = dissect_frame_padding ( tvb , & padding , http2_tree , offset , flags ) ;
offset = dissect_frame_prio ( tvb , http2_tree , offset , flags ) ;
2018-07-22 18:51:06 +00:00
headlen = tvb_reported_length_remaining ( tvb , offset ) ;
if ( headlen < padding ) {
/* XXX - what error *should* be reported here? */
THROW ( ReportedBoundsError ) ;
}
headlen - = padding ;
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_headers , tvb , offset , headlen , ENC_NA ) ;
2014-05-12 07:00:52 +00:00
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-05-06 15:54:47 +00:00
/* decompress the header block */
inflate_http2_header_block ( tvb , pinfo , offset , http2_tree , headlen , h2session , flags ) ;
2016-08-26 13:18:29 +00:00
# endif
2014-05-06 15:54:47 +00:00
2014-04-25 14:29:10 +00:00
offset + = headlen ;
2017-06-12 20:59:22 +00:00
if ( padding ) {
proto_tree_add_item ( http2_tree , hf_http2_headers_padding , tvb , offset , padding , ENC_NA ) ;
offset + = padding ;
}
2014-04-25 14:29:10 +00:00
return offset ;
}
/* Priority */
static int
dissect_http2_priority ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree ,
guint offset , guint8 flags )
{
/* we pretend the HTTP2_FLAGS_PRIORITY flag is set to share the dissect
function */
offset = dissect_frame_prio ( tvb , http2_tree , offset ,
flags | HTTP2_FLAGS_PRIORITY ) ;
2013-08-30 11:14:09 +00:00
return offset ;
}
/* RST Stream */
static int
dissect_http2_rst_stream ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 flags _U_ )
{
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_rst_stream_error , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
offset + = 4 ;
return offset ;
}
/* Settings */
static int
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-06-23 10:25:33 +00:00
dissect_http2_settings ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 flags )
2016-08-26 13:18:29 +00:00
# else
dissect_http2_settings ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 flags _U_ )
# endif
2013-08-30 11:14:09 +00:00
{
guint32 settingsid ;
proto_item * ti_settings ;
proto_tree * settings_tree ;
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-08-02 07:22:28 +00:00
guint32 header_table_size ;
guint32 min_header_table_size ;
2014-06-23 10:25:33 +00:00
int header_table_size_found ;
http2_session_t * h2session ;
2013-08-30 11:14:09 +00:00
2014-06-23 10:25:33 +00:00
header_table_size_found = 0 ;
header_table_size = 0 ;
2014-08-02 07:22:28 +00:00
min_header_table_size = 0xFFFFFFFFu ;
2016-08-26 13:18:29 +00:00
# endif
2014-05-06 15:54:47 +00:00
2013-08-30 11:14:09 +00:00
while ( tvb_reported_length_remaining ( tvb , offset ) > 0 ) {
2018-11-19 21:01:53 +00:00
ti_settings = proto_tree_add_item ( http2_tree , hf_http2_settings , tvb , offset , 6 , ENC_NA ) ;
2013-08-30 11:14:09 +00:00
settings_tree = proto_item_add_subtree ( ti_settings , ett_http2_settings ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_identifier , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
2014-06-23 14:21:15 +00:00
settingsid = tvb_get_ntohs ( tvb , offset ) ;
2014-04-25 14:29:10 +00:00
proto_item_append_text ( ti_settings , " - %s " ,
val_to_str ( settingsid , http2_settings_vals , " Unknown (%u) " ) ) ;
2014-06-23 14:21:15 +00:00
offset + = 2 ;
2013-08-30 11:14:09 +00:00
switch ( settingsid ) {
2013-12-15 19:07:40 +00:00
case HTTP2_SETTINGS_HEADER_TABLE_SIZE :
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_header_table_size , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2014-06-23 10:25:33 +00:00
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-06-23 10:25:33 +00:00
/* We only care the last header table size in SETTINGS */
header_table_size_found = 1 ;
header_table_size = tvb_get_ntohl ( tvb , offset ) ;
2014-08-02 07:22:28 +00:00
if ( min_header_table_size > header_table_size ) {
min_header_table_size = header_table_size ;
}
2016-08-26 13:18:29 +00:00
# endif
2013-12-15 19:07:40 +00:00
break ;
case HTTP2_SETTINGS_ENABLE_PUSH :
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_enable_push , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-12-15 19:07:40 +00:00
break ;
2013-08-30 11:14:09 +00:00
case HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS :
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_max_concurrent_streams , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
break ;
case HTTP2_SETTINGS_INITIAL_WINDOW_SIZE :
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_initial_window_size , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
break ;
2014-08-02 07:22:28 +00:00
case HTTP2_SETTINGS_MAX_FRAME_SIZE :
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_max_frame_size , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2014-08-02 07:22:28 +00:00
break ;
case HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE :
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_max_header_list_size , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2014-08-02 07:22:28 +00:00
break ;
2013-08-30 11:14:09 +00:00
default :
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( settings_tree , hf_http2_settings_unknown , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
break ;
}
proto_item_append_text ( ti_settings , " : %u " , tvb_get_ntohl ( tvb , offset ) ) ;
offset + = 4 ;
}
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-06-23 10:25:33 +00:00
if ( ! PINFO_FD_VISITED ( pinfo ) ) {
h2session = get_http2_session ( pinfo ) ;
if ( flags & HTTP2_FLAGS_ACK ) {
apply_and_pop_settings ( pinfo , h2session ) ;
} else {
http2_settings_t * settings ;
settings = wmem_new ( wmem_file_scope ( ) , http2_settings_t ) ;
2014-08-02 07:22:28 +00:00
settings - > min_header_table_size = min_header_table_size ;
2014-06-23 10:25:33 +00:00
settings - > header_table_size = header_table_size ;
settings - > has_header_table_size = header_table_size_found ;
push_settings ( pinfo , h2session , settings ) ;
}
}
2016-08-26 13:18:29 +00:00
# endif
2014-06-23 10:25:33 +00:00
2013-08-30 11:14:09 +00:00
return offset ;
}
/* Push Promise */
static int
2014-04-25 14:29:10 +00:00
dissect_http2_push_promise ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree ,
guint offset , guint8 flags _U_ )
2013-08-30 11:14:09 +00:00
{
2014-04-25 14:29:10 +00:00
guint16 padding ;
2014-05-12 07:00:52 +00:00
gint headlen ;
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-05-06 15:54:47 +00:00
http2_session_t * h2session ;
h2session = get_http2_session ( pinfo ) ;
2016-08-26 13:18:29 +00:00
# endif
2013-08-30 11:14:09 +00:00
2014-04-25 14:29:10 +00:00
offset = dissect_frame_padding ( tvb , & padding , http2_tree , offset , flags ) ;
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_push_promise_r , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2014-04-25 14:29:10 +00:00
proto_tree_add_item ( http2_tree , hf_http2_push_promise_promised_stream_id , tvb ,
2014-09-19 02:29:29 +00:00
offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
offset + = 4 ;
2018-07-22 18:51:06 +00:00
headlen = tvb_reported_length_remaining ( tvb , offset ) ;
if ( headlen < padding ) {
/* XXX - what error *should* be reported here? */
THROW ( ReportedBoundsError ) ;
}
headlen - = padding ;
2014-05-12 07:00:52 +00:00
proto_tree_add_item ( http2_tree , hf_http2_push_promise_header , tvb , offset , headlen ,
2016-08-24 17:53:04 +00:00
ENC_NA ) ;
2014-04-25 14:29:10 +00:00
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-05-06 15:54:47 +00:00
inflate_http2_header_block ( tvb , pinfo , offset , http2_tree , headlen , h2session , flags ) ;
2016-08-26 13:18:29 +00:00
# endif
2014-05-06 15:54:47 +00:00
2014-05-12 07:00:52 +00:00
offset + = headlen ;
2014-04-25 14:29:10 +00:00
2017-06-12 20:59:22 +00:00
if ( padding ) {
proto_tree_add_item ( http2_tree , hf_http2_push_promise_padding , tvb ,
offset , padding , ENC_NA ) ;
}
2014-04-25 14:29:10 +00:00
2013-08-30 11:14:09 +00:00
offset + = tvb_reported_length_remaining ( tvb , offset ) ;
return offset ;
}
/* Ping */
static int
2014-04-25 14:29:10 +00:00
dissect_http2_ping ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree ,
guint offset , guint8 flags )
2013-08-30 11:14:09 +00:00
{
/* TODO : Add Response time */
2013-12-15 19:07:40 +00:00
if ( flags & HTTP2_FLAGS_ACK )
2013-08-30 11:14:09 +00:00
{
proto_tree_add_item ( http2_tree , hf_http2_pong , tvb , offset , 8 , ENC_NA ) ;
} else {
proto_tree_add_item ( http2_tree , hf_http2_ping , tvb , offset , 8 , ENC_NA ) ;
}
offset + = 8 ;
return offset ;
}
/* Goaway */
static int
dissect_http2_goaway ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 flags _U_ )
{
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_goaway_r , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( http2_tree , hf_http2_goaway_last_stream_id , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
offset + = 4 ;
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_goaway_error , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
offset + = 4 ;
if ( tvb_reported_length_remaining ( tvb , offset ) > 0 )
{
proto_tree_add_item ( http2_tree , hf_http2_goaway_addata , tvb , offset , - 1 , ENC_NA ) ;
offset + = tvb_reported_length_remaining ( tvb , offset ) ;
}
return offset ;
}
/* Window Update */
static int
dissect_http2_window_update ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 flags _U_ )
{
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_window_update_r , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( http2_tree , hf_http2_window_update_window_size_increment , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
offset + = 4 ;
return offset ;
}
static int
2014-05-12 07:00:52 +00:00
dissect_http2_continuation ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree , guint offset , guint8 flags )
2013-08-30 11:14:09 +00:00
{
2014-05-12 07:00:52 +00:00
guint16 padding ;
gint headlen ;
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-05-06 15:54:47 +00:00
http2_session_t * h2session ;
h2session = get_http2_session ( pinfo ) ;
2017-03-27 10:48:26 +00:00
/* Mark this as the last CONTINUATION frame for a HEADERS frame. This is used to know the context when we read
* header ( is the source a HEADER frame or a PUSH_PROMISE frame ? ) */
if ( flags & HTTP2_FLAGS_END_HEADERS ) {
2017-07-30 13:39:11 +00:00
http2_header_stream_info_t * stream_info = get_header_stream_info ( pinfo , FALSE ) ;
2017-03-27 10:48:26 +00:00
if ( stream_info - > header_start_in ! = 0 & & stream_info - > header_end_in = = 0 ) {
stream_info - > header_end_in = get_http2_frame_num ( tvb , pinfo ) ;
}
}
2016-08-26 13:18:29 +00:00
# endif
2014-05-12 07:00:52 +00:00
offset = dissect_frame_padding ( tvb , & padding , http2_tree , offset , flags ) ;
2013-08-30 11:14:09 +00:00
2018-07-22 18:51:06 +00:00
headlen = tvb_reported_length_remaining ( tvb , offset ) ;
if ( headlen < padding ) {
/* XXX - what error *should* be reported here? */
THROW ( ReportedBoundsError ) ;
}
headlen - = padding ;
2014-05-12 07:00:52 +00:00
proto_tree_add_item ( http2_tree , hf_http2_continuation_header , tvb , offset , headlen , ENC_ASCII | ENC_NA ) ;
2016-08-26 13:18:29 +00:00
# ifdef HAVE_NGHTTP2
2014-05-06 15:54:47 +00:00
inflate_http2_header_block ( tvb , pinfo , offset , http2_tree , headlen , h2session , flags ) ;
2016-08-26 13:18:29 +00:00
# endif
2014-05-06 15:54:47 +00:00
2014-05-12 07:00:52 +00:00
offset + = headlen ;
2017-06-12 20:59:22 +00:00
if ( padding ) {
proto_tree_add_item ( http2_tree , hf_http2_continuation_padding , tvb , offset , padding , ENC_NA ) ;
offset + = padding ;
}
2013-08-30 11:14:09 +00:00
return offset ;
}
2014-04-25 14:29:10 +00:00
/* Altsvc */
static int
dissect_http2_altsvc ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * http2_tree ,
guint offset , guint8 flags _U_ , guint16 length )
{
2016-04-15 16:35:39 +00:00
guint32 origin_len ;
int remain = length ;
2014-04-25 14:29:10 +00:00
2016-04-15 16:35:39 +00:00
proto_tree_add_item_ret_uint ( http2_tree , hf_http2_altsvc_origin_len , tvb , offset , 2 , ENC_BIG_ENDIAN , & origin_len ) ;
2014-04-25 14:29:10 +00:00
offset + = 2 ;
2016-04-15 16:35:39 +00:00
remain - = 2 ;
2014-04-25 14:29:10 +00:00
2016-04-15 16:35:39 +00:00
proto_tree_add_item ( http2_tree , hf_http2_altsvc_origin , tvb , offset , origin_len , ENC_ASCII | ENC_NA ) ;
offset + = origin_len ;
remain - = origin_len ;
2014-04-25 14:29:10 +00:00
2016-04-15 16:35:39 +00:00
if ( remain ) {
proto_tree_add_item ( http2_tree , hf_http2_altsvc_field_value , tvb , offset , remain , ENC_ASCII | ENC_NA ) ;
2014-04-25 14:29:10 +00:00
offset + = remain ;
}
return offset ;
}
2016-08-18 06:07:00 +00:00
int
2013-11-09 17:46:28 +00:00
dissect_http2_pdu ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
2013-08-30 11:14:09 +00:00
{
proto_item * ti ;
proto_tree * http2_tree ;
guint offset = 0 ;
guint8 type , flags ;
guint16 length ;
guint32 streamid ;
2015-01-08 16:35:58 +00:00
struct HTTP2Tap * http2_stats ;
2013-08-30 11:14:09 +00:00
2014-06-23 10:25:33 +00:00
if ( ! p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_http2 , 0 ) ) {
http2_header_data_t * header_data ;
2016-02-05 14:41:57 +00:00
header_data = wmem_new0 ( wmem_file_scope ( ) , http2_header_data_t ) ;
2014-06-23 10:25:33 +00:00
header_data - > header_list = wmem_list_new ( wmem_file_scope ( ) ) ;
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_http2 , 0 , header_data ) ;
}
2013-08-30 11:14:09 +00:00
/* 4.1 Frame Format
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - +
2014-08-02 07:22:28 +00:00
| Length ( 24 ) |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
| Type ( 8 ) | Flags ( 8 ) |
+ - + - + - - - - - - - - - - - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2013-08-30 11:14:09 +00:00
| R | Stream Identifier ( 31 ) |
2014-08-02 07:22:28 +00:00
+ = + = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +
2013-08-30 11:14:09 +00:00
| Frame Payload ( 0. . . ) . . .
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2016-02-03 06:06:07 +00:00
ti = proto_tree_add_item ( tree , hf_http2_stream , tvb , 0 , - 1 , ENC_NA ) ;
2013-08-30 11:14:09 +00:00
http2_tree = proto_item_add_subtree ( ti , ett_http2_header ) ;
/* 3.5 Connection Header
Upon establishment of a TCP connection and determination that
2014-08-02 07:22:28 +00:00
HTTP / 2 will be used by both peers , each endpoint MUST send a
connection preface as a final confirmation and to establish the
initial SETTINGS parameters for the HTTP / 2 connection .
2013-08-30 11:14:09 +00:00
*/
/* tvb_memeql makes certain there are enough bytes in the buffer.
* returns - 1 if there are not enough bytes or if there is not a
* match . Returns 0 on a match
*/
if ( tvb_memeql ( tvb , offset , kMagicHello , MAGIC_FRAME_LENGTH ) = = 0 )
{
col_append_sep_str ( pinfo - > cinfo , COL_INFO , " , " , " Magic " ) ;
proto_item_set_len ( ti , MAGIC_FRAME_LENGTH ) ;
proto_item_append_text ( ti , " : Magic " ) ;
proto_tree_add_item ( http2_tree , hf_http2_magic , tvb , offset , MAGIC_FRAME_LENGTH , ENC_ASCII | ENC_NA ) ;
2014-05-12 07:00:52 +00:00
2013-11-09 17:46:28 +00:00
return MAGIC_FRAME_LENGTH ;
2013-08-30 11:14:09 +00:00
}
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_length , tvb , offset , 3 , ENC_BIG_ENDIAN ) ;
2014-08-02 07:22:28 +00:00
length = tvb_get_ntoh24 ( tvb , offset ) ;
offset + = 3 ;
2013-08-30 11:14:09 +00:00
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( http2_tree , hf_http2_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
type = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
flags = dissect_http2_header_flags ( tvb , pinfo , http2_tree , offset , type ) ;
offset + = 1 ;
2014-09-19 02:29:29 +00:00
proto_tree_add_item ( http2_tree , hf_http2_r , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( http2_tree , hf_http2_streamid , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
2013-08-30 11:14:09 +00:00
streamid = tvb_get_ntohl ( tvb , offset ) & MASK_HTTP2_STREAMID ;
proto_item_append_text ( ti , " : %s, Stream ID: %u, Length %u " , val_to_str ( type , http2_type_vals , " Unknown type (%d) " ) , streamid , length ) ;
offset + = 4 ;
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
/* append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3] */
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " , " , " %s[%u] " , val_to_str ( type , http2_type_vals , " Unknown type (%d) " ) , streamid ) ;
2017-03-27 10:48:26 +00:00
# ifdef HAVE_NGHTTP2
/* Mark the current stream, used for per-stream processing later in the dissection */
http2_session_t * http2_session = get_http2_session ( pinfo ) ;
http2_session - > current_stream_id = streamid ;
# endif
2015-01-08 16:35:58 +00:00
/* Collect stats */
http2_stats = wmem_new0 ( wmem_packet_scope ( ) , struct HTTP2Tap ) ;
http2_stats - > type = type ;
2013-08-30 11:14:09 +00:00
switch ( type ) {
case HTTP2_DATA : /* Data (0) */
2014-04-25 14:29:10 +00:00
dissect_http2_data ( tvb , pinfo , http2_tree , offset , flags ) ;
2013-08-30 11:14:09 +00:00
break ;
case HTTP2_HEADERS : /* Headers (1) */
dissect_http2_headers ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
case HTTP2_PRIORITY : /* Priority (2) */
dissect_http2_priority ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
case HTTP2_RST_STREAM : /* RST Stream (3) */
dissect_http2_rst_stream ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
case HTTP2_SETTINGS : /* Settings (4) */
dissect_http2_settings ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
case HTTP2_PUSH_PROMISE : /* PUSH Promise (5) */
dissect_http2_push_promise ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
case HTTP2_PING : /* Ping (6) */
dissect_http2_ping ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
case HTTP2_GOAWAY : /* Goaway (7) */
dissect_http2_goaway ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
2014-04-25 14:29:10 +00:00
case HTTP2_WINDOW_UPDATE : /* Window Update (8) */
2013-08-30 11:14:09 +00:00
dissect_http2_window_update ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
2014-04-25 14:29:10 +00:00
case HTTP2_CONTINUATION : /* Continuation (9) */
2013-08-30 11:14:09 +00:00
dissect_http2_continuation ( tvb , pinfo , http2_tree , offset , flags ) ;
break ;
2014-04-25 14:29:10 +00:00
case HTTP2_ALTSVC : /* ALTSVC (10) */
dissect_http2_altsvc ( tvb , pinfo , http2_tree , offset , flags , length ) ;
break ;
case HTTP2_BLOCKED : /* BLOCKED (11) */
/* no payload! */
break ;
2013-08-30 11:14:09 +00:00
default :
proto_tree_add_item ( http2_tree , hf_http2_unknown , tvb , offset , - 1 , ENC_NA ) ;
break ;
}
2015-01-08 16:35:58 +00:00
tap_queue_packet ( http2_tap , pinfo , http2_stats ) ;
2014-05-06 15:54:47 +00:00
return tvb_captured_length ( tvb ) ;
2013-08-30 11:14:09 +00:00
}
2015-01-25 19:30:13 +00:00
static guint get_http2_message_len ( packet_info * pinfo _U_ , tvbuff_t * tvb ,
int offset , void * data _U_ )
2013-08-30 11:14:09 +00:00
{
if ( tvb_memeql ( tvb , offset , kMagicHello , MAGIC_FRAME_LENGTH ) = = 0 ) {
return MAGIC_FRAME_LENGTH ;
}
2014-08-02 07:22:28 +00:00
return ( guint ) tvb_get_ntoh24 ( tvb , offset ) + FRAME_HEADER_LENGTH ;
2013-08-30 11:14:09 +00:00
}
static int
dissect_http2 ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree ,
2013-11-09 17:46:28 +00:00
void * data )
2013-08-30 11:14:09 +00:00
{
proto_item * ti ;
proto_tree * http2_tree ;
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " HTTP2 " ) ;
col_clear ( pinfo - > cinfo , COL_INFO ) ;
ti = proto_tree_add_item ( tree , proto_http2 , tvb , 0 , - 1 , ENC_NA ) ;
http2_tree = proto_item_add_subtree ( ti , ett_http2 ) ;
tcp_dissect_pdus ( tvb , pinfo , http2_tree , TRUE , FRAME_HEADER_LENGTH ,
2013-11-09 17:46:28 +00:00
get_http2_message_len , dissect_http2_pdu , data ) ;
2013-08-30 11:14:09 +00:00
2014-05-06 15:54:47 +00:00
return tvb_captured_length ( tvb ) ;
2013-08-30 11:14:09 +00:00
}
2013-11-29 08:02:09 +00:00
static gboolean
dissect_http2_heur ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data )
{
2015-03-10 11:05:25 +00:00
conversation_t * conversation ;
2015-03-21 16:33:50 +00:00
http2_session_t * session ;
conversation = find_or_create_conversation ( pinfo ) ;
session = ( http2_session_t * ) conversation_get_proto_data ( conversation ,
proto_http2 ) ;
/* A http2 conversation was previously started, assume it is still active */
if ( session ) {
dissect_http2 ( tvb , pinfo , tree , data ) ;
return TRUE ;
}
2013-12-23 09:42:10 +00:00
if ( tvb_memeql ( tvb , 0 , kMagicHello , MAGIC_FRAME_LENGTH ) ! = 0 ) {
2015-08-01 09:38:03 +00:00
/* we couldn't find the Magic Hello (PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n). */
return FALSE ;
2013-12-23 09:42:10 +00:00
}
2013-11-29 08:02:09 +00:00
2015-03-21 16:33:50 +00:00
/* Remember http2 conversation. */
get_http2_session ( pinfo ) ;
2013-11-29 08:02:09 +00:00
dissect_http2 ( tvb , pinfo , tree , data ) ;
return ( TRUE ) ;
}
2016-01-11 20:47:03 +00:00
static gboolean
dissect_http2_heur_ssl ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data )
{
dissector_handle_t * app_handle = ( dissector_handle_t * ) data ;
if ( dissect_http2_heur ( tvb , pinfo , tree , NULL ) ) {
* app_handle = http2_handle ;
return TRUE ;
}
return FALSE ;
}
2013-08-30 11:14:09 +00:00
void
proto_register_http2 ( void )
{
static hf_register_info hf [ ] = {
/* Packet Header */
2016-02-03 06:06:07 +00:00
{ & hf_http2_stream ,
{ " Stream " , " http2.stream " ,
2013-08-30 11:14:09 +00:00
FT_NONE , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_length ,
{ " Length " , " http2.length " ,
2014-08-02 07:22:28 +00:00
FT_UINT24 , BASE_DEC , NULL , 0x0 ,
" The length (24 bits) of the frame payload (The 9 octets of the frame header are not included) " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
{ & hf_http2_type ,
{ " Type " , " http2.type " ,
FT_UINT8 , BASE_DEC , VALS ( http2_type_vals ) , 0x0 ,
" The frame type determines how the remainder of the frame header and payload are interpreted " , HFILL }
} ,
{ & hf_http2_r ,
{ " Reserved " , " http2.r " ,
FT_UINT32 , BASE_HEX , NULL , MASK_HTTP2_RESERVED ,
" The semantics of this bit are undefined and the bit MUST remain unset (0) when sending and MUST be ignored when receiving " , HFILL }
} ,
2014-04-25 14:29:10 +00:00
{ & hf_http2_weight ,
{ " Weight " , " http2.headers.weight " ,
FT_UINT8 , BASE_DEC , NULL , 0x0 ,
" An 8-bit weight for the identified priority " , HFILL }
} ,
2014-05-13 15:49:24 +00:00
{ & hf_http2_weight_real ,
{ " Weight real " , " http2.headers.weight_real " ,
FT_UINT8 , BASE_DEC , NULL , 0x0 ,
" Real Weight value (Add one to value) " , HFILL }
} ,
2013-08-30 11:14:09 +00:00
{ & hf_http2_streamid ,
{ " Stream Identifier " , " http2.streamid " ,
FT_UINT32 , BASE_DEC , NULL , MASK_HTTP2_STREAMID ,
" A 31-bit stream identifier " , HFILL }
} ,
{ & hf_http2_magic ,
{ " Magic " , " http2.magic " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_unknown ,
{ " Unknown " , " http2.unknown " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
/* Flags */
{ & hf_http2_flags ,
{ " Flags " , " http2.flags " ,
FT_UINT8 , BASE_HEX , NULL , 0x0 ,
" Flags are assigned semantics specific to the indicated frame type " , HFILL }
} ,
{ & hf_http2_flags_end_stream ,
2014-04-25 14:29:10 +00:00
{ " End Stream " , " http2.flags.end_stream " ,
FT_BOOLEAN , 8 , NULL , HTTP2_FLAGS_END_STREAM ,
2013-12-15 19:07:40 +00:00
" Indicates that this frame is the last that the endpoint will send for the identified stream " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
{ & hf_http2_flags_end_headers ,
{ " End Headers " , " http2.flags.eh " ,
2014-04-25 14:29:10 +00:00
FT_BOOLEAN , 8 , NULL , HTTP2_FLAGS_END_HEADERS ,
2013-12-15 19:07:40 +00:00
" Indicates that this frame contains an entire header block and is not followed by any CONTINUATION frames. " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-06-23 14:21:15 +00:00
{ & hf_http2_flags_padded ,
{ " Padded " , " http2.flags.padded " ,
FT_BOOLEAN , 8 , NULL , HTTP2_FLAGS_PADDED ,
" Indicates that the Pad Length field is present " , HFILL }
2014-04-25 14:29:10 +00:00
} ,
2013-08-30 11:14:09 +00:00
{ & hf_http2_flags_priority ,
2014-04-25 14:29:10 +00:00
{ " Priority " , " http2.flags.priority " ,
FT_BOOLEAN , 8 , NULL , HTTP2_FLAGS_PRIORITY ,
" Indicates that the Exclusive Flag (E), Stream Dependency, and Weight fields are present " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-04-25 14:29:10 +00:00
2013-12-15 19:07:40 +00:00
{ & hf_http2_flags_ping_ack ,
{ " ACK " , " http2.flags.ack.ping " ,
FT_BOOLEAN , 8 , NULL , HTTP2_FLAGS_ACK ,
2013-08-30 11:14:09 +00:00
" Set indicates that this PING frame is a PING response " , HFILL }
} ,
2014-05-12 07:00:52 +00:00
{ & hf_http2_flags_unused ,
{ " Unused " , " http2.flags.unused " ,
2014-08-02 07:22:28 +00:00
FT_UINT8 , BASE_HEX , NULL , HTTP2_FLAGS_UNUSED ,
2014-05-12 07:00:52 +00:00
" Must be zero " , HFILL }
} ,
2014-06-23 14:21:15 +00:00
{ & hf_http2_flags_unused_settings ,
{ " Unused " , " http2.flags.unused_settings " ,
2014-08-02 07:22:28 +00:00
FT_UINT8 , BASE_HEX , NULL , HTTP2_FLAGS_UNUSED_SETTINGS ,
2014-05-12 07:00:52 +00:00
" Must be zero " , HFILL }
} ,
2014-06-23 14:21:15 +00:00
{ & hf_http2_flags_unused_ping ,
{ " Unused " , " http2.flags.unused_ping " ,
2014-08-02 07:22:28 +00:00
FT_UINT8 , BASE_HEX , NULL , HTTP2_FLAGS_UNUSED_PING ,
2014-06-23 14:21:15 +00:00
" Must be zero " , HFILL }
} ,
{ & hf_http2_flags_unused_continuation ,
{ " Unused " , " http2.flags.unused_continuation " ,
2014-08-02 07:22:28 +00:00
FT_UINT8 , BASE_HEX , NULL , HTTP2_FLAGS_UNUSED_CONTINUATION ,
2014-06-23 14:21:15 +00:00
" Must be zero " , HFILL }
} ,
{ & hf_http2_flags_unused_push_promise ,
{ " Unused " , " http2.flags.unused_push_promise " ,
2014-08-02 07:22:28 +00:00
FT_UINT8 , BASE_HEX , NULL , HTTP2_FLAGS_UNUSED_PUSH_PROMISE ,
2014-05-12 07:00:52 +00:00
" Must be zero " , HFILL }
} ,
{ & hf_http2_flags_unused_data ,
{ " Unused " , " http2.flags.unused_data " ,
2014-08-02 07:22:28 +00:00
FT_UINT8 , BASE_HEX , NULL , HTTP2_FLAGS_UNUSED_DATA ,
2014-05-12 07:00:52 +00:00
" Must be zero " , HFILL }
} ,
2014-06-23 14:21:15 +00:00
{ & hf_http2_flags_unused_headers ,
{ " Unused " , " http2.flags.unused_headers " ,
2014-08-02 07:22:28 +00:00
FT_UINT8 , BASE_HEX , NULL , HTTP2_FLAGS_UNUSED_HEADERS ,
2014-05-12 07:00:52 +00:00
" Must be zero " , HFILL }
} ,
2013-12-15 19:07:40 +00:00
{ & hf_http2_flags_settings_ack ,
{ " ACK " , " http2.flags.ack.settings " ,
FT_BOOLEAN , 8 , NULL , HTTP2_FLAGS_ACK ,
" Indicates that this frame acknowledges receipt and application of the peer's SETTINGS frame " , HFILL }
} ,
2014-06-23 14:21:15 +00:00
{ & hf_http2_padding ,
{ " Pad Length " , " http2.padding " ,
2014-04-25 14:29:10 +00:00
FT_UINT8 , BASE_HEX , NULL , 0x0 ,
2014-06-23 14:21:15 +00:00
" Padding size " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-05-12 07:00:52 +00:00
{ & hf_http2_pad_length ,
{ " Pad Length " , " http2.pad_length " ,
FT_UINT16 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
2014-04-25 14:29:10 +00:00
{ & hf_http2_excl_dependency ,
{ " Exclusive " , " http2.exclusive " ,
2014-05-13 15:49:24 +00:00
FT_BOOLEAN , 32 , NULL , 0x80000000 ,
2014-04-25 14:29:10 +00:00
" A single bit flag indicates that the stream dependency is exclusive " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-04-25 14:29:10 +00:00
{ & hf_http2_stream_dependency ,
{ " Stream Dependency " , " http2.stream_dependency " ,
2014-05-13 15:49:24 +00:00
FT_UINT32 , BASE_DEC , NULL , 0x7FFFFFFF ,
2014-04-25 14:29:10 +00:00
" An identifier for the stream that this stream depends on " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-04-25 14:29:10 +00:00
/* Data */
{ & hf_http2_data_data ,
{ " Data " , " http2.data.data " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" Application data " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-04-25 14:29:10 +00:00
{ & hf_http2_data_padding ,
{ " Padding " , " http2.data.padding " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" Padding octets " , HFILL }
} ,
2017-03-27 10:48:26 +00:00
/* Body fragments */
{ & hf_http2_body_fragments ,
{ " Body fragments " , " http2.body.fragments " ,
FT_NONE , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_fragment ,
{ " Body fragment " , " http2.body.fragment " ,
FT_FRAMENUM , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_fragment_overlap ,
{ " Body fragment overlap " , " http2.body.fragment.overlap " ,
FT_BOOLEAN , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_fragment_overlap_conflicts ,
{ " Body fragment overlapping with conflicting data " , " http2.body.fragment.overlap.conflicts " ,
FT_BOOLEAN , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_fragment_multiple_tails ,
{ " Body has multiple tail fragments " , " http2.body.fragment.multiple_tails " ,
FT_BOOLEAN , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_fragment_too_long_fragment ,
{ " Body fragment too long " , " http2.body.fragment.too_long_fragment " ,
FT_BOOLEAN , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_fragment_error ,
{ " Body defragment error " , " http2.body.fragment.error " ,
FT_FRAMENUM , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_fragment_count ,
{ " Body fragment count " , " http2.body.fragment.count " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_body_reassembled_in ,
{ " Reassembled body in frame " , " http2.body.reassembled.in " ,
FT_FRAMENUM , BASE_NONE , NULL , 0x0 ,
" Reassembled body in frame number " , HFILL }
} ,
{ & hf_http2_body_reassembled_length ,
{ " Reassembled body length " , " http2.body.reassembled.length " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
" Reassembled body in frame number " , HFILL }
} ,
2014-04-25 14:29:10 +00:00
/* Headers */
{ & hf_http2_headers ,
{ " Header Block Fragment " , " http2.headers " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" A header block fragment " , HFILL }
} ,
{ & hf_http2_headers_padding ,
{ " Padding " , " http2.headers.padding " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" Padding octets " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-05-06 15:54:47 +00:00
{ & hf_http2_header ,
{ " Header " , " http2.header " ,
FT_NONE , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_header_length ,
{ " Header Length " , " http2.header.length " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
2016-02-05 14:41:57 +00:00
{ & hf_http2_header_count ,
{ " Header Count " , " http2.header.count " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
2014-05-06 15:54:47 +00:00
{ & hf_http2_header_name_length ,
{ " Name Length " , " http2.header.name.length " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_header_name ,
{ " Name " , " http2.header.name " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_header_value_length ,
{ " Value Length " , " http2.header.value.length " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_header_value ,
{ " Value " , " http2.header.value " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
2018-12-19 12:08:41 +00:00
{ & hf_http2_header_unescaped ,
{ " Unescaped " , " http2.header.unescaped " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
2014-08-04 12:06:14 +00:00
{ & hf_http2_header_repr ,
{ " Representation " , " http2.header.repr " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_header_index ,
{ " Index " , " http2.header.index " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_header_table_size_update ,
{ " Header table size update " , " http2.header_table_size_update " ,
FT_NONE , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_header_table_size ,
{ " Header table size " , " http2.header_table_size_update.header_table_size " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
2013-08-30 11:14:09 +00:00
/* RST Stream */
{ & hf_http2_rst_stream_error ,
{ " Error " , " http2.rst_stream.error " ,
FT_UINT32 , BASE_DEC , VALS ( http2_error_codes_vals ) , 0x0 ,
" The error code indicates why the stream is being terminated " , HFILL }
} ,
/* Settings */
{ & hf_http2_settings ,
{ " Settings " , " http2.settings " ,
FT_NONE , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_settings_identifier ,
{ " Settings Identifier " , " http2.settings.id " ,
2014-12-13 17:52:20 +00:00
FT_UINT16 , BASE_DEC , VALS ( http2_settings_vals ) , 0x0 ,
2013-08-30 11:14:09 +00:00
NULL , HFILL }
} ,
2013-12-15 19:07:40 +00:00
{ & hf_http2_settings_header_table_size ,
{ " Header table size " , " http2.settings.header_table_size " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
2014-04-25 14:29:10 +00:00
" Allows the sender to inform the remote endpoint of the size of the header compression table used to decode header blocks. The initial value is 4096 bytes " , HFILL }
2013-12-15 19:07:40 +00:00
} ,
{ & hf_http2_settings_enable_push ,
{ " Enable PUSH " , " http2.settings.enable_push " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
" The initial value is 1, which indicates that push is permitted " , HFILL }
} ,
2013-08-30 11:14:09 +00:00
{ & hf_http2_settings_max_concurrent_streams ,
{ " Max concurrent streams " , " http2.settings.max_concurrent_streams " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
" Indicates the maximum number of concurrent streams that the sender will allow " , HFILL }
} ,
{ & hf_http2_settings_initial_window_size ,
{ " Initial Windows Size " , " http2.settings.initial_window_size " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
" Indicates the sender's initial window size (in bytes) for stream level flow control " , HFILL }
} ,
2014-08-02 07:22:28 +00:00
{ & hf_http2_settings_max_frame_size ,
{ " Max frame size " , " http2.settings.max_frame_size " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
" Indicates the size of the largest frame payload that the sender will allow " , HFILL }
} ,
{ & hf_http2_settings_max_header_list_size ,
{ " Max header list size " , " http2.settings.max_header_list_size " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
" This advisory setting informs a peer of the maximum size of header list that the sender is prepared to accept. " , HFILL }
} ,
2013-08-30 11:14:09 +00:00
{ & hf_http2_settings_unknown ,
{ " Unknown Settings " , " http2.settings.unknown " ,
FT_UINT32 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL }
} ,
/* Push Promise */
{ & hf_http2_push_promise_r ,
{ " Reserved " , " http2.push_promise.r " ,
FT_UINT32 , BASE_HEX , NULL , MASK_HTTP2_RESERVED ,
" Must be zero " , HFILL }
} ,
2014-04-25 14:29:10 +00:00
2013-08-30 11:14:09 +00:00
{ & hf_http2_push_promise_promised_stream_id ,
{ " Promised-Stream-ID " , " http2.push_promise.promised_stream_id " ,
FT_UINT32 , BASE_DEC , NULL , MASK_HTTP2_PRIORITY ,
" Identifies the stream the endpoint intends to start sending frames for " , HFILL }
} ,
{ & hf_http2_push_promise_header ,
2016-08-24 17:53:04 +00:00
{ " Header Block Fragment " , " http2.push_promise.header " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" Containing request header fields " , HFILL }
2013-08-30 11:14:09 +00:00
} ,
2014-04-25 14:29:10 +00:00
{ & hf_http2_push_promise_padding ,
{ " Padding " , " http2.push_promise.padding " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" Padding octets " , HFILL }
} ,
2013-08-30 11:14:09 +00:00
/* Ping / Pong */
{ & hf_http2_ping ,
{ " Ping " , " http2.ping " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_http2_pong ,
{ " Pong " , " http2.pong " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
/* Goaway */
{ & hf_http2_goaway_r ,
{ " Reserved " , " http2.goway.r " ,
FT_UINT32 , BASE_HEX , NULL , MASK_HTTP2_RESERVED ,
" Must be zero " , HFILL }
} ,
{ & hf_http2_goaway_last_stream_id ,
{ " Promised-Stream-ID " , " http2.goaway.last_stream_id " ,
FT_UINT32 , BASE_DEC , NULL , MASK_HTTP2_PRIORITY ,
" Contains the highest numbered stream identifier for which the sender of the GOAWAY frame has received frames on and might have taken some action on " , HFILL }
} ,
{ & hf_http2_goaway_error ,
{ " Error " , " http2.goaway.error " ,
FT_UINT32 , BASE_DEC , VALS ( http2_error_codes_vals ) , 0x0 ,
" The error code indicates the reason for closing the connection " , HFILL }
} ,
{ & hf_http2_goaway_addata ,
{ " Additional Debug Data " , " http2.goaway.addata " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
NULL , HFILL }
} ,
/* Window Update */
{ & hf_http2_window_update_r ,
{ " Reserved " , " http2.window_update.r " ,
FT_UINT32 , BASE_HEX , NULL , MASK_HTTP2_RESERVED ,
" Must be zero " , HFILL }
} ,
{ & hf_http2_window_update_window_size_increment ,
{ " Window Size Increment " , " http2.window_update.window_size_increment " ,
FT_UINT32 , BASE_DEC , NULL , MASK_HTTP2_PRIORITY ,
" Indicating the number of bytes that the sender can transmit in addition to the existing flow control window " , HFILL }
} ,
/* Continuation */
{ & hf_http2_continuation_header ,
{ " Continuation Header " , " http2.continuation.header " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
" Contains a header block fragment " , HFILL }
} ,
2014-05-12 07:00:52 +00:00
{ & hf_http2_continuation_padding ,
{ " Padding " , " http2.continuation.padding " ,
FT_BYTES , BASE_NONE , NULL , 0x0 ,
" Padding octets " , HFILL }
} ,
2013-08-30 11:14:09 +00:00
2016-04-15 16:35:39 +00:00
/* ALTSVC */
{ & hf_http2_altsvc_origin_len ,
{ " Origin Length " , " http2.altsvc.origin.len " ,
2014-04-25 14:29:10 +00:00
FT_UINT16 , BASE_DEC , NULL , 0x0 ,
2016-04-15 16:35:39 +00:00
" indicating the length, in octets, of the Origin field. " , HFILL }
2014-04-25 14:29:10 +00:00
} ,
{ & hf_http2_altsvc_origin ,
{ " Origin " , " http2.altsvc.origin " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
" A sequence of characters containing ASCII serialisation of an "
" origin that the alternate service is applicable to. " , HFILL }
} ,
2016-04-15 16:35:39 +00:00
{ & hf_http2_altsvc_field_value ,
{ " Field/Value " , " http2.altsvc.field_value " ,
FT_STRING , BASE_NONE , NULL , 0x0 ,
" A sequence of octets containing a value identical to the Alt-Svc field value " , HFILL }
} ,
2013-08-30 11:14:09 +00:00
2014-04-25 14:29:10 +00:00
} ;
2013-08-30 11:14:09 +00:00
static gint * ett [ ] = {
& ett_http2 ,
& ett_http2_header ,
2014-05-06 15:54:47 +00:00
& ett_http2_headers ,
2013-08-30 11:14:09 +00:00
& ett_http2_flags ,
2017-03-27 10:48:26 +00:00
& ett_http2_settings ,
& ett_http2_encoded_entity ,
& ett_http2_body_fragment ,
& ett_http2_body_fragments
2013-08-30 11:14:09 +00:00
} ;
2016-02-05 14:41:57 +00:00
/* Setup protocol expert items */
/*
* Excessive header size or lines could mean a decompression bomb . Should
* these be PI_SECURITY instead ?
*/
static ei_register_info ei [ ] = {
{ & ei_http2_header_size ,
{ " http2.header_size_exceeded " , PI_UNDECODED , PI_ERROR ,
" Decompression stopped. " , EXPFILL }
} ,
{ & ei_http2_header_lines ,
{ " http2.header_lines_exceeded " , PI_UNDECODED , PI_ERROR ,
" Decompression stopped after " G_STRINGIFY ( MAX_HTTP2_HEADER_LINES ) " header lines. " , EXPFILL }
2017-03-27 10:48:26 +00:00
} ,
{ & ei_http2_body_decompression_failed ,
{ " http2.body_decompression_failed " , PI_UNDECODED , PI_WARN ,
" Body decompression failed " , EXPFILL }
2016-02-05 14:41:57 +00:00
}
} ;
2014-08-02 10:00:59 +00:00
module_t * http2_module ;
2016-02-05 14:41:57 +00:00
expert_module_t * expert_http2 ;
2014-08-02 10:00:59 +00:00
2013-08-30 11:14:09 +00:00
proto_http2 = proto_register_protocol ( " HyperText Transfer Protocol 2 " , " HTTP2 " , " http2 " ) ;
proto_register_field_array ( proto_http2 , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2014-08-02 10:00:59 +00:00
http2_module = prefs_register_protocol ( proto_http2 , NULL ) ;
2016-02-05 14:41:57 +00:00
expert_http2 = expert_register_protocol ( proto_http2 ) ;
expert_register_field_array ( expert_http2 , ei , array_length ( ei ) ) ;
2015-07-13 00:40:31 +00:00
prefs_register_obsolete_preference ( http2_module , " heuristic_http2 " ) ;
2014-08-02 10:00:59 +00:00
2017-11-18 02:09:50 +00:00
# ifdef HAVE_NGHTTP2
uat_t * headers_uat ;
static const value_string http2_custom_type_vals [ ] = {
{ val_string , " string " } ,
{ val_uint64 , " unsigned 64-bit integer " } ,
{ 0x00 , NULL }
} ;
static uat_field_t custom_header_uat_fields [ ] = {
UAT_FLD_CSTRING ( header_fields , header_name , " Header name " , " HTTP2 header name " ) ,
UAT_FLD_VS ( header_fields , header_type , " Header type " , http2_custom_type_vals , " Field type " ) ,
UAT_FLD_CSTRING ( header_fields , header_desc , " Field desc " , " Description of the value contained in the header " ) ,
UAT_END_FIELDS
} ;
headers_uat = uat_new ( " Custom HTTP2 Header Fields " ,
sizeof ( header_field_t ) ,
" custom_http2_header_fields " ,
TRUE ,
& header_fields ,
& num_header_fields ,
/* specifies named fields, so affects dissection
and the set of named fields */
UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS ,
NULL ,
header_fields_copy_cb ,
header_fields_update_cb ,
header_fields_free_cb ,
NULL ,
NULL ,
custom_header_uat_fields
) ;
prefs_register_uat_preference ( http2_module , " custom_http2_header_fields " , " Custom HTTP2 header fields " ,
" A table to define custom HTTP2 header for which fields can be setup and used for filtering/data extraction etc. " ,
headers_uat ) ;
/* Fill hash table with static headers */
register_static_headers ( ) ;
# endif
register_init_routine ( & http2_init_protocol ) ;
register_cleanup_routine ( & http2_cleanup_protocol ) ;
2016-01-11 20:47:03 +00:00
http2_handle = register_dissector ( " http2 " , dissect_http2 , proto_http2 ) ;
2015-01-08 16:35:58 +00:00
2017-03-27 10:48:26 +00:00
reassembly_table_register ( & http2_body_reassembly_table ,
& addresses_ports_reassembly_table_functions ) ;
2015-01-08 16:35:58 +00:00
http2_tap = register_tap ( " http2 " ) ;
}
static void http2_stats_tree_init ( stats_tree * st )
{
2018-12-27 19:47:02 +00:00
st_node_http2 = stats_tree_create_node ( st , st_str_http2 , 0 , STAT_DT_INT , TRUE ) ;
2015-01-08 16:35:58 +00:00
st_node_http2_type = stats_tree_create_pivot ( st , st_str_http2_type , st_node_http2 ) ;
}
2019-01-01 03:36:12 +00:00
static tap_packet_status http2_stats_tree_packet ( stats_tree * st , packet_info * pinfo _U_ , epan_dissect_t * edt _U_ , const void * p )
2015-01-08 16:35:58 +00:00
{
2015-12-26 14:04:03 +00:00
const struct HTTP2Tap * pi = ( const struct HTTP2Tap * ) p ;
2015-01-08 16:35:58 +00:00
tick_stat_node ( st , st_str_http2 , 0 , FALSE ) ;
stats_tree_tick_pivot ( st , st_node_http2_type ,
val_to_str ( pi - > type , http2_type_vals , " Unknown type (%d) " ) ) ;
2019-01-01 03:36:12 +00:00
return TAP_PACKET_REDRAW ;
2013-08-30 11:14:09 +00:00
}
void
proto_reg_handoff_http2 ( void )
{
2017-07-22 11:19:24 +00:00
# ifdef HAVE_NGHTTP2
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
media_type_dissector_table = find_dissector_table ( " media_type " ) ;
2017-07-22 11:19:24 +00:00
# endif
HTTP2: Dissect reassembled http2.data.data according to content-type (as text/html, png, application/grpc and etc) and some enhancement for displays.
Change Details:
1. Just like HTTP1.1, dissect reassembled http2.data.data according to content-type header value (searching media_type dissector table).
With this feature, we can add new dissector that based HTTP2 (for example application/grpc), or old text/html, image/png, image/jpeg dissectors.
2. Append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3]
3. Append request :method and :path inforamtion to info column, like: HEADERS[1]: GET /demo/1.jpg. (and also append :method and :path info to Stream Node in tree)
4. Append response status and reason-phrase to info column, like: HEADERS[1]: 200 OK
One HTTP2 package file's info column will look like:
10.10.10.123 23.13.190.101 Magic
10.10.10.123 23.13.190.101 SETTINGS[0]
10.10.10.123 23.13.190.101 WINDOW_UPDATE[0]
10.10.10.123 23.13.190.101 HEADERS[1]: GET /demo
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[1]: 200 OK
23.13.190.101 10.10.10.123 DATA[1], DATA[1], DATA[1], DATA[1] (text/html)
10.10.10.123 23.13.190.101 HEADERS[3]: GET /demo/tile-0.png
10.10.10.123 23.13.190.101 HEADERS[5]: GET /demo/tile-1.png
10.10.10.123 23.13.190.101 HEADERS[7]: GET /demo/tile-2.png
10.10.10.123 23.13.190.101 HEADERS[9]: GET /demo/tile-3.png
10.10.10.123 23.13.190.101 HEADERS[11]: GET /demo/tile-4.png
23.13.190.101 10.10.10.123 SETTINGS[0]
23.13.190.101 10.10.10.123 SETTINGS[0]
10.10.10.123 23.13.190.101 SETTINGS[0]
23.13.190.101 10.10.10.123 HEADERS[5]: 200 OK
23.13.190.101 10.10.10.123 DATA[5]
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[5], DATA[5] (PNG), DATA[5]
23.13.190.101 10.10.10.123 HEADERS[11]: 200 OK
23.13.190.101 10.10.10.123 DATA[7], DATA[7] (PNG), DATA[11], DATA[11] (PNG)
23.13.190.101 10.10.10.123 HEADERS[3]: 200 OK
23.13.190.101 10.10.10.123 DATA[3], DATA[3] (PNG)
23.13.190.101 10.10.10.123 HEADERS[7]: 200 OK
23.13.190.101 10.10.10.123 DATA[9], DATA[9] (PNG)
Change-Id: I4452dadeeefc49806e3036a44d44b5f5186096b9
Reviewed-on: https://code.wireshark.org/review/22715
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2017-07-19 14:10:50 +00:00
2016-10-07 20:25:01 +00:00
dissector_add_for_decode_as_with_preference ( " tcp.port " , http2_handle ) ;
2013-12-15 19:07:40 +00:00
2018-05-27 01:42:41 +00:00
/*
2018-08-12 16:51:10 +00:00
* SSL / TLS Application - Layer Protocol Negotiation ( ALPN ) protocol ID .
2018-05-27 01:42:41 +00:00
*/
2018-09-14 19:58:35 +00:00
dissector_add_string ( " tls.alpn " , " h2 " , http2_handle ) ;
2018-08-12 16:51:10 +00:00
dissector_add_string ( " http.upgrade " , " h2 " , http2_handle ) ;
dissector_add_string ( " http.upgrade " , " h2c " , http2_handle ) ;
2018-05-27 01:42:41 +00:00
2018-09-13 15:40:27 +00:00
heur_dissector_add ( " tls " , dissect_http2_heur_ssl , " HTTP2 over TLS " , " http2_tls " , proto_http2 , HEURISTIC_ENABLE ) ;
2015-07-13 00:40:31 +00:00
heur_dissector_add ( " http " , dissect_http2_heur , " HTTP2 over TCP " , " http2_tcp " , proto_http2 , HEURISTIC_ENABLE ) ;
2015-01-08 16:35:58 +00:00
stats_tree_register ( " http2 " , " http2 " , " HTTP2 " , 0 , http2_stats_tree_packet , http2_stats_tree_init , NULL ) ;
2013-08-30 11:14:09 +00:00
}
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/