2 * Routines for HTTP2 dissection
3 * Copyright 2013, Alexis La Goutte <alexis.lagoutte@gmail.com>
4 * Copyright 2013, Stephen Ludin <sludin@ludin.org>
5 * Copyright 2014, Daniel Stenberg <daniel@haxx.se>
6 * Copyright 2014, Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
16 * The information used comes from:
17 * RFC7540: Hypertext Transfer Protocol version 2 (HTTP/2)
18 * RFC7541: HTTP Header Compression for HTTP/2
19 * RFC7838: HTTP Alternative Services
22 * Enhance display of Data
23 * Reassembling of continuation frame (and other frame)
24 * Add same tap and ping/pong time response
28 #define WS_LOG_DOMAIN "packet-http2"
30 #include <epan/packet.h>
31 #include <epan/expert.h>
32 #include <epan/prefs.h>
33 #include <epan/proto_data.h>
34 #include <epan/exceptions.h>
35 #include "packet-http.h" /* for getting status reason-phrase */
36 #include "packet-http2.h"
37 #include "packet-media-type.h"
41 #include <epan/charsets.h>
42 #include <epan/decode_as.h>
43 #include <nghttp2/nghttp2.h>
44 #include <epan/export_object.h>
48 #include <epan/stats_tree.h>
49 #include <epan/reassemble.h>
50 #include <epan/follow.h>
51 #include <epan/addr_resolv.h>
53 #include "packet-tcp.h"
54 #include "packet-tls.h"
55 #include "wsutil/pint.h"
56 #include "wsutil/strtoi.h"
57 #include "wsutil/str_util.h"
58 #include <wsutil/unicode-utils.h>
59 #include <wsutil/wsjson.h>
60 #include <wsutil/array.h>
63 #define http2_header_repr_type_VALUE_STRING_LIST(XXX) \
64 XXX(HTTP2_HD_NONE, 0x00, "") \
65 XXX(HTTP2_HD_INDEXED, 0x01, "Indexed Header Field") \
66 XXX(HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME, 0x02, "Literal Header Field with Incremental Indexing - Indexed Name") \
67 XXX(HTTP2_HD_LITERAL_INDEXING_NEW_NAME, 0x03, "Literal Header Field with Incremental Indexing - New Name") \
68 XXX(HTTP2_HD_LITERAL_INDEXED_NAME, 0x04, "Literal Header Field without Indexing - Indexed Name") \
69 XXX(HTTP2_HD_LITERAL_NEW_NAME, 0x05, "Literal Header Field without Indexing - New Name") \
70 XXX(HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME, 0x06, "Literal Header Field never Indexed - Indexed Name") \
71 XXX(HTTP2_HD_LITERAL_NEVER_INDEXING_NEW_NAME, 0x07, "Literal Header Field never Indexed - New Name") \
72 XXX(HTTP2_HD_HEADER_TABLE_SIZE_UPDATE, 0x08, "Maximum Header Table Size Change")
74 VALUE_STRING_ENUM(http2_header_repr_type
);
75 VALUE_STRING_ARRAY(http2_header_repr_type
);
78 * Decompression of zlib or brotli encoded entities.
80 #if defined(HAVE_ZLIB) || defined(HAVE_ZLIBNG) || defined(HAVE_BROTLI) || defined(HAVE_ZSTD)
81 static bool http2_decompress_body
= true;
83 static bool http2_decompress_body
;
86 /* Try to dissect reassembled http2.data.data according to content-type later */
87 static dissector_table_t media_type_dissector_table
;
89 static int http_eo_tap
;
92 /* Some protocols on top of http2 require http2 streams to remain open. For example, the stream
93 * mode gRPC method (like ETCD watch stream). These kinds of subdissectors need http2 dissector
94 * to reassemble http2.data.data according to the desegment_offset and desegment_len fields of the
95 * pinfo returned from them. Subdissectors can register its content-type in this table.
96 * Note: Subdissector can set pinfo->desegment_len to DESEGMENT_ONE_MORE_SEGMENT or
97 * to missing nbytes of the head length if entire length of message is undetermined. */
98 static dissector_table_t streaming_content_type_dissector_table
;
100 static dissector_table_t stream_id_content_type_dissector_table
;
103 /* The type of reassembly mode contains:
104 * - HTTP2_DATA_REASSEMBLY_MODE_END_STREAM Complete reassembly at the end of stream. (default)
105 * - HTTP2_DATA_REASSEMBLY_MODE_STREAMING Determined by the desegment_offset and desegment_len fields returned from subdissector.
107 enum http2_data_reassembly_mode_t
{
108 HTTP2_DATA_REASSEMBLY_MODE_END_STREAM
= 0, /* default */
109 HTTP2_DATA_REASSEMBLY_MODE_STREAMING
= 1
112 static enum http2_data_reassembly_mode_t
113 http2_get_data_reassembly_mode(const char* content_type
)
115 return dissector_get_string_handle(streaming_content_type_dissector_table
, content_type
) ?
116 HTTP2_DATA_REASSEMBLY_MODE_STREAMING
: HTTP2_DATA_REASSEMBLY_MODE_END_STREAM
;
120 /* Decompressed header field */
122 /* one of http2_header_repr_type */
124 /* encoded (compressed) length */
132 /* name index or name/value index if type is one of
133 HTTP2_HD_INDEXED and HTTP2_HD_*_INDEXED_NAMEs */
136 /* header table size if type == HTTP2_HD_HEADER_TABLE_SIZE_UPDATE */
137 unsigned header_table_size
;
141 /* Context to decode header representation */
143 /* one of http2_header_repr_type */
145 /* final or temporal result of decoding integer */
147 /* next bit shift to made when decoding integer */
149 /* true if integer decoding was completed */
151 } http2_header_repr_info_t
;
153 /* Cached decompressed header data in one packet_info */
155 /* list of pointer to wmem_array_t, which is array of
157 wmem_list_t
*header_list
;
158 /* This points to the list frame containing current decompressed
159 header for dissecting later. */
160 wmem_list_frame_t
*current
;
161 /* Bytes decompressed if we exceeded MAX_HTTP2_HEADER_SIZE */
162 unsigned header_size_reached
;
163 /* Bytes decompressed if we had not exceeded MAX_HTTP2_HEADER_SIZE */
164 unsigned header_size_attempted
;
165 /* true if we found >= MAX_HTTP2_HEADER_LINES */
166 bool header_lines_exceeded
;
167 } http2_header_data_t
;
169 /* In-flight SETTINGS data. */
171 /* header table size last seen in SETTINGS */
172 uint32_t header_table_size
;
173 /* minimum header table size in SETTINGS */
174 uint32_t min_header_table_size
;
175 /* nonzero if header_table_size has effective value. */
176 int has_header_table_size
;
180 typedef uint64_t http2_frame_num_t
;
182 /* struct for per-stream, per-direction DATA frame reassembly */
184 http2_frame_num_t data_initiated_in
;
185 bool has_transfer_encoded_body
;
186 /* streaming_reassembly_info only used for STREAMING reassembly mode */
187 streaming_reassembly_info_t
* streaming_reassembly_info
;
188 } http2_data_stream_reassembly_info_t
;
190 /* struct for per-stream, per-direction entity body info */
193 char *content_type_parameters
;
194 char *content_encoding
;
195 bool is_partial_content
;
196 } http2_data_stream_body_info_t
;
198 /* struct to track header state, so we know if continuation frames are part
199 * of a HEADERS frame or a PUSH_PROMISE.
202 /* Only track the latest received because we only use this on the first
203 * pass. We could keep all the data in a wmem_list_t if we needed it on
205 http2_frame_num_t header_start_in
;
206 http2_frame_num_t header_end_in
;
207 uint32_t stream_id
; /* Normally the same as the parent http2_stream_info_t
208 * During a PUSH_PROMISE, this is the promised stream. */
209 /* list of pointer to wmem_array_t, which is array of http2_header_t
210 * that come from all HEADERS and CONTINUATION frames. */
211 wmem_list_t
*stream_header_list
;
212 /* fake header info */
213 http2_frame_num_t fake_headers_initiated_fn
;
214 wmem_array_t
* fake_headers
;
215 } http2_header_stream_info_t
;
217 /* struct to reference uni-directional per-stream info */
219 http2_data_stream_body_info_t data_stream_body_info
;
220 http2_data_stream_reassembly_info_t data_stream_reassembly_info
;
221 http2_header_stream_info_t header_stream_info
;
222 bool is_window_initialized
;
223 /* Current window size of the one-way session */
224 int32_t current_window_size
;
225 } http2_oneway_stream_info_t
;
227 /* struct to hold per-stream information for both directions */
229 /* index into http2_oneway_stream_info_t struct is based off
230 * http2_session_t.fwd_flow, available by calling select_http2_flow_index().
231 * The index could be for either client or server, depending on when
232 * the capture is started but the index will be consistent for the lifetime
233 * of the http2_session_t */
234 http2_oneway_stream_info_t oneway_stream_info
[2];
235 bool is_stream_http_connect
;
237 uint32_t request_in_frame_num
;
238 uint32_t response_in_frame_num
;
240 enum http2_data_reassembly_mode_t reassembly_mode
;
244 } http2_stream_info_t
;
246 /* struct to hold data per HTTP/2 session */
248 /* We need to distinguish the direction of the flow to keep track
249 of in-flight SETTINGS and HPACK inflater objects. To achieve
250 this, we use fwd member of tcp_analysis. In the first packet,
251 we record fwd of tcp_analysis. Later, if processing
252 packet_info has fwd of tcp_analysis equal to the recorded fwd,
253 we use index 0 of settings_queue and hd_inflater. We keep
254 track of SETTINGS frame sent in this direction in
255 settings_queue[0] and inflate header block using
256 hd_inflater[0]. Otherwise, we use settings_queue[1] and
258 wmem_queue_t
*settings_queue
[2];
260 nghttp2_hd_inflater
*hd_inflater
[2];
261 http2_header_repr_info_t header_repr_info
[2];
262 wmem_map_t
*per_stream_info
;
263 bool fix_dynamic_table
[2];
265 uint32_t current_stream_id
;
266 tcp_flow_t
*fwd_flow
;
267 /* Initial window size of new streams (in both directions) */
268 uint32_t initial_new_stream_window_size
[2];
269 /* Current window size of the connection (in both directions) */
270 int32_t current_connection_window_size
[2];
273 typedef struct http2_follow_tap_data
{
276 } http2_follow_tap_data_t
;
278 typedef struct http2_adjust_window
{
279 int32_t windowSizeDiff
;
281 } http2_adjust_window_t
;
284 /* Decode as functions */
286 http2_current_stream_id_value(packet_info
* pinfo
)
288 return GUINT_TO_POINTER(http2_get_stream_id(pinfo
));
292 http2_streamid_prompt(packet_info
* pinfo
, char* result
)
295 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "stream (%u)", http2_get_stream_id(pinfo
));
299 decode_as_http2_populate_list(const char* table_name _U_
, decode_as_add_to_list_func add_to_list
, void *ui_element
)
301 decode_as_default_populate_list("media_type", add_to_list
, ui_element
);
304 #endif /*HAVE_NGHTTP2*/
306 static GHashTable
* streamid_hash
;
308 void proto_register_http2(void);
309 void proto_reg_handoff_http2(void);
315 static int http2_tap
;
316 static int http2_follow_tap
;
318 static const uint8_t* st_str_http2
= "HTTP2";
319 static const uint8_t* st_str_http2_type
= "Type";
321 static int st_node_http2
= -1;
322 static int st_node_http2_type
= -1;
324 #define PROTO_DATA_KEY_HEADER 0
325 #define PROTO_DATA_KEY_WINDOW_SIZE_CONNECTION_BEFORE 1
326 #define PROTO_DATA_KEY_WINDOW_SIZE_STREAM_BEFORE 2
329 static int proto_http2
;
330 static int hf_http2_stream
;
331 static int hf_http2_length
;
332 static int hf_http2_type
;
333 static int hf_http2_r
;
334 static int hf_http2_streamid
;
335 static int hf_http2_magic
;
336 static int hf_http2_unknown
;
338 static int hf_http2_flags
;
339 static int hf_http2_flags_end_stream
;
340 static int hf_http2_flags_end_headers
;
341 static int hf_http2_flags_padded
;
342 static int hf_http2_flags_priority
;
343 static int hf_http2_flags_settings_ack
;
344 static int hf_http2_flags_ping_ack
;
345 static int hf_http2_flags_unused
;
346 static int hf_http2_flags_unused_settings
;
347 static int hf_http2_flags_unused_ping
;
348 static int hf_http2_flags_unused_continuation
;
349 static int hf_http2_flags_unused_push_promise
;
350 static int hf_http2_flags_unused_data
;
351 static int hf_http2_flags_unused_headers
;
354 static int hf_http2_padding
;
355 static int hf_http2_pad_length
;
357 static int hf_http2_weight
;
358 static int hf_http2_weight_real
;
359 static int hf_http2_stream_dependency
;
360 static int hf_http2_excl_dependency
;
362 static int hf_http2_data_segment
;
363 static int hf_http2_data_data
;
364 static int hf_http2_data_padding
;
365 static int hf_http2_body_fragments
;
366 static int hf_http2_body_fragment
;
367 static int hf_http2_body_fragment_overlap
;
368 static int hf_http2_body_fragment_overlap_conflicts
;
369 static int hf_http2_body_fragment_multiple_tails
;
370 static int hf_http2_body_fragment_too_long_fragment
;
371 static int hf_http2_body_fragment_error
;
372 static int hf_http2_body_fragment_count
;
373 static int hf_http2_body_reassembled_in
;
374 static int hf_http2_body_reassembled_length
;
375 static int hf_http2_body_reassembled_data
;
377 static int hf_http2_headers
;
378 static int hf_http2_headers_padding
;
379 static int hf_http2_header
;
380 static int hf_http2_header_length
;
381 static int hf_http2_header_count
;
382 static int hf_http2_header_name_length
;
383 static int hf_http2_header_name
;
384 static int hf_http2_header_value_length
;
385 static int hf_http2_header_value
;
386 static int hf_http2_header_unescaped
;
387 static int hf_http2_header_repr
;
388 static int hf_http2_header_index
;
389 static int hf_http2_header_table_size_update
;
390 static int hf_http2_header_table_size
;
391 static int hf_http2_fake_header_count
;
392 static int hf_http2_fake_header
;
393 static int hf_http2_header_request_full_uri
;
395 static int hf_http2_rst_stream_error
;
397 static int hf_http2_settings
;
398 static int hf_http2_settings_identifier
;
399 static int hf_http2_settings_header_table_size
;
400 static int hf_http2_settings_enable_push
;
401 static int hf_http2_settings_max_concurrent_streams
;
402 static int hf_http2_settings_initial_window_size
;
403 static int hf_http2_settings_max_frame_size
;
404 static int hf_http2_settings_max_header_list_size
;
405 static int hf_http2_settings_extended_connect
;
406 static int hf_http2_settings_no_rfc7540_priorities
;
407 static int hf_http2_settings_unknown
;
409 static int hf_http2_push_promise_r
;
410 static int hf_http2_push_promise_promised_stream_id
;
411 static int hf_http2_push_promise_header
;
412 static int hf_http2_push_promise_padding
;
414 static int hf_http2_ping
;
415 static int hf_http2_pong
;
417 static int hf_http2_goaway_r
;
418 static int hf_http2_goaway_last_stream_id
;
419 static int hf_http2_goaway_error
;
420 static int hf_http2_goaway_addata
;
422 static int hf_http2_window_update_r
;
423 static int hf_http2_window_update_window_size_increment
;
425 static int hf_http2_continuation_header
;
426 static int hf_http2_continuation_padding
;
428 static int hf_http2_altsvc_origin_len
;
429 static int hf_http2_altsvc_origin
;
430 static int hf_http2_altsvc_field_value
;
432 static int hf_http2_calculated_window_size_connection_before
;
433 static int hf_http2_calculated_window_size_connection_after
;
434 static int hf_http2_calculated_window_size_stream_before
;
435 static int hf_http2_calculated_window_size_stream_after
;
437 /* HTTP2 header static fields */
438 static int hf_http2_headers_status
;
439 static int hf_http2_headers_path
;
440 static int hf_http2_headers_method
;
441 static int hf_http2_headers_scheme
;
442 static int hf_http2_headers_accept
;
443 static int hf_http2_headers_accept_charset
;
444 static int hf_http2_headers_accept_encoding
;
445 static int hf_http2_headers_accept_language
;
446 static int hf_http2_headers_accept_ranges
;
447 static int hf_http2_headers_access_control_allow_origin
;
448 static int hf_http2_headers_age
;
449 static int hf_http2_headers_allow
;
450 static int hf_http2_headers_authorization
;
451 static int hf_http2_headers_authority
;
452 static int hf_http2_headers_cache_control
;
453 static int hf_http2_headers_content_disposition
;
454 static int hf_http2_headers_content_encoding
;
455 static int hf_http2_headers_content_language
;
456 static int hf_http2_headers_content_length
;
457 static int hf_http2_headers_content_location
;
458 static int hf_http2_headers_content_range
;
459 static int hf_http2_headers_content_type
;
460 static int hf_http2_headers_cookie
;
461 static int hf_http2_headers_date
;
462 static int hf_http2_headers_etag
;
463 static int hf_http2_headers_expect
;
464 static int hf_http2_headers_expires
;
465 static int hf_http2_headers_from
;
466 static int hf_http2_headers_if_match
;
467 static int hf_http2_headers_if_modified_since
;
468 static int hf_http2_headers_if_none_match
;
469 static int hf_http2_headers_if_range
;
470 static int hf_http2_headers_if_unmodified_since
;
471 static int hf_http2_headers_last_modified
;
472 static int hf_http2_headers_link
;
473 static int hf_http2_headers_location
;
474 static int hf_http2_headers_max_forwards
;
475 static int hf_http2_headers_proxy_authenticate
;
476 static int hf_http2_headers_proxy_authorization
;
477 static int hf_http2_headers_range
;
478 static int hf_http2_headers_referer
;
479 static int hf_http2_headers_refresh
;
480 static int hf_http2_headers_retry_after
;
481 static int hf_http2_headers_server
;
482 static int hf_http2_headers_set_cookie
;
483 static int hf_http2_headers_strict_transport_security
;
484 static int hf_http2_headers_user_agent
;
485 static int hf_http2_headers_vary
;
486 static int hf_http2_headers_via
;
487 static int hf_http2_headers_www_authenticate
;
491 static int hf_http2_origin
;
492 static int hf_http2_origin_origin_len
;
493 static int hf_http2_origin_origin
;
494 /* Priority Update */
495 static int hf_http2_priority_update_stream_id
;
496 static int hf_http2_priority_update_field_value
;
497 /* Generated fields */
498 static int hf_http2_time
;
499 static int hf_http2_request_in
;
500 static int hf_http2_response_in
;
503 * These values *should* be large enough to handle most use cases while
504 * keeping hostile traffic from consuming too many resources. If that's
505 * not the case we can convert them to preferences. Current (Feb 2016)
506 * client and server limits:
508 * Apache: 8K (LimitRequestFieldSize), 100 lines (LimitRequestFields)
511 * IIS: 16K (MaxRequestBytes)
512 * Nginx: 8K (large_client_header_buffers)
514 * Tomcat: 8K (maxHttpHeaderSize)
516 #define MAX_HTTP2_HEADER_SIZE (256 * 1024)
517 #define MAX_HTTP2_HEADER_LINES 200
518 static expert_field ei_http2_header_size
;
519 static expert_field ei_http2_header_lines
;
520 static expert_field ei_http2_body_decompression_failed
;
521 static expert_field ei_http2_reassembly_error
;
523 static int ett_http2
;
524 static int ett_http2_header
;
525 static int ett_http2_headers
;
526 static int ett_http2_flags
;
527 static int ett_http2_settings
;
528 static int ett_http2_encoded_entity
;
529 static int ett_http2_body_fragment
;
530 static int ett_http2_body_fragments
;
531 static int ett_http2_origin
;
534 static const fragment_items http2_body_fragment_items
= {
535 /* Fragment subtrees */
536 &ett_http2_body_fragment
,
537 &ett_http2_body_fragments
,
538 /* Fragment fields */
539 &hf_http2_body_fragments
,
540 &hf_http2_body_fragment
,
541 &hf_http2_body_fragment_overlap
,
542 &hf_http2_body_fragment_overlap_conflicts
,
543 &hf_http2_body_fragment_multiple_tails
,
544 &hf_http2_body_fragment_too_long_fragment
,
545 &hf_http2_body_fragment_error
,
546 &hf_http2_body_fragment_count
,
547 &hf_http2_body_reassembled_in
,
548 &hf_http2_body_reassembled_length
,
549 &hf_http2_body_reassembled_data
,
553 /* Due to HPACK compression, we may get lots of relatively large
554 header fields (e.g., 4KiB). Allocating each of them requires lots
555 of memory. The maximum compression is achieved in HPACK by
556 referencing header field stored in dynamic table by one or two
557 bytes. We reduce memory usage by caching header field in this
558 wmem_map_t to reuse its memory region when we see the same header
560 static wmem_map_t
*http2_hdrcache_map
;
561 /* Header name_length + name + value_length + value */
562 static char *http2_header_pstr
;
566 /* Stuff for generation/handling of fields for HTTP2 headers */
568 enum header_field_type
{
573 typedef struct _header_field_t
{
575 enum header_field_type header_type
;
579 static header_field_t
* header_fields
;
580 static unsigned num_header_fields
;
581 static unsigned num_header_fields_cleanup
;
583 static GHashTable
* header_fields_hash
;
586 header_fields_update_cb(void *r
, char **err
)
588 header_field_t
*rec
= (header_field_t
*)r
;
591 if (rec
->header_name
== NULL
) {
592 *err
= g_strdup("Header name can't be empty");
596 g_strstrip(rec
->header_name
);
597 if (rec
->header_name
[0] == 0) {
598 *err
= g_strdup("Header name can't be empty");
602 /* Check for invalid characters (to avoid asserting out when
603 * registering the field).
605 c
= proto_check_field_name(rec
->header_name
);
607 *err
= ws_strdup_printf("Header name can't contain '%c'", c
);
611 /* If the hash table is empty(e.g. on startup), do not try to check a value */
612 if (header_fields_hash
!= NULL
) {
613 const int *entry
= (const int *) g_hash_table_lookup(header_fields_hash
, rec
->header_name
);
615 *err
= ws_strdup_printf("This header field is already defined in UAT or it is a static header field");
625 header_fields_copy_cb(void* n
, const void* o
, size_t siz _U_
)
627 header_field_t
* new_rec
= (header_field_t
*)n
;
628 const header_field_t
* old_rec
= (const header_field_t
*)o
;
630 new_rec
->header_name
= g_strdup(old_rec
->header_name
);
631 new_rec
->header_type
= old_rec
->header_type
;
632 new_rec
->header_desc
= g_strdup(old_rec
->header_desc
);
638 header_fields_free_cb(void*r
)
640 header_field_t
* rec
= (header_field_t
*)r
;
642 g_hash_table_remove(header_fields_hash
, rec
->header_name
);
644 g_free(rec
->header_name
);
645 g_free(rec
->header_desc
);
649 static hf_register_info
* hf_uat
;
652 deregister_header_fields(void)
655 for (unsigned i
= 0; i
< num_header_fields_cleanup
; ++i
) {
656 proto_deregister_field(proto_http2
, *(hf_uat
[i
].p_id
));
657 g_free(hf_uat
[i
].p_id
);
659 proto_add_deregistered_data(hf_uat
);
661 num_header_fields_cleanup
= 0;
664 /* header_fields_hash also contains the static header list (used for
665 * look ups to avoid duplicate entries, so we don't destroy it here.
666 * The dynamic entries are removed from the hash table in
667 * header_fields_free_cb().
672 header_fields_post_update_cb(void)
676 char* header_name_key
;
678 deregister_header_fields();
680 /* Add to hash table headers from UAT */
681 if (num_header_fields
) {
682 hf_uat
= g_new0(hf_register_info
, num_header_fields
);
683 num_header_fields_cleanup
= num_header_fields
;
685 for (unsigned i
= 0; i
< num_header_fields
; i
++) {
686 hf_id
= g_new(int,1);
688 header_name
= g_strdup(header_fields
[i
].header_name
);
689 header_name_key
= g_ascii_strdown(header_name
, -1);
691 hf_uat
[i
].p_id
= hf_id
;
692 hf_uat
[i
].hfinfo
.name
= header_name
;
693 hf_uat
[i
].hfinfo
.abbrev
= ws_strdup_printf("http2.headers.%s", header_name
);
694 switch(header_fields
[i
].header_type
) {
696 hf_uat
[i
].hfinfo
.type
= FT_UINT64
;
697 hf_uat
[i
].hfinfo
.display
= BASE_DEC
;
700 hf_uat
[i
].hfinfo
.type
= FT_STRING
;
701 hf_uat
[i
].hfinfo
.display
= BASE_NONE
;
704 hf_uat
[i
].hfinfo
.strings
= NULL
;
705 hf_uat
[i
].hfinfo
.bitmask
= 0;
706 hf_uat
[i
].hfinfo
.blurb
= g_strdup(header_fields
[i
].header_desc
);
707 HFILL_INIT(hf_uat
[i
]);
709 g_hash_table_insert(header_fields_hash
, header_name_key
, hf_id
);
712 proto_register_field_array(proto_http2
, hf_uat
, num_header_fields
);
717 header_fields_reset_cb(void)
719 deregister_header_fields();
723 register_static_headers(void) {
724 header_fields_hash
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
727 /* Here hf[x].hfinfo.name is a header method which is used as key
728 * for matching ids while processing HTTP2 packets */
729 static hf_register_info hf
[] = {
731 &hf_http2_headers_authority
,
732 {":authority", "http2.headers.authority",
733 FT_STRING
, BASE_NONE
, NULL
, 0x0,
734 "Authority portion of the target URI", HFILL
}
737 &hf_http2_headers_status
,
738 {":status", "http2.headers.status",
739 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
743 &hf_http2_headers_path
,
744 {":path", "http2.headers.path",
745 FT_STRING
, BASE_NONE
, NULL
, 0x0,
749 &hf_http2_headers_method
,
750 {":method", "http2.headers.method",
751 FT_STRING
, BASE_NONE
, NULL
, 0x0,
755 &hf_http2_headers_scheme
,
756 {":scheme", "http2.headers.scheme",
757 FT_STRING
, BASE_NONE
, NULL
, 0x0,
761 &hf_http2_headers_accept
,
762 {"accept", "http2.headers.accept",
763 FT_STRING
, BASE_NONE
, NULL
, 0x0,
764 "Media types that are acceptable to the user agent", HFILL
}
767 &hf_http2_headers_accept_charset
,
768 {"accept-charset", "http2.headers.accept_charset",
769 FT_STRING
, BASE_NONE
, NULL
, 0x0,
770 "Acceptable charsets in textual responses for the user agent", HFILL
}
773 &hf_http2_headers_accept_encoding
,
774 {"accept-encoding", "http2.headers.accept_encoding",
775 FT_STRING
, BASE_NONE
, NULL
, 0x0,
776 "Acceptable content codings (like compression) in responses for the user agent", HFILL
}
779 &hf_http2_headers_accept_language
,
780 {"accept-language", "http2.headers.accept_language",
781 FT_STRING
, BASE_NONE
, NULL
, 0x0,
782 "Preferred natural languages for the user agent", HFILL
}
785 &hf_http2_headers_accept_ranges
,
786 {"accept-ranges", "http2.headers.accept_ranges",
787 FT_STRING
, BASE_NONE
, NULL
, 0x0,
788 "Bytes range which server may use for partial data transfer", HFILL
}
791 &hf_http2_headers_access_control_allow_origin
,
792 {"access-control-allow-origin", "http2.headers.access_control_allow_origin",
793 FT_STRING
, BASE_NONE
, NULL
, 0x0,
794 "Origin control for cross-origin resource sharing", HFILL
}
797 &hf_http2_headers_age
,
798 {"age", "http2.headers.age",
799 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
800 "Time in seconds which was spent for transferring data through proxy", HFILL
}
803 &hf_http2_headers_allow
,
804 {"allow", "http2.headers.allow",
805 FT_STRING
, BASE_NONE
, NULL
, 0x0,
806 "List of allowed methods for request", HFILL
}
809 &hf_http2_headers_authorization
,
810 {"authorization", "http2.headers.authorization",
811 FT_STRING
, BASE_NONE
, NULL
, 0x0,
812 "Credentials for a server-side authorization", HFILL
}
815 &hf_http2_headers_cache_control
,
816 {"cache-control", "http2.headers.cache_control",
817 FT_STRING
, BASE_NONE
, NULL
, 0x0,
818 "Request or response directives for a cache control", HFILL
}
821 &hf_http2_headers_content_disposition
,
822 {"content-disposition", "http2.headers.content_disposition",
823 FT_STRING
, BASE_NONE
, NULL
, 0x0,
824 "Indicates that response will be displayed as page or downloaded with dialog box", HFILL
}
827 &hf_http2_headers_content_encoding
,
828 {"content-encoding", "http2.headers.content_encoding",
829 FT_STRING
, BASE_NONE
, NULL
, 0x0,
833 &hf_http2_headers_content_language
,
834 {"content-language", "http2.headers.content_language",
835 FT_STRING
, BASE_NONE
, NULL
, 0x0,
839 &hf_http2_headers_content_length
,
840 {"content-length", "http2.headers.content_length",
841 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
842 "Size of body in bytes", HFILL
}
845 &hf_http2_headers_content_location
,
846 {"content-location", "http2.headers.content_location",
847 FT_STRING
, BASE_NONE
, NULL
, 0x0,
848 "Alternative URL for a response data", HFILL
}
851 &hf_http2_headers_content_range
,
852 {"content-range", "http2.headers.content_range",
853 FT_STRING
, BASE_NONE
, NULL
, 0x0,
854 "Range of bytes which was sent by server for partial data transfer", HFILL
}
857 &hf_http2_headers_content_type
,
858 {"content-type", "http2.headers.content_type",
859 FT_STRING
, BASE_NONE
, NULL
, 0x0,
860 "MIME type of response", HFILL
}
863 &hf_http2_headers_cookie
,
864 {"cookie", "http2.headers.cookie",
865 FT_STRING
, BASE_NONE
, NULL
, 0x0,
866 "Stored cookies", HFILL
}
869 &hf_http2_headers_date
,
870 {"date", "http2.headers.date",
871 FT_STRING
, BASE_NONE
, NULL
, 0x0,
872 "Date and time at which the data was originated", HFILL
}
875 &hf_http2_headers_etag
,
876 {"etag", "http2.headers.etag",
877 FT_STRING
, BASE_NONE
, NULL
, 0x0,
878 "Directive for version indication of resource", HFILL
}
881 &hf_http2_headers_expect
,
882 {"expect", "http2.headers.expect",
883 FT_STRING
, BASE_NONE
, NULL
, 0x0,
884 "Expectations that need to be fulfilled for correct request", HFILL
}
887 &hf_http2_headers_expires
,
888 {"expires", "http2.headers.expires",
889 FT_STRING
, BASE_NONE
, NULL
, 0x0,
890 "Data after which resource will be stale", HFILL
}
893 &hf_http2_headers_from
,
894 {"from", "http2.headers.from",
895 FT_STRING
, BASE_NONE
, NULL
, 0x0,
896 "Email of a person who responsible for a requesting data", HFILL
}
899 &hf_http2_headers_if_match
,
900 {"if-match", "http2.headers.if_match",
901 FT_STRING
, BASE_NONE
, NULL
, 0x0,
902 "Mechanism for requesting data matched by a list of ETags", HFILL
}
905 &hf_http2_headers_if_modified_since
,
906 {"if-modified-since", "http2.headers.if_modified_since",
907 FT_STRING
, BASE_NONE
, NULL
, 0x0,
908 "Resource will be sent with status code 200 if it was modified otherwise with status code 304", HFILL
}
911 &hf_http2_headers_if_none_match
,
912 {"if-none-match", "http2.headers.if_none_match",
913 FT_STRING
, BASE_NONE
, NULL
, 0x0,
914 "Mechanism for requesting data not matched by a list of ETags", HFILL
}
917 &hf_http2_headers_if_range
,
918 {"if-range", "http2.headers.if_range",
919 FT_STRING
, BASE_NONE
, NULL
, 0x0,
920 "Mechanism for a range request which is used to check if a resource was modified", HFILL
}
923 &hf_http2_headers_if_unmodified_since
,
924 {"if-unmodified-since", "http2.headers.if_unmodified_since",
925 FT_STRING
, BASE_NONE
, NULL
, 0x0,
926 "Resource will be processed if it was not modified otherwise 412 error will be returned", HFILL
}
929 &hf_http2_headers_last_modified
,
930 {"last-modified", "http2.headers.last_modified",
931 FT_STRING
, BASE_NONE
, NULL
, 0x0,
932 "Date and time at which the origin server believes the resource was last modified", HFILL
}
935 &hf_http2_headers_link
,
936 {"link", "http2.headers.link",
937 FT_STRING
, BASE_NONE
, NULL
, 0x0,
938 "Mechanism for indicating that resource will be preloaded", HFILL
}
941 &hf_http2_headers_location
,
942 {"location", "http2.headers.location",
943 FT_STRING
, BASE_NONE
, NULL
, 0x0,
944 "Mechanism for indicating that client will be redirected", HFILL
}
947 &hf_http2_headers_max_forwards
,
948 {"max-forwards", "http2.headers.max_forwards",
949 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
950 "Mechanism for limiting the number of proxies", HFILL
}
953 &hf_http2_headers_proxy_authenticate
,
954 {"proxy-authenticate", "http2.headers.proxy_authenticate",
955 FT_STRING
, BASE_NONE
, NULL
, 0x0,
956 "Authentication method that should be used to gain access to a resource behind a proxy server", HFILL
}
959 &hf_http2_headers_proxy_authorization
,
960 {"proxy-authorization", "http2.headers.proxy_authorization",
961 FT_STRING
, BASE_NONE
, NULL
, 0x0,
962 "Credentials for a proxy-side authorization", HFILL
}
965 &hf_http2_headers_range
,
966 {"range", "http2.headers.range",
967 FT_STRING
, BASE_NONE
, NULL
, 0x0,
968 "Range of resource bytes that server should return", HFILL
}
971 &hf_http2_headers_referer
,
972 {"referer", "http2.headers.referer",
973 FT_STRING
, BASE_NONE
, NULL
, 0x0,
974 "Address of the previous web page", HFILL
}
977 &hf_http2_headers_refresh
,
978 {"refresh", "http2.headers.refresh",
979 FT_STRING
, BASE_NONE
, NULL
, 0x0,
980 "Time in seconds after which client will be redirected by given url", HFILL
}
983 &hf_http2_headers_retry_after
,
984 {"retry-after", "http2.headers.retry_after",
985 FT_STRING
, BASE_NONE
, NULL
, 0x0,
986 "Mechanism to indicate when resource expected to be available", HFILL
}
989 &hf_http2_headers_server
,
990 {"server", "http2.headers.server",
991 FT_STRING
, BASE_NONE
, NULL
, 0x0,
992 "Information about server software", HFILL
}
995 &hf_http2_headers_set_cookie
,
996 {"set-cookie", "http2.headers.set_cookie",
997 FT_STRING
, BASE_NONE
, NULL
, 0x0,
998 "Send a cookie to the client", HFILL
}
1001 &hf_http2_headers_strict_transport_security
,
1002 {"strict-transport-security", "http2.headers.strict_transport_security",
1003 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1004 "HSTS indicates that resource should be accessed only using HTTPS", HFILL
}
1007 &hf_http2_headers_user_agent
,
1008 {"user-agent", "http2.headers.user_agent",
1009 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1010 "Information about client software", HFILL
}
1013 &hf_http2_headers_vary
,
1014 {"vary", "http2.headers.vary",
1015 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1016 "Mechanism for selecting which header will be used for content negotiation algorithm", HFILL
}
1019 &hf_http2_headers_via
,
1020 {"via", "http2.headers.via",
1021 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1022 "Additional information for loop detection and protocol capabilities in proxy requests", HFILL
}
1025 &hf_http2_headers_www_authenticate
,
1026 {"www-authenticate", "http2.headers.www_authenticate",
1027 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1028 "Authentication method that should be used to gain access to a resource", HFILL
}
1032 for (unsigned i
= 0; i
< G_N_ELEMENTS(hf
); ++i
) {
1033 header_name
= g_strdup(hf
[i
].hfinfo
.name
);
1035 g_hash_table_insert(header_fields_hash
, header_name
, &hf
[i
].hfinfo
.id
);
1037 proto_register_field_array(proto_http2
, hf
, G_N_ELEMENTS(hf
));
1040 UAT_CSTRING_CB_DEF(header_fields
, header_name
, header_field_t
)
1041 UAT_VS_DEF(header_fields
, header_type
, header_field_t
, enum header_field_type
, val_string
, "string")
1042 UAT_CSTRING_CB_DEF(header_fields
, header_desc
, header_field_t
)
1044 /* message/stream direction (to or from server) vals */
1045 #define http2_direction_type_vals_VALUE_STRING_LIST(XXX) \
1046 XXX(DIRECTION_IN, 0, "IN") \
1047 XXX(DIRECTION_OUT, 1, "OUT")
1049 typedef VALUE_STRING_ENUM(http2_direction_type_vals
) http2_direction_type
;
1050 VALUE_STRING_ARRAY(http2_direction_type_vals
);
1052 /* The fake headers will be used if the HEADERS frame before the first DATA is missing. */
1054 range_t
* server_port_range
;
1055 uint32_t stream_id
; /* 0 means applicable to all streams */
1056 http2_direction_type direction
;
1059 bool override
; /* override existing header */
1060 bool enable
; /* enable or disable this rule */
1061 } http2_fake_header_t
;
1063 static http2_fake_header_t
* http2_fake_headers
;
1064 static unsigned num_http2_fake_headers
;
1067 http2_fake_headers_copy_cb(void* n
, const void* o
, size_t siz _U_
)
1069 http2_fake_header_t
* new_rec
= (http2_fake_header_t
*)n
;
1070 const http2_fake_header_t
* old_rec
= (const http2_fake_header_t
*)o
;
1072 /* copy values like uint32_t */
1073 memcpy(new_rec
, old_rec
, sizeof(http2_fake_header_t
));
1075 if (old_rec
->server_port_range
)
1076 new_rec
->server_port_range
= range_copy(NULL
, old_rec
->server_port_range
);
1078 new_rec
->header_name
= g_strdup(old_rec
->header_name
);
1079 new_rec
->header_value
= g_strdup(old_rec
->header_value
);
1085 http2_fake_headers_update_cb(void* r
, char** err
)
1087 http2_fake_header_t
* rec
= (http2_fake_header_t
*)r
;
1088 static range_t
* empty
;
1090 empty
= range_empty(NULL
);
1091 if (ranges_are_equal(rec
->server_port_range
, empty
)) {
1092 *err
= g_strdup("Must specify server port(s) (like 50051 or 50051,60051-60054)");
1093 wmem_free(NULL
, empty
);
1097 wmem_free(NULL
, empty
);
1099 /* Check header_name */
1100 if (rec
->header_name
== NULL
) {
1101 *err
= g_strdup("Header name can't be empty");
1105 g_strstrip(rec
->header_name
);
1106 if (rec
->header_name
[0] == 0) {
1107 *err
= g_strdup("Header name can't be empty");
1112 if (rec
->header_value
== NULL
) {
1113 *err
= g_strdup("Header value can't be empty");
1117 g_strstrip(rec
->header_value
);
1118 if (rec
->header_name
[0] == 0) {
1119 *err
= g_strdup("Header value can't be empty");
1128 http2_fake_headers_free_cb(void* r
)
1130 http2_fake_header_t
* rec
= (http2_fake_header_t
*)r
;
1132 wmem_free(NULL
, rec
->server_port_range
);
1133 g_free(rec
->header_name
);
1134 g_free(rec
->header_value
);
1137 UAT_RANGE_CB_DEF(http2_fake_headers
, server_port_range
, http2_fake_header_t
)
1138 UAT_DEC_CB_DEF(http2_fake_headers
, stream_id
, http2_fake_header_t
)
1139 UAT_VS_DEF(http2_fake_headers
, direction
, http2_fake_header_t
, http2_direction_type
,
1140 DIRECTION_IN
, try_val_to_str(DIRECTION_IN
, http2_direction_type_vals
))
1141 UAT_CSTRING_CB_DEF(http2_fake_headers
, header_name
, http2_fake_header_t
)
1142 UAT_CSTRING_CB_DEF(http2_fake_headers
, header_value
, http2_fake_header_t
)
1143 UAT_BOOL_CB_DEF(http2_fake_headers
, override
, http2_fake_header_t
)
1144 UAT_BOOL_CB_DEF(http2_fake_headers
, enable
, http2_fake_header_t
)
1147 get_fake_header_value(packet_info
* pinfo
, const char* name
, bool the_other_direction
, bool* override
)
1149 if (num_http2_fake_headers
== 0) {
1153 http2_direction_type direction
;
1154 range_t
* server_port_range
;
1155 uint32_t stream_id
= http2_get_stream_id(pinfo
);
1157 for (unsigned i
= 0; i
< num_http2_fake_headers
; i
++) {
1158 http2_fake_header_t
* fake_header
= http2_fake_headers
+ i
;
1160 if (fake_header
->enable
== false ||
1161 (fake_header
->stream_id
> 0 && fake_header
->stream_id
!= stream_id
)) {
1165 server_port_range
= fake_header
->server_port_range
;
1166 if (value_is_in_range(server_port_range
, pinfo
->destport
)) {
1167 direction
= the_other_direction
? DIRECTION_OUT
: DIRECTION_IN
;
1168 } else if (value_is_in_range(server_port_range
, pinfo
->srcport
)) {
1169 direction
= the_other_direction
? DIRECTION_IN
: DIRECTION_OUT
;
1174 if (fake_header
->direction
== direction
&& strcmp(fake_header
->header_name
, name
) == 0) {
1176 *override
= fake_header
->override
;
1178 return wmem_strdup(pinfo
->pool
, fake_header
->header_value
);
1187 http2_init_protocol(void)
1189 /* Init hash table with mapping of stream id -> frames count for Follow HTTP2 */
1190 streamid_hash
= g_hash_table_new_full(NULL
, NULL
, NULL
, (GDestroyNotify
)g_hash_table_destroy
);
1194 http2_cleanup_protocol(void) {
1195 g_hash_table_destroy(streamid_hash
);
1198 static dissector_handle_t http2_handle
;
1199 static dissector_handle_t data_handle
;
1201 static reassembly_table http2_body_reassembly_table
;
1202 static reassembly_table http2_streaming_reassembly_table
;
1204 #define FRAME_HEADER_LENGTH 9
1205 #define MAGIC_FRAME_LENGTH 24
1206 #define MAGIC_FRAME_FIRST_LINE 16
1207 #define MASK_HTTP2_RESERVED 0x80000000
1208 #define MASK_HTTP2_STREAMID 0X7FFFFFFF
1209 #define MASK_HTTP2_PRIORITY 0X7FFFFFFF
1211 /* Header Type Code */
1212 #define HTTP2_DATA 0
1213 #define HTTP2_HEADERS 1
1214 #define HTTP2_PRIORITY 2
1215 #define HTTP2_RST_STREAM 3
1216 #define HTTP2_SETTINGS 4
1217 #define HTTP2_PUSH_PROMISE 5
1218 #define HTTP2_PING 6
1219 #define HTTP2_GOAWAY 7
1220 #define HTTP2_WINDOW_UPDATE 8
1221 #define HTTP2_CONTINUATION 9
1222 #define HTTP2_ALTSVC 0xA
1223 #define HTTP2_BLOCKED 0xB
1224 #define HTTP2_ORIGIN 0xC
1225 #define HTTP2_PRIORITY_UPDATE 0x10
1227 static const value_string http2_type_vals
[] = {
1228 { HTTP2_DATA
, "DATA" },
1229 { HTTP2_HEADERS
, "HEADERS" },
1230 { HTTP2_PRIORITY
, "PRIORITY" },
1231 { HTTP2_RST_STREAM
, "RST_STREAM" },
1232 { HTTP2_SETTINGS
, "SETTINGS" },
1233 { HTTP2_PUSH_PROMISE
, "PUSH_PROMISE" },
1234 { HTTP2_PING
, "PING" },
1235 { HTTP2_GOAWAY
, "GOAWAY" },
1236 { HTTP2_WINDOW_UPDATE
, "WINDOW_UPDATE" },
1237 { HTTP2_CONTINUATION
, "CONTINUATION" },
1238 { HTTP2_ALTSVC
, "ALTSVC" },
1239 { HTTP2_BLOCKED
, "BLOCKED" },
1240 { HTTP2_ORIGIN
, "ORIGIN" },
1241 { HTTP2_PRIORITY_UPDATE
, "PRIORITY_UPDATE" },
1246 #define HTTP2_FLAGS_ACK 0x01 /* for PING and SETTINGS */
1248 #define HTTP2_FLAGS_END_STREAM 0x01
1249 #define HTTP2_FLAGS_END_HEADERS 0x04
1250 #define HTTP2_FLAGS_PADDED 0x08
1251 #define HTTP2_FLAGS_PRIORITY 0x20
1253 #define HTTP2_FLAGS_UNUSED 0xFF
1254 #define HTTP2_FLAGS_UNUSED_SETTINGS (~HTTP2_FLAGS_ACK & 0xFF)
1255 #define HTTP2_FLAGS_UNUSED_PING (~HTTP2_FLAGS_ACK & 0xFF)
1256 #define HTTP2_FLAGS_UNUSED_CONTINUATION (~HTTP2_FLAGS_END_HEADERS & 0xFF)
1257 #define HTTP2_FLAGS_UNUSED_PUSH_PROMISE \
1258 (~(HTTP2_FLAGS_END_HEADERS | HTTP2_FLAGS_PADDED) & 0xFF)
1259 #define HTTP2_FLAGS_UNUSED_DATA \
1260 (~(HTTP2_FLAGS_END_STREAM | HTTP2_FLAGS_PADDED) & 0xFF)
1261 #define HTTP2_FLAGS_UNUSED_HEADERS \
1262 (~(HTTP2_FLAGS_END_STREAM | HTTP2_FLAGS_END_HEADERS | \
1263 HTTP2_FLAGS_PADDED | HTTP2_FLAGS_PRIORITY) & 0xFF)
1265 #define HTTP2_FLAGS_R 0xFF
1266 #define HTTP2_FLAGS_R1 0xFE
1267 #define HTTP2_FLAGS_R2 0xFA
1268 #define HTTP2_FLAGS_R4 0xFB
1270 /* header matching helpers */
1271 #define IS_HTTP2_END_STREAM(flags) (flags & HTTP2_FLAGS_END_STREAM)
1273 /* Magic Header : PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n */
1274 static uint8_t kMagicHello
[] = {
1275 0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,
1276 0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,
1277 0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a
1281 #define EC_NO_ERROR 0x0
1282 #define EC_PROTOCOL_ERROR 0x1
1283 #define EC_INTERNAL_ERROR 0x2
1284 #define EC_FLOW_CONTROL_ERROR 0x3
1285 #define EC_SETTINGS_TIMEOUT 0x4
1286 #define EC_STREAM_CLOSED 0x5
1287 #define EC_FRAME_SIZE_ERROR 0x6
1288 #define EC_REFUSED_STREAM 0x7
1289 #define EC_CANCEL 0x8
1290 #define EC_COMPRESSION_ERROR 0x9
1291 #define EC_CONNECT_ERROR 0xa
1292 #define EC_ENHANCE_YOUR_CALM 0xb
1293 #define EC_INADEQUATE_SECURITY 0xc
1294 #define EC_HTTP_1_1_REQUIRED 0xd
1297 static const value_string http2_error_codes_vals
[] = {
1298 { EC_NO_ERROR
, "NO_ERROR" },
1299 { EC_PROTOCOL_ERROR
, "PROTOCOL_ERROR" },
1300 { EC_INTERNAL_ERROR
, "INTERNAL_ERROR" },
1301 { EC_FLOW_CONTROL_ERROR
, "FLOW_CONTROL_ERROR" },
1302 { EC_SETTINGS_TIMEOUT
, "SETTINGS_TIMEOUT" },
1303 { EC_STREAM_CLOSED
, "STREAM_CLOSED" },
1304 { EC_FRAME_SIZE_ERROR
, "FRAME_SIZE_ERROR" },
1305 { EC_REFUSED_STREAM
, "REFUSED_STREAM" },
1306 { EC_CANCEL
, "CANCEL" },
1307 { EC_COMPRESSION_ERROR
, "COMPRESSION_ERROR" },
1308 { EC_CONNECT_ERROR
, "CONNECT_ERROR" },
1309 { EC_ENHANCE_YOUR_CALM
, "ENHANCE_YOUR_CALM" },
1310 { EC_INADEQUATE_SECURITY
, "INADEQUATE_SECURITY" },
1311 { EC_HTTP_1_1_REQUIRED
, "HTTP_1_1_REQUIRED" },
1316 #define HTTP2_SETTINGS_HEADER_TABLE_SIZE 1
1317 #define HTTP2_SETTINGS_ENABLE_PUSH 2
1318 #define HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS 3
1319 #define HTTP2_SETTINGS_INITIAL_WINDOW_SIZE 4
1320 #define HTTP2_SETTINGS_MAX_FRAME_SIZE 5
1321 #define HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE 6
1322 #define HTTP2_SETTINGS_EXTENDED_CONNECT 8 /* RFC 8441 */
1323 #define HTTP2_SETTINGS_NO_RFC7540_PRIORITIES 9 /* RFC 9218 */
1325 static const value_string http2_settings_vals
[] = {
1326 { HTTP2_SETTINGS_HEADER_TABLE_SIZE
, "Header table size" },
1327 { HTTP2_SETTINGS_ENABLE_PUSH
, "Enable PUSH" },
1328 { HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
, "Max concurrent streams" },
1329 { HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
, "Initial Windows size" },
1330 { HTTP2_SETTINGS_MAX_FRAME_SIZE
, "Max frame size" },
1331 { HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
, "Max header list size" },
1332 { HTTP2_SETTINGS_EXTENDED_CONNECT
, "Extended CONNECT" },
1333 { HTTP2_SETTINGS_NO_RFC7540_PRIORITIES
, "No RFC7540 Priorities" },
1338 * "When an HTTP/2 connection is first established, new streams
1339 * are created with an initial flow-control window size of 65,535
1340 * octets. The connection flow-control window is also 65,535
1341 * octets. Both endpoints can adjust the initial window size for
1342 * new streams by including a value for SETTINGS_INITIAL_WINDOW_SIZE
1343 * in the SETTINGS frame. The connection flow-control window can
1344 * only be changed using WINDOW_UPDATE frames."
1345 * https://www.ietf.org/rfc/rfc9113.html#section-6.9.2-1
1347 #define INITIAL_WINDOW_SIZE 65535
1350 select_http2_flow_index(packet_info
*pinfo
, http2_session_t
*h2session
)
1352 struct tcp_analysis
*tcpd
;
1354 tcpd
= get_tcp_conversation_data(NULL
, pinfo
);
1356 if(tcpd
->fwd
== h2session
->fwd_flow
) {
1365 hd_inflate_del_cb(wmem_allocator_t
*allocator _U_
, wmem_cb_event_t event _U_
, void *user_data
)
1367 nghttp2_hd_inflate_del((nghttp2_hd_inflater
*)user_data
);
1368 http2_hdrcache_map
= NULL
;
1369 http2_header_pstr
= NULL
;
1374 static http2_stream_info_t
*
1375 get_stream_info_for_id(packet_info
*pinfo
, http2_session_t
*http2_session
, bool initializeOppositeDirection
, uint32_t stream_id
)
1377 wmem_map_t
*stream_map
= http2_session
->per_stream_info
;
1378 uint32_t flow_index
= select_http2_flow_index(pinfo
, http2_session
);
1380 http2_stream_info_t
*stream_info
= (http2_stream_info_t
*)wmem_map_lookup(stream_map
, GINT_TO_POINTER(stream_id
));
1381 if (stream_info
== NULL
) {
1382 stream_info
= wmem_new0(wmem_file_scope(), http2_stream_info_t
);
1383 stream_info
->oneway_stream_info
[0].header_stream_info
.stream_header_list
= wmem_list_new(wmem_file_scope());
1384 stream_info
->oneway_stream_info
[1].header_stream_info
.stream_header_list
= wmem_list_new(wmem_file_scope());
1385 stream_info
->stream_id
= stream_id
;
1386 stream_info
->oneway_stream_info
[0].header_stream_info
.stream_id
= stream_id
;
1387 stream_info
->oneway_stream_info
[1].header_stream_info
.stream_id
= stream_id
;
1388 stream_info
->reassembly_mode
= HTTP2_DATA_REASSEMBLY_MODE_END_STREAM
;
1389 stream_info
->oneway_stream_info
[0].is_window_initialized
= false;
1390 stream_info
->oneway_stream_info
[0].current_window_size
= INITIAL_WINDOW_SIZE
;
1391 stream_info
->oneway_stream_info
[1].is_window_initialized
= false;
1392 stream_info
->oneway_stream_info
[1].current_window_size
= INITIAL_WINDOW_SIZE
;
1393 nstime_set_unset(&(stream_info
->request_ts
));
1394 wmem_map_insert(stream_map
, GINT_TO_POINTER(stream_id
), stream_info
);
1397 /* The first time the stream info is requested for a
1398 * particular direction, initialize the window size
1399 * in that direction to the current initial window size for
1400 * that direction. Flip what we're checking around if
1401 * initializeOppositeDirection is true.
1403 if (initializeOppositeDirection
) {
1406 if (!stream_info
->oneway_stream_info
[flow_index
].is_window_initialized
) {
1407 stream_info
->oneway_stream_info
[flow_index
].current_window_size
= http2_session
->initial_new_stream_window_size
[flow_index
];
1408 stream_info
->oneway_stream_info
[flow_index
].is_window_initialized
= true;
1414 static http2_stream_info_t
*
1415 get_stream_info(packet_info
*pinfo
, http2_session_t
*http2_session
, bool initializeOppositeDirection
)
1417 uint32_t stream_id
= http2_session
->current_stream_id
;
1419 return get_stream_info_for_id(pinfo
, http2_session
, initializeOppositeDirection
, stream_id
);
1423 static http2_session_t
*
1424 get_http2_session(packet_info
*pinfo
, conversation_t
* conversation
)
1426 http2_session_t
*h2session
;
1428 h2session
= (http2_session_t
*)conversation_get_proto_data(conversation
,
1432 struct tcp_analysis
*tcpd
;
1434 tcpd
= get_tcp_conversation_data(conversation
, pinfo
);
1436 h2session
= wmem_new0(wmem_file_scope(), http2_session_t
);
1439 nghttp2_hd_inflate_new(&h2session
->hd_inflater
[0]);
1440 nghttp2_hd_inflate_new(&h2session
->hd_inflater
[1]);
1442 wmem_register_callback(wmem_file_scope(), hd_inflate_del_cb
,
1443 h2session
->hd_inflater
[0]);
1444 wmem_register_callback(wmem_file_scope(), hd_inflate_del_cb
,
1445 h2session
->hd_inflater
[1]);
1446 h2session
->per_stream_info
= wmem_map_new(wmem_file_scope(),
1449 /* Unless found otherwise, assume that some earlier Header Block
1450 * Fragments were missing and that recovery should be attempted. */
1451 h2session
->fix_dynamic_table
[0] = true;
1452 h2session
->fix_dynamic_table
[1] = true;
1455 h2session
->fwd_flow
= tcpd
->fwd
;
1456 h2session
->settings_queue
[0] = wmem_queue_new(wmem_file_scope());
1457 h2session
->settings_queue
[1] = wmem_queue_new(wmem_file_scope());
1458 h2session
->initial_new_stream_window_size
[0] = INITIAL_WINDOW_SIZE
;
1459 h2session
->initial_new_stream_window_size
[1] = INITIAL_WINDOW_SIZE
;
1460 h2session
->current_connection_window_size
[0] = INITIAL_WINDOW_SIZE
;
1461 h2session
->current_connection_window_size
[1] = INITIAL_WINDOW_SIZE
;
1463 conversation_add_proto_data(conversation
, proto_http2
, h2session
);
1471 http2_get_stream_id(packet_info
*pinfo
)
1473 conversation_t
*conversation
;
1474 http2_session_t
*h2session
;
1476 conversation
= find_conversation_pinfo(pinfo
, 0);
1477 if (!conversation
) {
1481 h2session
= (http2_session_t
*)conversation_get_proto_data(conversation
, proto_http2
);
1486 return h2session
->current_stream_id
;
1490 http2_get_request_full_uri(packet_info
*pinfo
, http2_session_t
*http2_session
, uint32_t stream_id
)
1492 const char* uri
= NULL
;
1493 http2_stream_info_t
*stream_info
= get_stream_info_for_id(pinfo
, http2_session
, false, stream_id
);
1494 if (stream_info
&& stream_info
->authority
) {
1496 "All HTTP/2 requests MUST include exactly one valid value for the
1497 ":method", ":scheme", and ":path" pseudo-header fields, unless they
1498 are CONNECT requests"
1500 if (stream_info
->is_stream_http_connect
) {
1501 uri
= wmem_strdup(pinfo
->pool
, stream_info
->authority
);
1503 uri
= wmem_strdup_printf(pinfo
->pool
, "%s://%s%s", stream_info
->scheme
, stream_info
->authority
, stream_info
->path
);
1508 #else /* ! HAVE_NGHTTP2 */
1510 http2_get_stream_id(packet_info
*pinfo _U_
)
1516 http2_get_request_full_uri(packet_info
*pinfo _U_
, http2_session_t
*http2_session _U_
, uint32_t stream_id _U_
)
1520 #endif /* ! HAVE_NGHTTP2 */
1524 get_real_header_value(packet_info
* pinfo
, const char* name
, bool the_other_direction
);
1526 static http2_frame_num_t
1527 get_http2_frame_num(tvbuff_t
*tvb
, packet_info
*pinfo
)
1529 /* HTTP2 frames are identified as follows:
1531 * +--- 32 bits ---+--------- 8 bits -------+----- 24 bits -----+
1532 * | pinfo->num | pinfo->curr_layer_num | tvb->raw_offset |
1533 * +------------------------------------------------------------+
1535 * This allows for a single HTTP2 frame to be uniquely identified across a capture with the
1536 * added benefit that the number will always be increasing from the previous HTTP2 frame so
1537 * we can use "<" and ">" comparisons to determine before and after in time.
1539 * pinfo->curr_layer_num is used to deliberate when we have multiple TLS records in a
1540 * single (non-http2) frame. This ends up being dissected using two separate TVBs
1541 * (so tvb->raw_offset isn't useful) and then end up being the same pinfo->num.
1543 * I have seen instances where the pinfo->curr_layer_num can change between the first and second
1544 * pass of a packet so this needs to be taken into account when this is used as an identifier.
1546 return (((uint64_t)pinfo
->num
) << 32) + (((uint64_t)pinfo
->curr_layer_num
) << 24) + ((uint64_t)tvb_raw_offset(tvb
));
1549 static http2_oneway_stream_info_t
*
1550 get_oneway_stream_info_for_id(packet_info
*pinfo
, http2_session_t
* http2_session
, bool the_other_direction
, uint32_t stream_id
)
1552 http2_stream_info_t
*http2_stream_info
= get_stream_info_for_id(pinfo
, http2_session
, false, stream_id
);
1553 uint32_t flow_index
= select_http2_flow_index(pinfo
, http2_session
);
1554 if (the_other_direction
) {
1555 /* need stream info of the other direction,
1556 so set index from 0 to 1, or from 1 to 0 */
1560 return &http2_stream_info
->oneway_stream_info
[flow_index
];
1563 static http2_oneway_stream_info_t
*
1564 get_oneway_stream_info(packet_info
*pinfo
, http2_session_t
* http2_session
, bool the_other_direction
)
1566 return get_oneway_stream_info_for_id(pinfo
, http2_session
, the_other_direction
, http2_session
->current_stream_id
);
1569 static http2_data_stream_body_info_t
*
1570 get_data_stream_body_info_for_id(packet_info
*pinfo
, http2_session_t
* http2_session
, uint32_t stream_id
)
1572 return &(get_oneway_stream_info_for_id(pinfo
, http2_session
, false, stream_id
)->data_stream_body_info
);
1575 static http2_data_stream_body_info_t
*
1576 get_data_stream_body_info(packet_info
*pinfo
, http2_session_t
* http2_session
)
1578 return &(get_oneway_stream_info(pinfo
, http2_session
, false)->data_stream_body_info
);
1581 static http2_data_stream_reassembly_info_t
*
1582 get_data_reassembly_info_for_id(packet_info
*pinfo
, http2_session_t
* http2_session
, uint32_t stream_id
)
1584 return &(get_oneway_stream_info_for_id(pinfo
, http2_session
, false, stream_id
)->data_stream_reassembly_info
);
1587 static http2_data_stream_reassembly_info_t
*
1588 get_data_reassembly_info(packet_info
*pinfo
, http2_session_t
* http2_session
)
1590 return &(get_oneway_stream_info(pinfo
, http2_session
, false)->data_stream_reassembly_info
);
1593 static http2_header_stream_info_t
*
1594 get_header_stream_info_for_id(packet_info
*pinfo
, http2_session_t
* http2_session
,bool the_other_direction
, uint32_t stream_id
)
1596 return &(get_oneway_stream_info_for_id(pinfo
, http2_session
, the_other_direction
, stream_id
)->header_stream_info
);
1599 static http2_header_stream_info_t
*
1600 get_header_stream_info(packet_info
*pinfo
, http2_session_t
* http2_session
,bool the_other_direction
)
1602 return &(get_oneway_stream_info(pinfo
, http2_session
, the_other_direction
)->header_stream_info
);
1606 push_settings(packet_info
*pinfo
, http2_session_t
*h2session
,
1607 http2_settings_t
*settings
)
1609 wmem_queue_t
*queue
;
1610 uint32_t flow_index
;
1612 flow_index
= select_http2_flow_index(pinfo
, h2session
);
1614 queue
= h2session
->settings_queue
[flow_index
];
1616 wmem_queue_push(queue
, settings
);
1620 apply_and_pop_settings(packet_info
*pinfo
, http2_session_t
*h2session
)
1622 wmem_queue_t
*queue
;
1623 http2_settings_t
*settings
;
1624 nghttp2_hd_inflater
*inflater
;
1625 uint32_t flow_index
;
1627 /* When header table size is applied, it affects the inflater of
1630 flow_index
= select_http2_flow_index(pinfo
, h2session
);
1632 inflater
= h2session
->hd_inflater
[flow_index
];
1634 queue
= h2session
->settings_queue
[flow_index
^ 1];
1636 if(wmem_queue_count(queue
) == 0) {
1640 settings
= (http2_settings_t
*)wmem_queue_pop(queue
);
1642 if(settings
->has_header_table_size
) {
1643 if(settings
->min_header_table_size
< settings
->header_table_size
) {
1644 nghttp2_hd_inflate_change_table_size
1645 (inflater
, settings
->min_header_table_size
);
1648 nghttp2_hd_inflate_change_table_size(inflater
,
1649 settings
->header_table_size
);
1653 /* Decode integer from buf at position p, using prefix bits. This
1654 function can be called several times if buf does not contain whole
1655 integer. header_repr_info remembers the result of previous call.
1656 Returns the number bytes processed. */
1657 static unsigned read_integer(http2_header_repr_info_t
*header_repr_info
,
1658 const uint8_t *buf
, unsigned len
, unsigned p
, unsigned prefix
)
1660 unsigned k
= (1 << prefix
) - 1;
1661 unsigned n
= header_repr_info
->integer
;
1662 unsigned shift
= header_repr_info
->next_shift
;
1665 DISSECTOR_ASSERT(p
< len
);
1667 if((buf
[p
] & k
) != k
) {
1668 header_repr_info
->integer
= buf
[p
] & k
;
1669 header_repr_info
->complete
= true;
1678 for(; p
< len
; ++p
, shift
+= 7) {
1679 n
+= (buf
[p
] & 0x7F) << shift
;
1681 if((buf
[p
] & 0x80) == 0) {
1682 header_repr_info
->complete
= true;
1688 header_repr_info
->integer
= n
;
1689 header_repr_info
->next_shift
= shift
;
1694 reset_http2_header_repr_info(http2_header_repr_info_t
*header_repr_info
)
1696 header_repr_info
->type
= HTTP2_HD_NONE
;
1697 header_repr_info
->integer
= 0;
1698 header_repr_info
->next_shift
= 0;
1699 header_repr_info
->complete
= false;
1702 /* Reads zero or more header table size update and optionally header
1703 representation information. This function returns when first
1704 header representation is decoded or buf is processed completely.
1705 This function returns the number bytes processed for header table
1708 process_http2_header_repr_info(wmem_array_t
*headers
,
1709 http2_header_repr_info_t
*header_repr_info
,
1710 const uint8_t *buf
, unsigned len
)
1715 if(header_repr_info
->type
!= HTTP2_HD_NONE
&&
1716 header_repr_info
->type
!= HTTP2_HD_HEADER_TABLE_SIZE_UPDATE
&&
1717 header_repr_info
->complete
) {
1723 for(i
= 0; i
< len
;) {
1724 if(header_repr_info
->type
== HTTP2_HD_NONE
) {
1725 unsigned char c
= buf
[i
];
1726 if((c
& 0xE0) == 0x20) {
1727 header_repr_info
->type
= HTTP2_HD_HEADER_TABLE_SIZE_UPDATE
;
1729 i
= read_integer(header_repr_info
, buf
, len
, i
, 5);
1730 } else if(c
& 0x80) {
1731 header_repr_info
->type
= HTTP2_HD_INDEXED
;
1732 i
= read_integer(header_repr_info
, buf
, len
, i
, 7);
1733 } else if(c
== 0x40 || c
== 0 || c
== 0x10) {
1735 header_repr_info
->complete
= true;
1737 header_repr_info
->type
= HTTP2_HD_LITERAL_INDEXING_NEW_NAME
;
1738 } else if((c
& 0xF0) == 0x10) {
1739 header_repr_info
->type
= HTTP2_HD_LITERAL_NEVER_INDEXING_NEW_NAME
;
1741 header_repr_info
->type
= HTTP2_HD_LITERAL_NEW_NAME
;
1746 header_repr_info
->type
= HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME
;
1747 i
= read_integer(header_repr_info
, buf
, len
, i
, 6);
1748 } else if((c
& 0xF0) == 0x10) {
1749 header_repr_info
->type
= HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME
;
1750 i
= read_integer(header_repr_info
, buf
, len
, i
, 4);
1752 header_repr_info
->type
= HTTP2_HD_LITERAL_INDEXED_NAME
;
1753 i
= read_integer(header_repr_info
, buf
, len
, i
, 4);
1757 i
= read_integer(header_repr_info
, buf
, len
, i
, 8);
1760 if(header_repr_info
->complete
) {
1761 if(header_repr_info
->type
== HTTP2_HD_HEADER_TABLE_SIZE_UPDATE
) {
1762 http2_header_t
*out
;
1764 out
= wmem_new(wmem_file_scope(), http2_header_t
);
1766 out
->type
= header_repr_info
->type
;
1767 out
->length
= i
- start
;
1768 out
->table
.header_table_size
= header_repr_info
->integer
;
1770 wmem_array_append(headers
, out
, 1);
1772 reset_http2_header_repr_info(header_repr_info
);
1773 /* continue to decode header table size update or
1774 first header encoding is encountered. */
1777 /* Break on first header encoding */
1786 static size_t http2_hdrcache_length(const void *vv
)
1788 const uint8_t *v
= (const uint8_t *)vv
;
1789 uint32_t namelen
, valuelen
;
1791 namelen
= pntoh32(v
);
1792 valuelen
= pntoh32(v
+ sizeof(namelen
) + namelen
);
1794 return namelen
+ valuelen
+ sizeof(namelen
) + sizeof(valuelen
);
1797 static unsigned http2_hdrcache_hash(const void *key
)
1799 return wmem_strong_hash((const uint8_t *)key
, http2_hdrcache_length(key
));
1802 static gboolean
http2_hdrcache_equal(const void *lhs
, const void *rhs
)
1804 const uint8_t *a
= (const uint8_t *)lhs
;
1805 const uint8_t *b
= (const uint8_t *)rhs
;
1806 size_t alen
= http2_hdrcache_length(a
);
1807 size_t blen
= http2_hdrcache_length(b
);
1809 return alen
== blen
&& memcmp(a
, b
, alen
) == 0;
1812 /* If we are in a HEADERS or PUSH_PROMISE context, return the stream id
1813 * the headers describe. (For PUSH_PROMISE or CONTIUATIONs thereof, this
1814 * is the promised stream id.) Otherwise return 0.
1817 is_in_header_context(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* h2session
)
1819 http2_header_stream_info_t
*stream_info
= get_header_stream_info(pinfo
, h2session
, false);
1820 if (get_http2_frame_num(tvb
, pinfo
) >= stream_info
->header_start_in
) {
1821 /* We either haven't established the frame that the headers end in so we are currently in the HEADERS context,
1822 * or if we have, it should be equal or less that the current frame number */
1823 if (stream_info
->header_end_in
== 0 || get_http2_frame_num(tvb
, pinfo
) <= stream_info
->header_end_in
) {
1824 return stream_info
->stream_id
;
1830 /* Extracts only the media-type from a content-type header. EG:
1831 "text/html" returns "text/html"
1832 "text/html; charset=utf-8" returns "text/html"
1834 Allocates file-scoped string when called as its only called when the header population is done.
1837 get_content_type_only(const char *content_type
, size_t content_type_str_len
) {
1838 char *cp
= wmem_strndup(wmem_file_scope(), content_type
, content_type_str_len
);
1841 while (*cp
!= '\0' && *cp
!= ';' && !g_ascii_isspace(*cp
)) {
1842 *cp
= g_ascii_tolower(*cp
);
1850 /* Extracts the parameters from a content-type or returns NULL. EG:
1852 "text/html; charset=utf-8" returns "charset=utf-8"
1853 "text/html" returns NULL
1854 "text/html; " returns NULL
1856 Allocates file-scoped string when called as its only called when the header population is done.
1859 get_content_type_parameters_only(const char *content_type
, size_t content_type_str_len
) {
1860 char *cp
= wmem_strndup(wmem_file_scope(), content_type
, content_type_str_len
);
1862 /* Get past the first part of the content type EG: "text/html" */
1863 while (*cp
!= '\0' && *cp
!= ';' && !g_ascii_isspace(*cp
)) {
1872 /* Move past the first ";" or any whitespace */
1873 while (*cp
== ';' || g_ascii_isspace(*cp
)) {
1877 /* Didn't end up getting any parameters, we just had trailing whitespace or a semicolon after the content-type */
1885 /* Populates HTTP/2 header information for the given stream. For frames
1886 * associated with HEADERS this is the current frame, but for PUSH_PROMISE
1887 * populate information for the promised stream id.
1890 populate_http_header_tracking(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
*h2session
,
1891 const char *header_name
, const char *header_value
, uint32_t stream_id
, const bool override
)
1893 http2_stream_info_t
*stream_info
= get_stream_info_for_id(pinfo
, h2session
, false, stream_id
);
1894 http2_data_stream_body_info_t
*body_info
= get_data_stream_body_info_for_id(pinfo
, h2session
, stream_id
);
1895 http2_data_stream_reassembly_info_t
*reassembly_info
= get_data_reassembly_info_for_id(pinfo
, h2session
, stream_id
);
1897 /* header_value is after validation as UTF-8, so the length may have
1898 * changed due to REPLACEMENT CHARACTERS on packets with errors.
1900 size_t header_value_length
= strlen(header_value
);
1902 /* Populate the content encoding used so we can uncompress the body later if required */
1903 if (strcmp(header_name
, HTTP2_HEADER_CONTENT_ENCODING
) == 0) {
1904 if (body_info
->content_encoding
== NULL
|| override
== true) {
1905 body_info
->content_encoding
= wmem_strndup(wmem_file_scope(), header_value
, header_value_length
);
1909 /* Store the frame number so we can enhance the display of request/response */
1910 if (strcmp(header_name
, HTTP2_HEADER_METHOD
) == 0) {
1911 stream_info
->request_in_frame_num
= pinfo
->num
;
1912 stream_info
->request_ts
= pinfo
->abs_ts
;
1914 if (strcmp(header_name
, HTTP2_HEADER_STATUS
) == 0) {
1915 stream_info
->response_in_frame_num
= pinfo
->num
;
1918 /* Is this a partial content? */
1919 if (strcmp(header_name
, HTTP2_HEADER_STATUS
) == 0 &&
1920 strcmp(header_value
, HTTP2_HEADER_STATUS_PARTIAL_CONTENT
) == 0) {
1921 body_info
->is_partial_content
= true;
1924 /* Was this header used to initiate transfer of data frames? We'll use this later for reassembly */
1925 if (strcmp(header_name
, HTTP2_HEADER_STATUS
) == 0 ||
1926 strcmp(header_name
, HTTP2_HEADER_METHOD
) == 0 ||
1927 /* If we are in the middle of a stream assume there might be data transfer */
1928 strcmp(header_name
, HTTP2_HEADER_UNKNOWN
) == 0){
1929 if (reassembly_info
->data_initiated_in
== 0) {
1930 reassembly_info
->data_initiated_in
= get_http2_frame_num(tvb
, pinfo
);
1934 /* Do we have transfer encoding of bodies? We don't support reassembling these so mark it as such. */
1935 if (strcmp(header_name
, HTTP2_HEADER_TRANSFER_ENCODING
) == 0) {
1936 reassembly_info
->has_transfer_encoded_body
= true;
1939 /* Store away if the stream is associated with a CONNECT request */
1940 if (strcmp(header_name
, HTTP2_HEADER_METHOD
) == 0 &&
1941 strcmp(header_value
, HTTP2_HEADER_METHOD_CONNECT
) == 0) {
1942 stream_info
->is_stream_http_connect
= true;
1945 /* Populate the content type so we can dissect the body later */
1946 if (strcmp(header_name
, HTTP2_HEADER_CONTENT_TYPE
) == 0) {
1947 if (body_info
->content_type
== NULL
|| override
== true) {
1948 body_info
->content_type
= get_content_type_only(header_value
, header_value_length
);
1949 body_info
->content_type_parameters
= get_content_type_parameters_only(header_value
, header_value_length
);
1950 stream_info
->reassembly_mode
= http2_get_data_reassembly_mode(body_info
->content_type
);
1951 dissector_handle_t handle
= dissector_get_string_handle(media_type_dissector_table
, body_info
->content_type
);
1953 dissector_add_uint("http2.streamid", stream_info
->stream_id
, handle
);
1958 if (strcmp(header_name
, HTTP2_HEADER_PATH
) == 0) {
1959 stream_info
->path
= wmem_strndup(wmem_file_scope(), header_value
, header_value_length
);
1962 if (strcmp(header_name
, HTTP2_HEADER_AUTHORITY
) == 0) {
1963 stream_info
->authority
= wmem_strndup(wmem_file_scope(), header_value
, header_value_length
);
1966 if (strcmp(header_name
, HTTP2_HEADER_SCHEME
) == 0) {
1967 stream_info
->scheme
= wmem_strndup(wmem_file_scope(), header_value
, header_value_length
);
1972 try_append_method_path_info(packet_info
*pinfo
, proto_tree
*tree
,
1973 const char *method_header_value
, const char *path_header_value
)
1975 if (method_header_value
!= NULL
&& path_header_value
!= NULL
) {
1976 /* append request information to info column (for example, HEADERS: GET /demo/1.jpg) */
1977 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, ": ", "%s %s", method_header_value
, path_header_value
);
1978 /* append request information to Stream node */
1979 proto_item_append_text(tree
, ", %s %s", method_header_value
, path_header_value
);
1984 try_add_named_header_field(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, uint32_t length
, const char *header_name
, const char *header_value
)
1987 header_field_info
*hfi
;
1988 proto_item
* ti
= NULL
;
1990 const int *entry
= (const int*) g_hash_table_lookup(header_fields_hash
, header_name
);
1991 if (entry
== NULL
) {
1997 hfi
= proto_registrar_get_nth(hf_id
);
1998 DISSECTOR_ASSERT(hfi
!= NULL
);
2000 if (FT_IS_UINT32(hfi
->type
)) {
2002 if (ws_strtou32(header_value
, NULL
, &value
)) {
2003 ti
= proto_tree_add_uint(tree
, hf_id
, tvb
, offset
, length
, value
);
2005 } else if (FT_IS_UINT(hfi
->type
)) {
2007 if (ws_strtou64(header_value
, NULL
, &value
)) {
2008 ti
= proto_tree_add_uint64(tree
, hf_id
, tvb
, offset
, length
, value
);
2011 ti
= proto_tree_add_item(tree
, hf_id
, tvb
, offset
, length
, ENC_BIG_ENDIAN
);
2017 fix_partial_header_dissection_support(nghttp2_hd_inflater
*hd_inflater
, bool *fix_it
)
2019 /* Workaround is not necessary or has already been applied, skip. */
2025 /* Sanity-check: the workaround should fill an empty dynamic table only and
2026 * not evict existing entries. It is expected to be empty given that this is
2027 * the first time processing headers, but double-check just to be sure.
2029 if (nghttp2_hd_inflate_get_dynamic_table_size(hd_inflater
) != 0) {
2030 // Dynamic table is non-empty, do not touch it!
2034 /* Support dissection of headers where the capture starts in the middle of a
2035 * TCP stream. In that case, the Headers Block Fragment might reference
2036 * earlier dynamic table entries unknown to the decompressor. To avoid a
2037 * fatal error that breaks all future header dissection in this connection,
2038 * populate the dynamic table with some dummy entries.
2039 * See also https://github.com/nghttp2/nghttp2/issues/1389
2041 * The number of entries in the dynamic table is dependent on the maximum
2042 * table size (SETTINGS_HEADER_TABLE_SIZE, defaults to 4096 bytes) and the
2043 * size of individual entries (32 + name length + value length where 32 is
2044 * the overhead from RFC 7541, Section 4.1). Since earlier header fields in
2045 * the dynamic table are unknown, we will try to use a small dummy header
2046 * field to maximize the number of entries: "<unknown>" with no value.
2048 * The binary instruction to insert this is defined in Figure 7 of RFC 7541.
2050 static const uint8_t dummy_header
[] = "\x40"
2051 "\x09" /* Name String Length */
2052 HTTP2_HEADER_UNKNOWN
/* Name String */
2053 "\0"; /* Value Length */
2054 const int dummy_header_size
= sizeof(dummy_header
) - 1;
2055 const int dummy_entries_to_add
= (int)(nghttp2_hd_inflate_get_max_dynamic_table_size(hd_inflater
) / (32 + dummy_header_size
- 3));
2056 for (int i
= dummy_entries_to_add
- 1; i
>= 0; --i
) {
2058 int inflate_flags
= 0;
2059 int rv
= (int)nghttp2_hd_inflate_hd2(hd_inflater
, &nv
, &inflate_flags
,
2060 dummy_header
, dummy_header_size
,
2062 if (rv
!= dummy_header_size
) {
2063 ws_log(WS_LOG_DOMAIN
, LOG_LEVEL_WARNING
,
2064 "unexpected decompression state: %d != %d", rv
,
2069 nghttp2_hd_inflate_end_headers(hd_inflater
);
2073 inflate_http2_header_block(tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
,
2074 unsigned headlen
, http2_session_t
*h2session
, uint8_t flags
)
2077 proto_tree
*header_tree
;
2078 proto_item
*header
, *ti
, *ti_named_field
;
2079 uint32_t header_name_length
;
2080 uint32_t header_value_length
;
2081 const uint8_t *header_name
;
2082 const uint8_t *header_value
;
2084 nghttp2_hd_inflater
*hd_inflater
;
2085 tvbuff_t
*header_tvb
= NULL
;
2089 uint32_t flow_index
;
2090 http2_header_data_t
*header_data
;
2091 http2_header_repr_info_t
*header_repr_info
;
2092 wmem_list_t
*header_list
;
2093 wmem_array_t
*headers
;
2095 const char *method_header_value
= NULL
;
2096 const char *path_header_value
= NULL
;
2097 http2_header_stream_info_t
* header_stream_info
;
2098 char *header_unescaped
= NULL
;
2100 if (!http2_hdrcache_map
) {
2101 http2_hdrcache_map
= wmem_map_new(wmem_file_scope(), http2_hdrcache_hash
, http2_hdrcache_equal
);
2104 header_data
= (http2_header_data_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_http2
, PROTO_DATA_KEY_HEADER
);
2105 header_list
= header_data
->header_list
;
2107 if(!PINFO_FD_VISITED(pinfo
)) {
2108 /* This packet has not been processed yet, which means this is
2109 the first linear scan. We do header decompression only
2110 once in linear scan and cache the result. If we don't
2111 cache, already processed data will be fed into decompressor
2112 again and again since dissector will be called randomly.
2113 This makes context out-of-sync. */
2114 int decompressed_bytes
= 0;
2116 /* Make sure the length isn't too large. */
2117 tvb_ensure_bytes_exist(tvb
, offset
, headlen
);
2118 headbuf
= (uint8_t*)wmem_alloc(pinfo
->pool
, headlen
);
2119 tvb_memcpy(tvb
, headbuf
, offset
, headlen
);
2121 flow_index
= select_http2_flow_index(pinfo
, h2session
);
2122 hd_inflater
= h2session
->hd_inflater
[flow_index
];
2123 header_repr_info
= &h2session
->header_repr_info
[flow_index
];
2125 fix_partial_header_dissection_support(hd_inflater
, &h2session
->fix_dynamic_table
[flow_index
]);
2127 final
= flags
& HTTP2_FLAGS_END_HEADERS
;
2129 headers
= wmem_array_sized_new(wmem_file_scope(), sizeof(http2_header_t
), 16);
2133 int inflate_flags
= 0;
2135 if (wmem_array_get_count(headers
) >= MAX_HTTP2_HEADER_LINES
) {
2136 header_data
->header_lines_exceeded
= true;
2140 rv
= (int)nghttp2_hd_inflate_hd2(hd_inflater
, &nv
,
2141 &inflate_flags
, headbuf
, headlen
, final
);
2150 rv
-= process_http2_header_repr_info(headers
, header_repr_info
, headbuf
- rv
, rv
);
2152 if(inflate_flags
& NGHTTP2_HD_INFLATE_EMIT
) {
2155 unsigned datalen
= (unsigned)(4 + nv
.namelen
+ 4 + nv
.valuelen
);
2156 http2_header_t
*out
;
2158 if (decompressed_bytes
+ datalen
>= MAX_HTTP2_HEADER_SIZE
) {
2159 header_data
->header_size_reached
= decompressed_bytes
;
2160 header_data
->header_size_attempted
= decompressed_bytes
+ datalen
;
2164 out
= wmem_new(wmem_file_scope(), http2_header_t
);
2166 out
->type
= header_repr_info
->type
;
2168 out
->table
.data
.idx
= header_repr_info
->integer
;
2170 out
->table
.data
.datalen
= datalen
;
2171 decompressed_bytes
+= datalen
;
2173 /* Prepare buffer... with the following format
2174 name length (uint32)
2176 value length (uint32)
2179 http2_header_pstr
= (char *)wmem_realloc(wmem_file_scope(), http2_header_pstr
, out
->table
.data
.datalen
);
2181 /* nv.namelen and nv.valuelen are of size_t. In order
2182 to get length in 4 bytes, we have to copy it to
2184 len
= (uint32_t)nv
.namelen
;
2185 phton32(&http2_header_pstr
[0], len
);
2186 memcpy(&http2_header_pstr
[4], nv
.name
, nv
.namelen
);
2188 len
= (uint32_t)nv
.valuelen
;
2189 phton32(&http2_header_pstr
[4 + nv
.namelen
], len
);
2190 memcpy(&http2_header_pstr
[4 + nv
.namelen
+ 4], nv
.value
, nv
.valuelen
);
2192 cached_pstr
= (char *)wmem_map_lookup(http2_hdrcache_map
, http2_header_pstr
);
2194 out
->table
.data
.data
= cached_pstr
;
2196 wmem_map_insert(http2_hdrcache_map
, http2_header_pstr
, http2_header_pstr
);
2197 out
->table
.data
.data
= http2_header_pstr
;
2198 http2_header_pstr
= NULL
;
2201 wmem_array_append(headers
, out
, 1);
2203 reset_http2_header_repr_info(header_repr_info
);
2205 if(inflate_flags
& NGHTTP2_HD_INFLATE_FINAL
) {
2206 nghttp2_hd_inflate_end_headers(hd_inflater
);
2209 if((inflate_flags
& NGHTTP2_HD_INFLATE_EMIT
) == 0 &&
2215 wmem_list_append(header_list
, headers
);
2217 if(!header_data
->current
) {
2218 header_data
->current
= wmem_list_head(header_list
);
2221 /* add this packet headers to stream header list */
2222 /* If this is a PUSH_PROMISE frame (or a CONTINUATION of a PUSH_PROMISE
2223 * field block), we don't want to add it to this list, but to the list
2224 * for the promised stream.
2226 uint32_t header_stream_id
= is_in_header_context(tvb
, pinfo
, h2session
);
2227 if (header_stream_id
== 0) {
2228 header_stream_id
= h2session
->current_stream_id
;
2230 header_stream_info
= get_header_stream_info_for_id(pinfo
, h2session
, false, header_stream_id
);
2231 if (header_stream_info
) {
2232 wmem_list_append(header_stream_info
->stream_header_list
, headers
);
2235 } else if (header_data
->current
) {
2236 headers
= (wmem_array_t
*)wmem_list_frame_data(header_data
->current
);
2238 header_data
->current
= wmem_list_frame_next(header_data
->current
);
2240 if(!header_data
->current
) {
2241 header_data
->current
= wmem_list_head(header_list
);
2247 if(wmem_array_get_count(headers
) == 0) {
2251 for(i
= 0; i
< wmem_array_get_count(headers
); ++i
) {
2255 in
= (http2_header_t
*)wmem_array_index(headers
, i
);
2257 if(in
->type
== HTTP2_HD_HEADER_TABLE_SIZE_UPDATE
) {
2261 header_len
+= in
->table
.data
.datalen
;
2263 /* Now setup the tvb buffer to have the new data */
2264 next_tvb
= tvb_new_child_real_data(tvb
, in
->table
.data
.data
, in
->table
.data
.datalen
, in
->table
.data
.datalen
);
2266 header_tvb
= tvb_new_composite();
2268 tvb_composite_append(header_tvb
, next_tvb
);
2276 tvb_composite_finalize(header_tvb
);
2277 add_new_data_source(pinfo
, header_tvb
, "Decompressed Header");
2279 ti
= proto_tree_add_uint(tree
, hf_http2_header_length
, header_tvb
, hoffset
, 1, header_len
);
2280 proto_item_set_generated(ti
);
2282 if (header_data
->header_size_attempted
> 0) {
2283 expert_add_info_format(pinfo
, ti
, &ei_http2_header_size
,
2284 "Decompression stopped after %u bytes (%u attempted).",
2285 header_data
->header_size_reached
,
2286 header_data
->header_size_attempted
);
2289 ti
= proto_tree_add_uint(tree
, hf_http2_header_count
, header_tvb
, hoffset
, 1, wmem_array_get_count(headers
));
2290 proto_item_set_generated(ti
);
2292 if (header_data
->header_lines_exceeded
) {
2293 expert_add_info(pinfo
, ti
, &ei_http2_header_lines
);
2296 wmem_strbuf_t
* headers_buf
= wmem_strbuf_create(pinfo
->pool
);
2297 wmem_strbuf_t
* header_buf
;
2299 for(i
= 0; i
< wmem_array_get_count(headers
); ++i
) {
2300 http2_header_t
*in
= (http2_header_t
*)wmem_array_index(headers
, i
);
2302 if(in
->type
== HTTP2_HD_HEADER_TABLE_SIZE_UPDATE
) {
2303 header
= proto_tree_add_item(tree
, hf_http2_header_table_size_update
, tvb
, offset
, in
->length
, ENC_NA
);
2305 header_tree
= proto_item_add_subtree(header
, ett_http2_headers
);
2307 proto_tree_add_uint(header_tree
, hf_http2_header_table_size
, tvb
, offset
, in
->length
, in
->table
.header_table_size
);
2309 offset
+= in
->length
;
2313 /* Populate tree with header name/value details. */
2314 /* Add 'Header' subtree with description. */
2316 header
= proto_tree_add_item(tree
, hf_http2_header
, tvb
, offset
, in
->length
, ENC_NA
);
2318 header_tree
= proto_item_add_subtree(header
, ett_http2_headers
);
2320 /* header value length */
2321 proto_tree_add_item_ret_uint(header_tree
, hf_http2_header_name_length
, header_tvb
, hoffset
, 4, ENC_BIG_ENDIAN
, &header_name_length
);
2324 /* Add header name. */
2325 proto_tree_add_item_ret_string(header_tree
, hf_http2_header_name
, header_tvb
, hoffset
, header_name_length
, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &header_name
);
2326 hoffset
+= header_name_length
;
2328 /* header value length */
2329 proto_tree_add_item_ret_uint(header_tree
, hf_http2_header_value_length
, header_tvb
, hoffset
, 4, ENC_BIG_ENDIAN
, &header_value_length
);
2332 /* Add header value. */
2333 proto_tree_add_item_ret_string(header_tree
, hf_http2_header_value
, header_tvb
, hoffset
, header_value_length
, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &header_value
);
2334 // check if field is http2 header https://tools.ietf.org/html/rfc7541#appendix-A
2335 ti_named_field
= try_add_named_header_field(header_tree
, header_tvb
, hoffset
, header_value_length
, header_name
, header_value
);
2337 /* Add header unescaped. */
2338 header_unescaped
= g_uri_unescape_string(header_value
, NULL
);
2339 if (header_unescaped
!= NULL
) {
2340 char *header_unescaped_valid
= ws_utf8_make_valid(pinfo
->pool
, header_unescaped
, strlen(header_unescaped
));
2341 ti
= proto_tree_add_string(header_tree
, hf_http2_header_unescaped
, header_tvb
, hoffset
, header_value_length
, header_unescaped_valid
);
2342 proto_item_set_generated(ti
);
2343 g_free(header_unescaped
);
2345 hoffset
+= header_value_length
;
2347 /* Track HEADER and CONTINUATION frames part thereof for this stream id.
2348 * For PUSH_PROMISE and CONTINUATION frames thereof, add to the promised stream id.
2349 * Only do it for the first pass in case the current layer changes, altering where the headers frame number,
2350 * http2_frame_num_t points to. */
2351 uint32_t header_stream_id
;
2352 if (!PINFO_FD_VISITED(pinfo
) && (header_stream_id
= is_in_header_context(tvb
, pinfo
, h2session
))) {
2353 populate_http_header_tracking(tvb
, pinfo
, h2session
, header_name
, header_value
, header_stream_id
, false);
2356 /* Add encoding representation */
2357 // This should probably be a bitmask for the first bits, see https://tools.ietf.org/html/rfc7541#section-6
2358 proto_tree_add_string(header_tree
, hf_http2_header_repr
, tvb
, offset
, 1, http2_header_repr_type
[in
->type
].strptr
);
2360 if(in
->type
== HTTP2_HD_INDEXED
||
2361 in
->type
== HTTP2_HD_LITERAL_INDEXING_INDEXED_NAME
||
2362 in
->type
== HTTP2_HD_LITERAL_INDEXED_NAME
||
2363 in
->type
== HTTP2_HD_LITERAL_NEVER_INDEXING_INDEXED_NAME
) {
2364 /* Only for HTTP2_HD_INDEXED, the index value covers the full
2365 * "in->length". In other cases, it is a subset. For simplicity,
2366 * just select 1 octet (this might not be accurate though). */
2367 unsigned index_length
= in
->length
;
2368 if (in
->type
!= HTTP2_HD_INDEXED
) {
2371 proto_tree_add_uint(header_tree
, hf_http2_header_index
, tvb
, offset
, index_length
, in
->table
.data
.idx
);
2374 header_buf
= wmem_strbuf_new(pinfo
->pool
, header_name
);
2375 wmem_strbuf_append_printf(header_buf
, ": %s", header_value
);
2376 proto_item_append_text(header
, ": %s", wmem_strbuf_get_str(header_buf
));
2377 wmem_strbuf_append_printf(headers_buf
, "%s\n", wmem_strbuf_finalize(header_buf
));
2379 /* Display :method, :path and :status in info column (just like http1.1 dissector does)*/
2380 if (strcmp(header_name
, HTTP2_HEADER_METHOD
) == 0) {
2381 method_header_value
= header_value
;
2382 try_append_method_path_info(pinfo
, tree
, method_header_value
, path_header_value
);
2384 else if (strcmp(header_name
, HTTP2_HEADER_PATH
) == 0) {
2385 path_header_value
= header_value
;
2386 try_append_method_path_info(pinfo
, tree
, method_header_value
, path_header_value
);
2387 http_add_path_components_to_tree(header_tvb
, pinfo
, ti_named_field
, hoffset
- header_value_length
, header_value_length
);
2389 else if (strcmp(header_name
, HTTP2_HEADER_STATUS
) == 0) {
2390 const char* reason_phase
= val_to_str_const((unsigned)strtoul(header_value
, NULL
, 10), vals_http_status_code
, "Unknown");
2391 /* append response status and reason phrase to info column (for example, HEADERS: 200 OK) */
2392 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, ": ", "%s %s", header_value
, reason_phase
);
2393 /* append response status and reason phrase to header_tree and Stream node */
2394 proto_item_append_text(header_tree
, " %s", reason_phase
);
2395 proto_item_append_text(tree
, ", %s %s", header_value
, reason_phase
);
2398 offset
+= in
->length
;
2401 if (have_tap_listener(http2_follow_tap
)) {
2402 http2_follow_tap_data_t
* follow_data
= wmem_new0(pinfo
->pool
, http2_follow_tap_data_t
);
2404 wmem_strbuf_append(headers_buf
, "\n");
2405 follow_data
->tvb
= tvb_new_child_real_data(header_tvb
,
2406 wmem_strbuf_get_str(headers_buf
), (unsigned)wmem_strbuf_get_len(headers_buf
),
2407 (int)wmem_strbuf_get_len(headers_buf
));
2408 follow_data
->stream_id
= h2session
->current_stream_id
;
2410 tap_queue_packet(http2_follow_tap
, pinfo
, follow_data
);
2414 /* If the initial/first HEADERS frame (containing ":method" or ":status" header) of this direction is not received
2415 * (normally because of starting capturing after a long-lived HTTP2 stream like gRPC streaming call has been establied),
2416 * we initialize the information in direction of the stream with the fake headers of wireshark http2 preferences.
2417 * In an other situation, some http2 headers are unable to be parse in current HEADERS frame because previous HEADERS
2418 * frames were not captured that causing HPACK index table not completed. Fake headers can also be used in this situation.
2421 try_init_stream_with_fake_headers(tvbuff_t
* tvb
, packet_info
* pinfo
, http2_session_t
* h2session
, proto_tree
* tree
, unsigned offset
)
2423 if (num_http2_fake_headers
== 0) {
2427 http2_direction_type direction
;
2428 range_t
* server_port_range
;
2429 uint32_t stream_id
= h2session
->current_stream_id
;
2430 wmem_array_t
* indexes
= NULL
; /* the indexes of fake headers matching this stream and direction */
2431 proto_item
* ti
, * ti_header
;
2432 proto_tree
* header_tree
;
2433 http2_frame_num_t http2_frame_num
= get_http2_frame_num(tvb
, pinfo
);
2435 http2_header_stream_info_t
* header_stream_info
= get_header_stream_info(pinfo
, h2session
, false);
2436 http2_data_stream_reassembly_info_t
* reassembly_info
= get_data_reassembly_info(pinfo
, h2session
);
2438 if (!PINFO_FD_VISITED(pinfo
) && header_stream_info
->fake_headers_initiated_fn
== 0) {
2439 header_stream_info
->fake_headers_initiated_fn
= http2_frame_num
;
2440 if (reassembly_info
->data_initiated_in
== 0) {
2441 /* At this time, the data_initiated_in has not been set,
2442 * indicating that the previous initial HEADERS frame has been lost.
2443 * We try to use fake headers to initialize stream reassembly info. */
2444 reassembly_info
->data_initiated_in
= http2_frame_num
;
2447 /* Initialize with fake headers in this frame.
2448 * Use only those fake headers that do not appear. */
2449 header_stream_info
->fake_headers
= wmem_array_sized_new(wmem_file_scope(), sizeof(http2_fake_header_t
*), 16);
2451 for (unsigned i
= 0; i
< num_http2_fake_headers
; ++i
) {
2452 http2_fake_header_t
* fake_header
= http2_fake_headers
+ i
;
2453 if (fake_header
->enable
== false ||
2454 (fake_header
->stream_id
> 0 && fake_header
->stream_id
!= stream_id
)) {
2458 server_port_range
= fake_header
->server_port_range
;
2459 if (value_is_in_range(server_port_range
, pinfo
->destport
)) {
2460 direction
= DIRECTION_IN
;
2461 } else if (value_is_in_range(server_port_range
, pinfo
->srcport
)) {
2462 direction
= DIRECTION_OUT
;
2467 if (fake_header
->direction
!= direction
) {
2472 if (get_real_header_value(pinfo
, fake_header
->header_name
, false) && fake_header
->override
== false) {
2473 /* If this header already appears, the fake header is ignored, unless we want to override. */
2477 populate_http_header_tracking(tvb
, pinfo
, h2session
,
2478 fake_header
->header_name
, fake_header
->header_value
, h2session
->current_stream_id
, fake_header
->override
);
2480 wmem_array_append(header_stream_info
->fake_headers
, &fake_header
, 1);
2484 if (header_stream_info
->fake_headers_initiated_fn
== http2_frame_num
) {
2485 indexes
= header_stream_info
->fake_headers
;
2486 /* Try to add the tree item of fake headers. */
2488 unsigned total_matching_fake_headers
= wmem_array_get_count(indexes
);
2490 ti
= proto_tree_add_uint(tree
, hf_http2_fake_header_count
, tvb
, offset
, 0, total_matching_fake_headers
);
2491 proto_item_append_text(ti
, " (Using fake headers because previous initial HEADERS frame is missing)");
2492 proto_item_set_generated(ti
);
2494 for (unsigned i
= 0; i
< total_matching_fake_headers
; ++i
) {
2495 http2_fake_header_t
* header
= *(http2_fake_header_t
**)wmem_array_index(indexes
, i
);
2497 ti_header
= proto_tree_add_item(tree
, hf_http2_fake_header
, tvb
, offset
, 0, ENC_NA
);
2498 header_tree
= proto_item_add_subtree(ti_header
, ett_http2_header
);
2499 proto_item_append_text(ti_header
, ": %s: %s", header
->header_name
, header
->header_value
);
2500 proto_item_set_generated(ti_header
);
2502 ti
= proto_tree_add_string(header_tree
, hf_http2_header_name
, tvb
, offset
, 0, header
->header_name
);
2503 proto_item_set_generated(ti
);
2504 ti
= proto_tree_add_string(header_tree
, hf_http2_header_value
, tvb
, offset
, 0, header
->header_value
);
2505 proto_item_set_generated(ti
);
2513 http2_follow_conv_filter(epan_dissect_t
*edt _U_
, packet_info
*pinfo
, unsigned *stream
, unsigned *sub_stream
)
2515 http2_session_t
*h2session
;
2516 struct tcp_analysis
*tcpd
;
2517 conversation_t
* conversation
;
2519 /* XXX: Since TCP doesn't use the endpoint API (and HTTP2 is
2520 * over TCP), we can only look up using the current pinfo addresses
2521 * and ports. We don't want to create a new conversion or stream.
2522 * Eventually the endpoint API should support storing multiple
2523 * endpoints and TCP should be changed to use the endpoint API.
2525 if (((pinfo
->net_src
.type
== AT_IPv4
&& pinfo
->net_dst
.type
== AT_IPv4
) ||
2526 (pinfo
->net_src
.type
== AT_IPv6
&& pinfo
->net_dst
.type
== AT_IPv6
))
2527 && (pinfo
->ptype
== PT_TCP
) &&
2528 (conversation
=find_conversation(pinfo
->num
, &pinfo
->net_src
, &pinfo
->net_dst
, CONVERSATION_TCP
, pinfo
->srcport
, pinfo
->destport
, 0)) != NULL
)
2530 h2session
= get_http2_session(pinfo
, conversation
);
2531 tcpd
= get_tcp_conversation_data(conversation
, pinfo
);
2535 if (h2session
== NULL
)
2538 *stream
= tcpd
->stream
;
2539 *sub_stream
= h2session
->current_stream_id
;
2540 return ws_strdup_printf("tcp.stream eq %u and http2.streamid eq %u", tcpd
->stream
, h2session
->current_stream_id
);
2547 get_http2_stream_count(unsigned streamid
)
2549 uint32_t result
= 0;
2552 GList
*entry_set
, *it
;
2554 entry
= (GHashTable
*)g_hash_table_lookup(streamid_hash
, GUINT_TO_POINTER(streamid
));
2555 if (entry
!= NULL
) {
2556 entry_set
= g_hash_table_get_keys(entry
);
2558 /* this is a doubly-linked list, g_list_sort has the same time complexity */
2559 for (it
= entry_set
; it
!= NULL
; it
= it
->next
) {
2560 key
= GPOINTER_TO_UINT(it
->data
);
2561 result
= key
> result
? key
: result
;
2563 g_list_free(entry_set
);
2570 is_http2_stream_contains(unsigned streamid
, int sub_stream_id
)
2574 entry
= (GHashTable
*)g_hash_table_lookup(streamid_hash
, GUINT_TO_POINTER(streamid
));
2575 if (entry
== NULL
) {
2579 if (!g_hash_table_contains(entry
, GINT_TO_POINTER(sub_stream_id
))) {
2587 http2_get_stream_id_le(unsigned streamid
, unsigned sub_stream_id
, unsigned *sub_stream_id_out
)
2589 // HTTP/2 Stream IDs are always 31 bit.
2590 int max_id
= (int)get_http2_stream_count(streamid
);
2591 int id
= (int)(sub_stream_id
& MASK_HTTP2_STREAMID
);
2595 for (; id
>= 0; id
--) {
2596 if (is_http2_stream_contains(streamid
, id
)) {
2597 *sub_stream_id_out
= (unsigned)id
;
2605 http2_get_stream_id_ge(unsigned streamid
, unsigned sub_stream_id
, unsigned *sub_stream_id_out
)
2607 // HTTP/2 Stream IDs are always 31 bit.
2608 int max_id
= (int)get_http2_stream_count(streamid
);
2609 for (int id
= (int)(sub_stream_id
& MASK_HTTP2_STREAMID
); id
<= max_id
; id
++) {
2610 if (is_http2_stream_contains(streamid
, id
)) {
2611 *sub_stream_id_out
= (unsigned)id
;
2619 http2_get_sub_stream_id(unsigned streamid
, unsigned sub_stream_id
, bool le
, unsigned *sub_stream_id_out
)
2622 return http2_get_stream_id_le(streamid
, sub_stream_id
, sub_stream_id_out
);
2624 return http2_get_stream_id_ge(streamid
, sub_stream_id
, sub_stream_id_out
);
2629 http2_follow_index_filter(unsigned stream
, unsigned sub_stream
)
2631 return ws_strdup_printf("tcp.stream eq %u and http2.streamid eq %u", stream
, sub_stream
);
2634 static tap_packet_status
2635 follow_http2_tap_listener(void *tapdata
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *data
, tap_flags_t flags
)
2637 follow_info_t
*follow_info
= (follow_info_t
*)tapdata
;
2638 const http2_follow_tap_data_t
*follow_data
= (const http2_follow_tap_data_t
*)data
;
2640 if (follow_info
->substream_id
!= SUBSTREAM_UNUSED
&&
2641 follow_info
->substream_id
!= follow_data
->stream_id
) {
2642 return TAP_PACKET_DONT_REDRAW
;
2645 return follow_tvb_tap_listener(tapdata
, pinfo
, NULL
, follow_data
->tvb
, flags
);
2649 dissect_http2_header_flags(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
, unsigned offset
, uint8_t type
)
2653 int* const * fields
;
2655 static int* const http2_hdr_flags
[] = {
2656 &hf_http2_flags_unused_headers
,
2657 &hf_http2_flags_priority
,
2658 &hf_http2_flags_padded
,
2659 &hf_http2_flags_end_headers
,
2660 &hf_http2_flags_end_stream
,
2664 static int* const http2_data_flags
[] = {
2665 &hf_http2_flags_unused_data
,
2666 &hf_http2_flags_padded
,
2667 &hf_http2_flags_end_stream
,
2671 static int* const http2_settings_flags
[] = {
2672 &hf_http2_flags_unused_settings
,
2673 &hf_http2_flags_settings_ack
,
2677 static int* const http2_push_promise_flags
[] = {
2678 &hf_http2_flags_unused_push_promise
,
2679 &hf_http2_flags_padded
,
2680 &hf_http2_flags_end_headers
,
2684 static int* const http2_continuation_flags
[] = {
2685 &hf_http2_flags_unused_continuation
,
2686 &hf_http2_flags_padded
,
2687 &hf_http2_flags_end_headers
,
2691 static int* const http2_ping_flags
[] = {
2692 &hf_http2_flags_unused_ping
,
2693 &hf_http2_flags_ping_ack
,
2697 static int* const http2_unused_flags
[] = {
2698 &hf_http2_flags_unused
,
2706 fields
= http2_data_flags
;
2709 fields
= http2_hdr_flags
;
2711 case HTTP2_SETTINGS
:
2712 fields
= http2_settings_flags
;
2714 case HTTP2_PUSH_PROMISE
:
2715 fields
= http2_push_promise_flags
;
2717 case HTTP2_CONTINUATION
:
2718 fields
= http2_continuation_flags
;
2721 fields
= http2_ping_flags
;
2723 case HTTP2_PRIORITY
:
2724 case HTTP2_RST_STREAM
:
2726 case HTTP2_WINDOW_UPDATE
:
2730 case HTTP2_PRIORITY_UPDATE
:
2732 /* Does not define any flags */
2733 fields
= http2_unused_flags
;
2737 proto_tree_add_bitmask_with_flags_ret_uint64(http2_tree
, tvb
, offset
, hf_http2_flags
,
2738 ett_http2_flags
, fields
, ENC_BIG_ENDIAN
, BMT_NO_FALSE
| BMT_NO_INT
, &flags_val
);
2739 return (uint8_t)flags_val
;
2743 /* helper function to get the padding data for the frames that feature them */
2745 dissect_frame_padding(tvbuff_t
*tvb
, uint16_t *padding
, proto_tree
*http2_tree
,
2746 unsigned offset
, uint8_t flags
)
2749 unsigned pad_len
= 0;
2753 if(flags
& HTTP2_FLAGS_PADDED
)
2755 *padding
= tvb_get_uint8(tvb
, offset
); /* read a single octet */
2756 proto_tree_add_item(http2_tree
, hf_http2_padding
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2760 ti
= proto_tree_add_uint(http2_tree
, hf_http2_pad_length
, tvb
, offset
-pad_len
, pad_len
, *padding
);
2761 proto_item_set_generated(ti
);
2766 /* helper function to get the priority dependence for the frames that feature them:
2767 HEADERS and PRIORITY */
2769 dissect_frame_prio(tvbuff_t
*tvb
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags
)
2774 if(flags
& HTTP2_FLAGS_PRIORITY
)
2776 proto_tree_add_item(http2_tree
, hf_http2_excl_dependency
, tvb
, offset
, 4, ENC_NA
);
2777 proto_tree_add_item(http2_tree
, hf_http2_stream_dependency
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
2779 proto_tree_add_item(http2_tree
, hf_http2_weight
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2780 weight
= tvb_get_uint8(tvb
, offset
);
2781 /* 6.2: Weight: An 8-bit weight for the stream; Add one to the value to obtain a weight between 1 and 256 */
2782 ti
= proto_tree_add_uint(http2_tree
, hf_http2_weight_real
, tvb
, offset
, 1, weight
+1);
2783 proto_item_set_generated(ti
);
2792 static streaming_reassembly_info_t
*
2793 get_streaming_reassembly_info(packet_info
* pinfo
, http2_session_t
* http2_session
)
2795 http2_data_stream_reassembly_info_t
* data_reassembly_info
=
2796 &get_oneway_stream_info(pinfo
, http2_session
, false)->data_stream_reassembly_info
;
2798 if (data_reassembly_info
->streaming_reassembly_info
== NULL
) {
2799 data_reassembly_info
->streaming_reassembly_info
= streaming_reassembly_info_new();
2802 return data_reassembly_info
->streaming_reassembly_info
;
2805 enum body_uncompression
{
2806 BODY_UNCOMPRESSION_NONE
,
2807 BODY_UNCOMPRESSION_ZLIB
,
2808 BODY_UNCOMPRESSION_BROTLI
,
2809 BODY_UNCOMPRESSION_ZSTD
2812 static enum body_uncompression
2813 get_body_uncompression_info(packet_info
*pinfo
, http2_session_t
* h2session
)
2815 http2_data_stream_body_info_t
*body_info
= get_data_stream_body_info(pinfo
, h2session
);
2816 char *content_encoding
= body_info
->content_encoding
;
2818 /* Check we have a content-encoding header appropriate as well as checking if this is partial content.
2819 * We can't decompress part of a gzip encoded entity */
2820 /* XXX - Should there be an expert info if a body is compressed but support
2821 * for that decompression method was not compiled in? */
2822 if (!http2_decompress_body
|| body_info
->is_partial_content
== true || content_encoding
== NULL
) {
2823 return BODY_UNCOMPRESSION_NONE
;
2826 if (strncmp(content_encoding
, "gzip", 4) == 0 || strncmp(content_encoding
, "deflate", 7) == 0) {
2827 return BODY_UNCOMPRESSION_ZLIB
;
2831 if (strncmp(content_encoding
, "gzip", 4) == 0 || strncmp(content_encoding
, "deflate", 7) == 0) {
2832 return BODY_UNCOMPRESSION_ZLIB
;
2836 if (strncmp(content_encoding
, "br", 2) == 0) {
2837 return BODY_UNCOMPRESSION_BROTLI
;
2841 if (strncmp(content_encoding
, "zstd", 4) == 0) {
2842 return BODY_UNCOMPRESSION_ZSTD
;
2846 return BODY_UNCOMPRESSION_NONE
;
2849 /* Try to dissect reassembled http2.data.data according to content_type. */
2851 dissect_body_data(proto_tree
*tree
, packet_info
*pinfo
, http2_session_t
* h2session
, tvbuff_t
*tvb
,
2852 const int start
, int length
, const unsigned encoding
, bool streaming_mode
)
2854 http2_data_stream_body_info_t
*body_info
= get_data_stream_body_info(pinfo
, h2session
);
2855 http2_stream_info_t
*stream_info
= get_stream_info(pinfo
, h2session
, false);
2856 char *content_type
= body_info
->content_type
;
2857 media_content_info_t metadata_used_for_media_type_handle
= { MEDIA_CONTAINER_HTTP_OTHERS
, body_info
->content_type_parameters
, NULL
, NULL
};
2861 stream_id
= http2_get_stream_id(pinfo
);
2862 if (!streaming_mode
)
2863 proto_tree_add_item(tree
, hf_http2_data_data
, tvb
, start
, length
, encoding
);
2865 if (have_tap_listener(http2_follow_tap
)) {
2866 http2_follow_tap_data_t
*follow_data
= wmem_new0(pinfo
->pool
, http2_follow_tap_data_t
);
2868 follow_data
->tvb
= tvb_new_subset_length(tvb
, start
, length
);
2869 follow_data
->stream_id
= stream_id
;
2871 tap_queue_packet(http2_follow_tap
, pinfo
, follow_data
);
2874 if (have_tap_listener(http_eo_tap
)) {
2875 eo_info
= wmem_new0(pinfo
->pool
, http_eo_t
);
2877 eo_info
->filename
= stream_info
->path
;
2878 eo_info
->hostname
= stream_info
->authority
;
2879 eo_info
->content_type
= content_type
;
2880 eo_info
->payload
= tvb_new_subset_length(tvb
, start
, length
);
2882 tap_queue_packet(http_eo_tap
, pinfo
, eo_info
);
2885 tvbuff_t
*data_tvb
= tvb_new_subset_length(tvb
, start
, length
);
2886 if (content_type
!= NULL
) {
2887 /* add it to STREAM level */
2888 proto_tree
* ptree
= proto_tree_get_parent_tree(tree
);
2889 dissector_try_string_with_data((streaming_mode
? streaming_content_type_dissector_table
: media_type_dissector_table
),
2890 content_type
, data_tvb
, pinfo
,
2891 ptree
, true, &metadata_used_for_media_type_handle
);
2893 if (!dissector_try_uint_with_data(stream_id_content_type_dissector_table
, stream_id
,
2894 data_tvb
, pinfo
, proto_tree_get_parent_tree(tree
), true, &metadata_used_for_media_type_handle
))
2896 /* Try heuristics */
2897 /* Check for possible boundary string */
2898 if (tvb_strneql(data_tvb
, 0, "--", 2) == 0) {
2900 int boundary_len
= tvb_find_line_end(data_tvb
, 0, -1, &next_offset
, true);
2901 if ((boundary_len
> 4) && (boundary_len
< 70)){
2902 boundary_len
= boundary_len
- 2; /* ignore ending CRLF*/
2903 /* We have a potential boundary string */
2904 uint8_t *boundary
= tvb_get_string_enc(wmem_packet_scope(), data_tvb
, 2, boundary_len
, ENC_ASCII
| ENC_NA
);
2905 if (tvb_strneql(data_tvb
, (length
- 4) - boundary_len
, boundary
, boundary_len
) == 0) {
2906 /* We have multipart/mixed */
2907 /* Populate the content type so we can dissect the body later */
2908 body_info
->content_type
= wmem_strndup(wmem_file_scope(), "multipart/mixed", 15);
2909 body_info
->content_type_parameters
= wmem_strdup_printf(wmem_file_scope(), "boundary=\"%s\"", boundary
);
2910 metadata_used_for_media_type_handle
.media_str
= body_info
->content_type_parameters
;
2911 dissector_try_uint_with_data(stream_id_content_type_dissector_table
, stream_id
,
2912 data_tvb
, pinfo
, proto_tree_get_parent_tree(tree
), true, &metadata_used_for_media_type_handle
);
2916 } /* Not multipart/mixed*/
2917 /* check for json, from RFC 4627
2918 * A JSON text is a serialized object or array.
2919 * JSON-text = object / array
2920 * These are the six structural characters:
2921 * begin-array = ws %x5B ws ; [ left square bracket
2922 * begin-object = ws %x7B ws ; { left curly bracket
2924 * Insignificant whitespace is allowed before or after any of the six
2925 * structural characters.
2928 * %x09 / ; Horizontal tab
2929 * %x0A / ; Line feed or New line
2930 * %x0D ; Carriage return
2934 offset
= tvb_skip_wsp(data_tvb
, 0, length
);
2935 uint8_t oct
= tvb_get_uint8(data_tvb
, offset
);
2936 if ((oct
== 0x5b) || (oct
== 0x7b)) {
2937 /* Potential json */
2938 const uint8_t* buf
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, length
, ENC_ASCII
);
2940 if (json_validate(buf
, length
) == true) {
2941 body_info
->content_type
= wmem_strndup(wmem_file_scope(), "application/json", 16);
2942 dissector_handle_t handle
= dissector_get_string_handle(media_type_dissector_table
, body_info
->content_type
);
2943 metadata_used_for_media_type_handle
.media_str
= body_info
->content_type_parameters
;
2945 dissector_add_uint("http2.streamid", stream_info
->stream_id
, handle
);
2947 dissector_try_uint_with_data(stream_id_content_type_dissector_table
, stream_id
,
2948 data_tvb
, pinfo
, proto_tree_get_parent_tree(tree
), true, &metadata_used_for_media_type_handle
);
2957 dissect_http2_data_full_body(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* h2session
, proto_tree
*http2_tree
)
2963 int datalen
= tvb_reported_length(tvb
);
2965 enum body_uncompression uncompression
= get_body_uncompression_info(pinfo
, h2session
);
2966 if (uncompression
!= BODY_UNCOMPRESSION_NONE
) {
2967 proto_item
*compressed_proto_item
= NULL
;
2969 tvbuff_t
*uncompressed_tvb
= NULL
;
2970 if (uncompression
== BODY_UNCOMPRESSION_ZLIB
) {
2971 uncompressed_tvb
= tvb_child_uncompress_zlib(tvb
, tvb
, 0, datalen
);
2972 } else if (uncompression
== BODY_UNCOMPRESSION_BROTLI
) {
2973 uncompressed_tvb
= tvb_child_uncompress_brotli(tvb
, tvb
, 0, datalen
);
2974 } else if (uncompression
== BODY_UNCOMPRESSION_ZSTD
) {
2975 uncompressed_tvb
= tvb_child_uncompress_zstd(tvb
, tvb
, 0, datalen
);
2978 http2_data_stream_body_info_t
*body_info
= get_data_stream_body_info(pinfo
, h2session
);
2979 char *compression_method
= body_info
->content_encoding
;
2981 proto_tree
*compressed_entity_tree
= proto_tree_add_subtree_format(http2_tree
, tvb
, 0, datalen
, ett_http2_encoded_entity
,
2982 &compressed_proto_item
, "Content-encoded entity body (%s): %u bytes",
2983 compression_method
== NULL
? "unknown" : compression_method
, datalen
2986 if (uncompressed_tvb
!= NULL
) {
2987 unsigned uncompressed_length
= tvb_captured_length(uncompressed_tvb
);
2988 add_new_data_source(pinfo
, uncompressed_tvb
, "Uncompressed entity body");
2989 proto_item_append_text(compressed_proto_item
, " -> %u bytes", uncompressed_length
);
2990 dissect_body_data(compressed_entity_tree
, pinfo
, h2session
, uncompressed_tvb
, 0, uncompressed_length
, ENC_NA
, false);
2993 proto_tree_add_expert(compressed_entity_tree
, pinfo
, &ei_http2_body_decompression_failed
, tvb
, 0, datalen
);
2994 dissect_body_data(compressed_entity_tree
, pinfo
, h2session
, tvb
, 0, datalen
, ENC_NA
, false);
2997 dissect_body_data(http2_tree
, pinfo
, h2session
, tvb
, 0, datalen
, ENC_NA
, false);
3003 should_attempt_to_reassemble_data_frame(http2_data_stream_reassembly_info_t
*reassembly
, packet_info
*pinfo _U_
,
3004 http2_session_t
* http2_session
)
3006 /* If we haven't captured the header frame with the request/response we don't know how many data
3007 * frames we might have lost before processing */
3008 if (reassembly
->data_initiated_in
== 0) {
3012 /* For now, do not reassemble transfer encoded bodies. Chunked encoding is explicitly disallowed by RFC7540,
3013 * section 8.1. Additionally, section 8.1.2.2 specifies that the only valid value for the TE header (indicating
3014 * which transfer-encoding is allowed) is trailers, suggesting transfer coding other than chunked (gzip,
3015 * deflate, etc) are not allowed */
3016 if (reassembly
->has_transfer_encoded_body
) {
3020 /* Is this data frame part of an established tunnel? Don't try to reassemble the data if that is the case */
3021 http2_stream_info_t
*stream_info
= get_stream_info(pinfo
, http2_session
, false);
3022 if (stream_info
->is_stream_http_connect
) {
3030 get_reassembly_id_from_stream(packet_info
*pinfo
, http2_session_t
* session
)
3032 http2_stream_info_t
*stream_info
= get_stream_info(pinfo
, session
, false);
3033 uint32_t flow_index
= select_http2_flow_index(pinfo
, session
);
3035 /* With a stream ID being 31 bits, use the most significant bit to determine the flow direction of the
3036 * stream. We use this for the ID in the body reassembly using the reassemble API */
3037 return stream_info
->stream_id
| (flow_index
<< 31);
3041 * Like process_reassembled_data() in reassemble.[ch], but ignores the layer
3042 * number, which is not always stable in HTTP/2, if multiple TLS records are
3043 * in the same frame.
3046 http2_process_reassembled_data(tvbuff_t
*tvb
, const int offset
, packet_info
*pinfo
,
3047 const char *name
, fragment_head
*fd_head
, const fragment_items
*fit
,
3048 bool *update_col_infop
, proto_tree
*tree
)
3051 bool update_col_info
;
3052 proto_item
* frag_tree_item
;
3054 if (fd_head
!= NULL
) {
3056 * OK, we've reassembled this.
3057 * Is this something that's been reassembled from more
3058 * than one fragment?
3060 if (fd_head
->next
!= NULL
) {
3063 * Allocate a new tvbuff, referring to the
3064 * reassembled payload, and set
3065 * the tvbuff to the list of tvbuffs to which
3066 * the tvbuff we were handed refers, so it'll get
3067 * cleaned up when that tvbuff is cleaned up.
3069 next_tvb
= tvb_new_chain(tvb
, fd_head
->tvb_data
);
3071 /* Add the defragmented data to the data source list. */
3072 add_new_data_source(pinfo
, next_tvb
, name
);
3074 /* show all fragments */
3075 if (fd_head
->flags
& FD_BLOCKSEQUENCE
) {
3076 update_col_info
= !show_fragment_seq_tree(
3077 fd_head
, fit
, tree
, pinfo
, next_tvb
, &frag_tree_item
);
3080 update_col_info
= !show_fragment_tree(fd_head
,
3081 fit
, tree
, pinfo
, next_tvb
, &frag_tree_item
);
3087 * Return a tvbuff with the payload, a subset of the tvbuff
3091 if (fd_head
->flags
& FD_BLOCKSEQUENCE
) {
3094 // XXX Do the non-seq functions have this optimization?
3095 len
= fd_head
->datalen
;
3097 next_tvb
= tvb_new_subset_length(tvb
, offset
, len
);
3098 pinfo
->fragmented
= false; /* one-fragment packet */
3099 update_col_info
= true;
3101 if (update_col_infop
!= NULL
)
3102 *update_col_infop
= update_col_info
;
3105 * We don't have the complete reassembled payload, or this
3106 * isn't the final frame of that payload.
3109 /* process_reassembled_data() in reassemble.[ch] adds reassembled_in
3110 * here, but the reas_in_layer_num is often unstable in HTTP/2 now so
3111 * we rely on the stream end flag (that's why we have this function).
3113 * Perhaps we could DISSECTOR_ASSERT() in this path, we shouldn't
3121 reassemble_http2_data_into_full_frame(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* http2_session
, proto_tree
*http2_tree
, unsigned offset
,
3122 uint8_t flags
, unsigned datalen
)
3124 http2_data_stream_reassembly_info_t
*reassembly
= get_data_reassembly_info(pinfo
, http2_session
);
3126 /* There are a number of conditions as to why we may not want to reassemble DATA frames */
3127 if (!should_attempt_to_reassemble_data_frame(reassembly
, pinfo
, http2_session
)) {
3131 /* Continue to add fragments, checking if we have any more fragments */
3132 uint32_t reassembly_id
= get_reassembly_id_from_stream(pinfo
, http2_session
);
3133 fragment_head
*head
= NULL
;
3134 if (IS_HTTP2_END_STREAM(flags
) && datalen
== 0) {
3135 /* Workaround displaying "[Frame: N (no data)]" for a HTTP2 frame that contains no data but ends the stream */
3136 head
= fragment_end_seq_next(&http2_body_reassembly_table
, pinfo
, reassembly_id
, NULL
);
3138 head
= fragment_add_seq_next(&http2_body_reassembly_table
, tvb
, offset
, pinfo
, reassembly_id
, NULL
,
3139 datalen
, !IS_HTTP2_END_STREAM(flags
));
3142 /* Only call this if its the last DATA frame (END_STREAM) as the check in process_reassembled_data() will
3143 * incorrectly match for frames that exist in the same packet as the final DATA frame and incorrectly add
3144 * reassembly information to those dissection trees */
3145 if (head
&& IS_HTTP2_END_STREAM(flags
)) {
3146 return http2_process_reassembled_data(tvb
, offset
, pinfo
, "Reassembled body", head
,
3147 &http2_body_fragment_items
, NULL
, http2_tree
);
3150 /* Add frame where reassembly happened. process_reassembled_data() does this automatically if the reassembled
3151 * packet matches the packet that is calling the function, but makes some incorrect assumptions for multiple
3152 * fragments contained in the same packet */
3154 proto_tree_add_uint(http2_tree
, hf_http2_body_reassembled_in
, tvb
, 0, 0,
3155 head
->reassembled_in
);
3158 /* Reassembly not complete yet*/
3163 dissect_http2_data_partial_body(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* http2_session
, proto_tree
*http2_tree
, unsigned offset
, int length
,
3166 http2_data_stream_reassembly_info_t
*reassembly
= get_data_reassembly_info(pinfo
, http2_session
);
3168 /* Is the frame part of a body that is going to be reassembled? */
3169 if(!IS_HTTP2_END_STREAM(flags
)) {
3170 proto_item_append_text(http2_tree
, " (partial entity body)");
3173 /* If we somehow got a transfer-encoded body, display it here */
3174 if (reassembly
->has_transfer_encoded_body
) {
3175 proto_item_append_text(http2_tree
, " (transfer-encoded body)");
3178 /* Is this part of a tunneled connection? */
3179 http2_stream_info_t
*stream_info
= get_stream_info(pinfo
, http2_session
, false);
3180 if (stream_info
->is_stream_http_connect
) {
3181 proto_item_append_text(http2_tree
, " (tunneled data)");
3184 proto_tree_add_item(http2_tree
, hf_http2_data_data
, tvb
, offset
, length
, ENC_NA
);
3188 check_reassembly_completion_status(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* http2_tree
,
3189 unsigned offset
, uint8_t flags
, int length
, streaming_reassembly_info_t
* reassembly_info
)
3191 int more_bytes_expected
= additional_bytes_expected_to_complete_reassembly(reassembly_info
);
3193 if (IS_HTTP2_END_STREAM(flags
) && more_bytes_expected
) {
3194 if (more_bytes_expected
== DESEGMENT_ONE_MORE_SEGMENT
) {
3195 proto_tree_add_expert_format(http2_tree
, pinfo
, &ei_http2_reassembly_error
, tvb
, offset
, length
,
3196 "Reassembling HTTP2 body for subdissector failed, more bytes are missing before END_STREAM.");
3198 proto_tree_add_expert_format(http2_tree
, pinfo
, &ei_http2_reassembly_error
, tvb
, offset
, length
,
3199 "Reassembling HTTP2 body for subdissector failed, %d bytes are missing before END_STREAM.",
3200 more_bytes_expected
);
3205 /* Streaming reassembly of HTTP2 DATA will handle many cases. The most complicated one is:
3207 * +--------------------------------------------- HTTP2 DATA payload ---------------------------------------------+
3208 * | Part1: end of a multisegment PDU | Part2: one or more non-fragment PDUs | Part3: begin of a multisegment PDU |
3209 * +----------------------------------+--------------------------------------+------------------------------------+
3210 * Note: we use short name 'MSP' for 'Multisegment PDU', and 'NFP' for 'Non-fragment PDU'.
3212 * In this case, one HTTP2 DATA payload contains:
3213 * Part1: At the begin of the DATA, there is the last part of a multisegment PDU.
3214 * Part2: The middle part of DATA payload contains one or more non-fragment PDUs.
3215 * Part3: At the tail of the DATA, there is the begin of a new multisegment PDU.
3216 * All of three parts are optional. For example, one DATA could contain only Part1, Part2 or Part3; or contain
3217 * Part1 and Part2 without Part3; or contain Part1 and Part3 without Part2; or contain Part2 and Part3 without
3220 * And another case is the entire DATA is one of middle parts of a multisegment PDU. We call it MoMSP. Following
3221 * case shows a multisegment PDU composed of Part3 + MoMSP + MoMSP + MoMSP + Part1:
3223 * +-------------------------------- One Multisegment PDU ---------------------------------+
3225 * +----- HTTP2 DATA1 -----+ +------------- HTTP2 DATA2 -----------+ +- DATA3 -+ +- DATA4 -+ +- HTTP2 DATA5 -+
3226 * | Part1 | Part2 | Part3 | | MoMSP: middle of a multisegment PDU | | MoMSP | | MoMSP | | Part1 | Part3 |
3227 * +-------+-------+-------+ +-------------------------------------+ +---------+ +---------+ +---------------+
3229 * +---------------------------------------------------------------------------------------+
3231 * Subdissector behave: The pinfo->desegment_len should contain the estimated number of additional bytes required
3232 * for completing the PDU. and set pinfo->desegment_offset to the offset in the tvbuff at which the dissector will
3233 * continue processing when next called. Next time the subdissector is called, it will be passed a tvbuff composed
3234 * of the end of the data from the previous tvbuff together with desegment_len more bytes. If the dissector cannot
3235 * tell how many more bytes it will need, it should set pinfo->desegment_len to additional bytes required for parsing
3236 * message head or just DESEGMENT_ONE_MORE_SEGMENT. It will then be called again as soon as more data becomes available.
3237 * Please refer to comments of the declaration of reassemble_streaming_data_and_call_subdissector() function in
3238 * 'epan/reassemble.h' for more requirments about subdissectors.
3241 reassemble_http2_data_according_to_subdissector(tvbuff_t
* tvb
, packet_info
* pinfo
, http2_session_t
* http2_session
,
3242 proto_tree
* http2_tree
, unsigned offset
, uint8_t flags
, int length
)
3244 const char* saved_match_string
= pinfo
->match_string
;
3245 http2_frame_num_t cur_frame_num
= get_http2_frame_num(tvb
, pinfo
);
3247 proto_tree_add_bytes_format(http2_tree
, hf_http2_data_data
, tvb
, offset
,
3248 length
, NULL
, "DATA payload (%u byte%s)", length
, plurality(length
, "", "s"));
3250 http2_data_stream_body_info_t
* body_info
= get_data_stream_body_info(pinfo
, http2_session
);
3251 char* content_type
= body_info
->content_type
;
3252 media_content_info_t metadata_used_for_media_type_handle
= {
3253 MEDIA_CONTAINER_HTTP_OTHERS
, body_info
->content_type_parameters
, NULL
, NULL
3255 streaming_reassembly_info_t
* reassembly_info
= get_streaming_reassembly_info(pinfo
, http2_session
);
3257 dissector_handle_t subdissector_handle
= dissector_get_string_handle(streaming_content_type_dissector_table
, content_type
);
3258 if (subdissector_handle
== NULL
) {
3259 /* We didn't get the content type, possibly because of byte errors.
3260 * Note that the content type is per direction (as it should be)
3261 * but reassembly_mode is set the same for *both* directions.
3263 * We could try to set it to the content type used in the other
3264 * direction, but among other things, if this is the request,
3265 * we might be getting here for the first time on the second pass,
3266 * and reassemble_streaming_data_and_call_subdissector() asserts in
3268 * Just set it to data for now to avoid an assert from a NULL handle.
3270 subdissector_handle
= data_handle
;
3272 /* XXX - Do we still need to set this? */
3273 pinfo
->match_string
= content_type
;
3275 reassemble_streaming_data_and_call_subdissector(
3276 tvb
, pinfo
, offset
, length
, http2_tree
, proto_tree_get_parent_tree(http2_tree
),
3277 http2_streaming_reassembly_table
, reassembly_info
, (uint64_t)cur_frame_num
,
3278 subdissector_handle
, proto_tree_get_parent_tree(http2_tree
), &metadata_used_for_media_type_handle
,
3279 "HTTP2 body", &http2_body_fragment_items
, hf_http2_data_segment
);
3281 pinfo
->match_string
= saved_match_string
;
3283 if (IS_HTTP2_END_STREAM(flags
)) {
3284 check_reassembly_completion_status(tvb
, pinfo
, http2_tree
, offset
, flags
, length
, reassembly_info
);
3289 dissect_http2_data_body(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* h2session
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags
, int length
)
3291 try_init_stream_with_fake_headers(tvb
, pinfo
, h2session
, http2_tree
, offset
);
3293 http2_stream_info_t
*stream_info
= get_stream_info(pinfo
, h2session
, false);
3294 if (stream_info
->reassembly_mode
== HTTP2_DATA_REASSEMBLY_MODE_STREAMING
) {
3295 reassemble_http2_data_according_to_subdissector(tvb
, pinfo
, h2session
, http2_tree
, offset
, flags
, length
);
3299 tvbuff_t
*data_tvb
= reassemble_http2_data_into_full_frame(tvb
, pinfo
, h2session
, http2_tree
, offset
, flags
, length
);
3301 if (data_tvb
!= NULL
) {
3302 dissect_http2_data_full_body(data_tvb
, pinfo
, h2session
, http2_tree
);
3304 dissect_http2_data_partial_body(tvb
, pinfo
, h2session
, http2_tree
, offset
, length
, flags
);
3308 /* Get real header value from current or the other direction stream_header_list */
3310 get_real_header_value(packet_info
* pinfo
, const char* name
, bool the_other_direction
)
3312 http2_header_stream_info_t
* header_stream_info
;
3313 wmem_list_frame_t
* frame
;
3314 wmem_array_t
* headers
;
3318 http2_header_t
*hdr
;
3321 conversation_t
* conversation
= find_or_create_conversation(pinfo
);
3322 header_stream_info
= get_header_stream_info(pinfo
, get_http2_session(pinfo
, conversation
), the_other_direction
);
3323 if (!header_stream_info
) {
3327 for (frame
= wmem_list_head(header_stream_info
->stream_header_list
);
3329 frame
= wmem_list_frame_next(frame
))
3330 { /* each frame contains one HEADERS or CONTINUATION frame's headers */
3331 headers
= (wmem_array_t
*)wmem_list_frame_data(frame
);
3336 for (i
= 0; i
< wmem_array_get_count(headers
); ++i
) {
3337 hdr
= (http2_header_t
*)wmem_array_index(headers
, i
);
3338 if (hdr
->type
== HTTP2_HD_HEADER_TABLE_SIZE_UPDATE
) {
3342 /* parsing data as format:
3343 name length (uint32)
3345 value length (uint32)
3348 data
= (char*) hdr
->table
.data
.data
;
3349 name_len
= pntoh32(data
);
3350 if (strlen(name
) == name_len
&& strncmp(data
+ 4, name
, name_len
) == 0) {
3351 value_len
= pntoh32(data
+ 4 + name_len
);
3352 if (4 + name_len
+ 4 + value_len
== hdr
->table
.data
.datalen
) {
3354 return get_ascii_string(pinfo
->pool
, data
+ 4 + name_len
+ 4, value_len
);
3357 return NULL
; /* unexpected error */
3366 /* Get header value from current or the other direction stream_header_list */
3368 http2_get_header_value(packet_info
*pinfo
, const char* name
, bool the_other_direction
)
3370 bool override
= false;
3371 const char* real_value
= get_real_header_value(pinfo
, name
, the_other_direction
);
3372 const char* fake_value
= get_fake_header_value(pinfo
, name
, the_other_direction
, &override
);
3373 if (real_value
&& override
== false) {
3375 } else if (fake_value
) {
3382 dissect_http2_data_body(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, http2_session_t
* http2_session _U_
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags _U_
, int datalen
)
3384 proto_tree_add_item(http2_tree
, hf_http2_data_data
, tvb
, offset
, datalen
, ENC_NA
);
3388 http2_get_header_value(packet_info
*pinfo _U_
, const char* name _U_
, bool the_other_direction _U_
)
3394 /* Increment or decrement the accumulated connection and/or stream window
3395 * sizes based on the flow direction, stream ID and increaseWindow parameter.
3396 * In other words, if increaseWindow is true, then we're processing a
3397 * WINDOW_UPDATE frame; otherwise, we're processing a DATA frame.
3400 adjust_window_size(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* http2_session
, proto_tree
*http2_tree
, int32_t adjustment
, bool increaseWindow
)
3402 uint32_t flow_index
= select_http2_flow_index(pinfo
, http2_session
);
3403 int32_t finalAdjustment
= ((increaseWindow
? 1 : -1) * adjustment
);
3405 if (increaseWindow
) {
3406 /* The WINDOW_UPDATE comes in for the other direction */
3410 /* Always decrease the connection window after sending data,
3411 * but only increase the connection window for a WINDOW_UPDATE on stream 0 (the connection). */
3412 if (!increaseWindow
|| http2_session
->current_stream_id
== 0) {
3413 int32_t* window_size_connection_before
= p_get_proto_data(wmem_file_scope(), pinfo
, proto_http2
, PROTO_DATA_KEY_WINDOW_SIZE_CONNECTION_BEFORE
);
3414 int32_t window_size_connection_after
;
3416 if (!window_size_connection_before
) {
3417 /* There may be multiple passes, so we must use proto_data to keep state */
3418 window_size_connection_before
= wmem_new0(wmem_file_scope(), int32_t);
3419 (*window_size_connection_before
) = http2_session
->current_connection_window_size
[flow_index
];
3420 http2_session
->current_connection_window_size
[flow_index
] += finalAdjustment
;
3421 p_add_proto_data(wmem_file_scope(), pinfo
, proto_http2
, PROTO_DATA_KEY_WINDOW_SIZE_CONNECTION_BEFORE
, window_size_connection_before
);
3424 proto_item_set_generated(proto_tree_add_int(http2_tree
, hf_http2_calculated_window_size_connection_before
,
3425 tvb
, 0, 0, (*window_size_connection_before
)));
3427 window_size_connection_after
= (*window_size_connection_before
) + finalAdjustment
;
3429 proto_item_set_generated(proto_tree_add_int(http2_tree
, hf_http2_calculated_window_size_connection_after
,
3430 tvb
, 0, 0, window_size_connection_after
));
3434 /* Always decrease the stream window after sending data,
3435 * but only increase the stream window for a WINDOW_UPDATE on stream > 0 (not the connection). */
3436 if (!increaseWindow
|| http2_session
->current_stream_id
> 0) {
3437 http2_stream_info_t
*http2_stream_info
= get_stream_info(pinfo
, http2_session
, increaseWindow
);
3438 int32_t* window_size_stream_before
= p_get_proto_data(wmem_file_scope(), pinfo
, proto_http2
, PROTO_DATA_KEY_WINDOW_SIZE_STREAM_BEFORE
);
3439 int32_t window_size_stream_after
;
3441 if (!window_size_stream_before
) {
3442 /* There may be multiple passes, so we must use proto_data to keep state */
3443 window_size_stream_before
= wmem_new0(wmem_file_scope(), int32_t);
3444 (*window_size_stream_before
) = http2_stream_info
->oneway_stream_info
[flow_index
].current_window_size
;
3445 http2_stream_info
->oneway_stream_info
[flow_index
].current_window_size
+= finalAdjustment
;
3446 p_add_proto_data(wmem_file_scope(), pinfo
, proto_http2
, PROTO_DATA_KEY_WINDOW_SIZE_STREAM_BEFORE
, window_size_stream_before
);
3449 proto_item_set_generated(proto_tree_add_int(http2_tree
, hf_http2_calculated_window_size_stream_before
, tvb
, 0, 0,
3450 (*window_size_stream_before
)));
3452 window_size_stream_after
= (*window_size_stream_before
) + finalAdjustment
;
3454 proto_item_set_generated(proto_tree_add_int(http2_tree
, hf_http2_calculated_window_size_stream_after
, tvb
, 0, 0,
3455 window_size_stream_after
));
3462 dissect_http2_data(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* http2_session
, proto_tree
*http2_tree
,
3463 unsigned offset
, uint8_t flags
)
3468 offset
= dissect_frame_padding(tvb
, &padding
, http2_tree
, offset
, flags
);
3469 datalen
= tvb_reported_length_remaining(tvb
, offset
) - padding
;
3471 dissect_http2_data_body(tvb_new_subset_length(tvb
, offset
, datalen
), pinfo
, http2_session
, http2_tree
, 0, flags
, datalen
);
3476 proto_tree_add_item(http2_tree
, hf_http2_data_padding
, tvb
, offset
, padding
, ENC_NA
);
3480 adjust_window_size(tvb
, pinfo
, http2_session
, http2_tree
, (int32_t)datalen
, false);
3488 dissect_http2_headers(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* h2session
, proto_tree
*http2_tree
,
3489 unsigned offset
, uint8_t flags
)
3491 dissect_http2_headers(tvbuff_t
*tvb
, packet_info
*pinfo
, http2_session_t
* h2session _U_
, proto_tree
*http2_tree
,
3492 unsigned offset
, uint8_t flags
)
3498 fragment_head
*head
;
3499 http2_stream_info_t
*info
;
3500 streaming_reassembly_info_t
*reassembly_info
;
3502 /* Trailing headers coming after a DATA stream should have END_STREAM set. DATA should be complete
3503 * so try to reassemble DATA fragments if that is the case */
3504 if(IS_HTTP2_END_STREAM(flags
)) {
3505 info
= get_stream_info(pinfo
, h2session
, false);
3506 switch (info
->reassembly_mode
) {
3507 case HTTP2_DATA_REASSEMBLY_MODE_END_STREAM
:
3508 head
= fragment_end_seq_next(&http2_body_reassembly_table
, pinfo
, get_reassembly_id_from_stream(pinfo
, h2session
), NULL
);
3510 tvbuff_t
*reassembled_data
= process_reassembled_data(tvb
, 0, pinfo
, "Reassembled body", head
,
3511 &http2_body_fragment_items
, NULL
, http2_tree
);
3512 dissect_http2_data_full_body(reassembled_data
, pinfo
, h2session
, http2_tree
);
3516 case HTTP2_DATA_REASSEMBLY_MODE_STREAMING
:
3517 reassembly_info
= get_streaming_reassembly_info(pinfo
, h2session
);
3518 check_reassembly_completion_status(tvb
, pinfo
, http2_tree
, offset
, flags
, tvb_reported_length(tvb
), reassembly_info
);
3527 /* Mark this frame as the first header frame seen and last if the END_HEADERS flag
3528 * is set. We use this to ensure when we read header values, we are not reading ones
3529 * that have come from a PUSH_PROMISE header (and associated CONTINUATION frames) */
3530 if (!PINFO_FD_VISITED(pinfo
)) {
3531 http2_header_stream_info_t
*header_stream_info
= get_header_stream_info(pinfo
, h2session
, false);
3532 header_stream_info
->header_start_in
= get_http2_frame_num(tvb
, pinfo
);
3533 if (flags
& HTTP2_FLAGS_END_HEADERS
) {
3534 header_stream_info
->header_end_in
= get_http2_frame_num(tvb
, pinfo
);
3536 header_stream_info
->header_end_in
= 0;
3538 header_stream_info
->stream_id
= h2session
->current_stream_id
;
3542 offset
= dissect_frame_padding(tvb
, &padding
, http2_tree
, offset
, flags
);
3543 offset
= dissect_frame_prio(tvb
, http2_tree
, offset
, flags
);
3545 headlen
= tvb_reported_length_remaining(tvb
, offset
);
3546 if (headlen
< padding
) {
3547 /* XXX - what error *should* be reported here? */
3548 THROW(ReportedBoundsError
);
3551 proto_tree_add_item(http2_tree
, hf_http2_headers
, tvb
, offset
, headlen
, ENC_NA
);
3554 /* decompress the header block */
3555 inflate_http2_header_block(tvb
, pinfo
, offset
, http2_tree
, headlen
, h2session
, flags
);
3556 http2_stream_info_t
*stream_info
= get_stream_info(pinfo
, h2session
, false);
3558 /* Display request/response links */
3559 if (pinfo
->num
> stream_info
->request_in_frame_num
&& stream_info
->request_in_frame_num
> 0) {
3560 /* Response frame */
3561 if (! nstime_is_unset(&(stream_info
->request_ts
))) {
3564 nstime_delta(&delta
, &pinfo
->abs_ts
, &(stream_info
->request_ts
));
3565 proto_item_set_generated(proto_tree_add_time(http2_tree
, hf_http2_time
, tvb
, 0, 0, &delta
));
3567 proto_item_set_generated(proto_tree_add_uint(http2_tree
, hf_http2_request_in
, tvb
, 0, 0, stream_info
->request_in_frame_num
));
3569 if (pinfo
->num
== stream_info
->request_in_frame_num
&& stream_info
->response_in_frame_num
> 0) {
3571 proto_item_set_generated(proto_tree_add_uint(http2_tree
, hf_http2_response_in
, tvb
, 0, 0, stream_info
->response_in_frame_num
));
3575 proto_tree_add_expert_format(http2_tree
, pinfo
, &ei_http2_header_size
, tvb
, offset
, headlen
,
3576 "Wireshark must be built with nghttp2 for HTTP/2 HEADERS support");
3582 proto_tree_add_item(http2_tree
, hf_http2_headers_padding
, tvb
, offset
, padding
, ENC_NA
);
3591 dissect_http2_priority(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
,
3592 unsigned offset
, uint8_t flags
)
3594 /* we pretend the HTTP2_FLAGS_PRIORITY flag is set to share the dissect
3596 offset
= dissect_frame_prio(tvb
, http2_tree
, offset
,
3597 flags
| HTTP2_FLAGS_PRIORITY
);
3603 dissect_http2_rst_stream(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags _U_
)
3606 proto_tree_add_item(http2_tree
, hf_http2_rst_stream_error
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3614 adjust_existing_window(void *key _U_
, void *value
, void *userData _U_
)
3616 http2_stream_info_t
*stream_info
= (http2_stream_info_t
*)value
;
3617 http2_adjust_window_t
*adjustWindow
= (http2_adjust_window_t
*)userData
;
3618 stream_info
->oneway_stream_info
[adjustWindow
->flow_index
].current_window_size
+= adjustWindow
->windowSizeDiff
;
3625 dissect_http2_settings(tvbuff_t
* tvb
, packet_info
* pinfo _U_
, http2_session_t
* h2session
, proto_tree
* http2_tree
, unsigned offset
, uint8_t flags
)
3627 dissect_http2_settings(tvbuff_t
* tvb
, packet_info
* pinfo _U_
, http2_session_t
* h2session _U_
, proto_tree
* http2_tree
, unsigned offset
, uint8_t flags _U_
)
3630 uint32_t settingsid
;
3631 proto_item
*ti_settings
;
3632 proto_tree
*settings_tree
;
3634 uint32_t header_table_size
;
3635 uint32_t min_header_table_size
;
3636 int header_table_size_found
;
3638 header_table_size_found
= 0;
3639 header_table_size
= 0;
3640 min_header_table_size
= 0xFFFFFFFFu
;
3643 while(tvb_reported_length_remaining(tvb
, offset
) > 0){
3645 ti_settings
= proto_tree_add_item(http2_tree
, hf_http2_settings
, tvb
, offset
, 6, ENC_NA
);
3646 settings_tree
= proto_item_add_subtree(ti_settings
, ett_http2_settings
);
3647 proto_tree_add_item(settings_tree
, hf_http2_settings_identifier
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
3648 settingsid
= tvb_get_ntohs(tvb
, offset
);
3649 proto_item_append_text(ti_settings
, " - %s",
3650 val_to_str( settingsid
, http2_settings_vals
, "Unknown (%u)") );
3655 case HTTP2_SETTINGS_HEADER_TABLE_SIZE
:
3656 proto_tree_add_item(settings_tree
, hf_http2_settings_header_table_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3659 /* We only care the last header table size in SETTINGS */
3660 header_table_size_found
= 1;
3661 header_table_size
= tvb_get_ntohl(tvb
, offset
);
3662 if(min_header_table_size
> header_table_size
) {
3663 min_header_table_size
= header_table_size
;
3667 case HTTP2_SETTINGS_ENABLE_PUSH
:
3668 proto_tree_add_item(settings_tree
, hf_http2_settings_enable_push
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3670 case HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
:
3671 proto_tree_add_item(settings_tree
, hf_http2_settings_max_concurrent_streams
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3673 case HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
:
3675 uint32_t newInitialWindowSize
;
3677 proto_tree_add_item_ret_uint(settings_tree
, hf_http2_settings_initial_window_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &newInitialWindowSize
);
3680 uint32_t flow_index
= select_http2_flow_index(pinfo
, h2session
);
3682 /* This new initial window size will be applied to
3683 * any new future streams going in the other direction.
3684 * Note that this setting does not apply to the connection:
3685 * https://lists.w3.org/Archives/Public/ietf-http-wg/2023JanMar/0003.html
3689 h2session
->initial_new_stream_window_size
[flow_index
] = newInitialWindowSize
;
3693 uint32_t previousInitialWindowSize
= h2session
->initial_new_stream_window_size
[flow_index
];
3694 int32_t windowSizeDiff
= newInitialWindowSize
- previousInitialWindowSize
;
3696 /* "When the value of SETTINGS_INITIAL_WINDOW_SIZE changes,
3697 * a receiver MUST adjust the size of all stream flow-control
3698 * windows that it maintains by the difference between the
3699 * new value and the old value."
3700 * https://www.ietf.org/rfc/rfc9113.html#section-6.9.2-3
3702 if (windowSizeDiff
!= 0) {
3703 http2_adjust_window_t userData
;
3705 userData
.windowSizeDiff
= windowSizeDiff
;
3706 userData
.flow_index
= flow_index
;
3708 wmem_map_foreach(h2session
->per_stream_info
, adjust_existing_window
, &userData
);
3715 case HTTP2_SETTINGS_MAX_FRAME_SIZE
:
3716 proto_tree_add_item(settings_tree
, hf_http2_settings_max_frame_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3718 case HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
:
3719 proto_tree_add_item(settings_tree
, hf_http2_settings_max_header_list_size
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3721 case HTTP2_SETTINGS_EXTENDED_CONNECT
:
3722 proto_tree_add_item(settings_tree
, hf_http2_settings_extended_connect
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3724 case HTTP2_SETTINGS_NO_RFC7540_PRIORITIES
:
3725 proto_tree_add_item(settings_tree
, hf_http2_settings_no_rfc7540_priorities
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3728 proto_tree_add_item(settings_tree
, hf_http2_settings_unknown
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3731 proto_item_append_text(ti_settings
, " : %u", tvb_get_ntohl(tvb
, offset
));
3736 if(!PINFO_FD_VISITED(pinfo
)&&(h2session
!= NULL
)) {
3738 if(flags
& HTTP2_FLAGS_ACK
) {
3739 apply_and_pop_settings(pinfo
, h2session
);
3741 http2_settings_t
*settings
;
3743 settings
= wmem_new(wmem_file_scope(), http2_settings_t
);
3745 settings
->min_header_table_size
= min_header_table_size
;
3746 settings
->header_table_size
= header_table_size
;
3747 settings
->has_header_table_size
= header_table_size_found
;
3749 push_settings(pinfo
, h2session
, settings
);
3758 dissect_http2_settings_ext(tvbuff_t
* tvb
, packet_info
* pinfo _U_
, proto_tree
* http2_tree
, unsigned offset
) {
3759 dissect_http2_settings(tvb
, pinfo
, NULL
, http2_tree
, offset
, 0);
3765 dissect_http2_push_promise(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, http2_session_t
* h2session
, proto_tree
*http2_tree
,
3766 unsigned offset
, uint8_t flags _U_
)
3768 dissect_http2_push_promise(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, http2_session_t
* h2session _U_
, proto_tree
*http2_tree
,
3769 unsigned offset
, uint8_t flags _U_
)
3774 uint32_t promised_stream_id
;
3776 offset
= dissect_frame_padding(tvb
, &padding
, http2_tree
, offset
, flags
);
3778 proto_tree_add_item(http2_tree
, hf_http2_push_promise_r
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3779 proto_tree_add_item_ret_uint(http2_tree
, hf_http2_push_promise_promised_stream_id
, tvb
,
3780 offset
, 4, ENC_BIG_ENDIAN
, &promised_stream_id
);
3782 if (!PINFO_FD_VISITED(pinfo
)) {
3783 http2_header_stream_info_t
*header_stream_info
= get_header_stream_info(pinfo
, h2session
, false);
3784 header_stream_info
->header_start_in
= get_http2_frame_num(tvb
, pinfo
);
3785 if (flags
& HTTP2_FLAGS_END_HEADERS
) {
3786 header_stream_info
->header_end_in
= get_http2_frame_num(tvb
, pinfo
);
3788 header_stream_info
->header_end_in
= 0;
3790 header_stream_info
->stream_id
= promised_stream_id
;
3795 headlen
= tvb_reported_length_remaining(tvb
, offset
);
3796 if (headlen
< padding
) {
3797 /* XXX - what error *should* be reported here? */
3798 THROW(ReportedBoundsError
);
3801 proto_tree_add_item(http2_tree
, hf_http2_push_promise_header
, tvb
, offset
, headlen
,
3805 inflate_http2_header_block(tvb
, pinfo
, offset
, http2_tree
, headlen
, h2session
, flags
);
3807 /* Display request/response links */
3808 /* For PUSH_PROMISE, the response is on the promised stream ID. The
3809 * response is also in the same direction as the request.
3811 http2_stream_info_t
*stream_info
= get_stream_info_for_id(pinfo
, h2session
, false, promised_stream_id
);
3812 if (pinfo
->num
== stream_info
->request_in_frame_num
&& stream_info
->response_in_frame_num
> 0) {
3814 proto_item_set_generated(proto_tree_add_uint(http2_tree
, hf_http2_response_in
, tvb
, 0, 0, stream_info
->response_in_frame_num
));
3817 const char *uri
= http2_get_request_full_uri(pinfo
, h2session
, promised_stream_id
);
3819 proto_item
*uri_ti
= proto_tree_add_string_format(http2_tree
, hf_http2_header_request_full_uri
, tvb
, 0, 0, uri
, "Full promised request URI: %s", uri
);
3820 proto_item_set_url(uri_ti
);
3821 proto_item_set_generated(uri_ti
);
3828 proto_tree_add_item(http2_tree
, hf_http2_push_promise_padding
, tvb
,
3829 offset
, padding
, ENC_NA
);
3832 offset
+= tvb_reported_length_remaining(tvb
, offset
);
3839 dissect_http2_ping(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
,
3840 unsigned offset
, uint8_t flags
)
3842 /* TODO : Add Response time */
3843 if(flags
& HTTP2_FLAGS_ACK
)
3845 proto_tree_add_item(http2_tree
, hf_http2_pong
, tvb
, offset
, 8, ENC_NA
);
3847 proto_tree_add_item(http2_tree
, hf_http2_ping
, tvb
, offset
, 8, ENC_NA
);
3856 dissect_http2_goaway(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags _U_
)
3859 proto_tree_add_item(http2_tree
, hf_http2_goaway_r
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3860 proto_tree_add_item(http2_tree
, hf_http2_goaway_last_stream_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3863 proto_tree_add_item(http2_tree
, hf_http2_goaway_error
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3865 if(tvb_reported_length_remaining(tvb
, offset
) > 0)
3867 proto_tree_add_item(http2_tree
, hf_http2_goaway_addata
, tvb
, offset
, -1, ENC_NA
);
3868 offset
+= tvb_reported_length_remaining(tvb
, offset
);
3875 dissect_http2_window_update(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, http2_session_t
* http2_session
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags _U_
)
3879 proto_tree_add_item(http2_tree
, hf_http2_window_update_r
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3880 proto_tree_add_item_ret_uint(http2_tree
, hf_http2_window_update_window_size_increment
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &wsi
);
3883 adjust_window_size(tvb
, pinfo
, http2_session
, http2_tree
, wsi
, true);
3890 dissect_http2_continuation(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, http2_session_t
* h2session
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags
)
3892 dissect_http2_continuation(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, http2_session_t
* h2session _U_
, proto_tree
*http2_tree
, unsigned offset
, uint8_t flags
)
3898 /* Mark this as the last CONTINUATION frame for a HEADERS frame. This is used to know the context when we read
3899 * header (is the source a HEADER frame or a PUSH_PROMISE frame?) */
3900 if (!PINFO_FD_VISITED(pinfo
) && flags
& HTTP2_FLAGS_END_HEADERS
) {
3901 http2_header_stream_info_t
*stream_info
= get_header_stream_info(pinfo
, h2session
, false);
3902 if (stream_info
->header_start_in
!= 0 && stream_info
->header_end_in
== 0) {
3903 stream_info
->header_end_in
= get_http2_frame_num(tvb
, pinfo
);
3909 offset
= dissect_frame_padding(tvb
, &padding
, http2_tree
, offset
, flags
);
3911 headlen
= tvb_reported_length_remaining(tvb
, offset
);
3912 if (headlen
< padding
) {
3913 /* XXX - what error *should* be reported here? */
3914 THROW(ReportedBoundsError
);
3917 proto_tree_add_item(http2_tree
, hf_http2_continuation_header
, tvb
, offset
, headlen
, ENC_NA
);
3920 inflate_http2_header_block(tvb
, pinfo
, offset
, http2_tree
, headlen
, h2session
, flags
);
3926 proto_tree_add_item(http2_tree
, hf_http2_continuation_padding
, tvb
, offset
, padding
, ENC_NA
);
3936 dissect_http2_altsvc(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
,
3937 unsigned offset
, uint8_t flags _U_
, uint16_t length
)
3939 uint32_t origin_len
;
3940 int remain
= length
;
3942 proto_tree_add_item_ret_uint(http2_tree
, hf_http2_altsvc_origin_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &origin_len
);
3946 proto_tree_add_item(http2_tree
, hf_http2_altsvc_origin
, tvb
, offset
, origin_len
, ENC_ASCII
);
3947 offset
+= origin_len
;
3948 remain
-= origin_len
;
3951 proto_tree_add_item(http2_tree
, hf_http2_altsvc_field_value
, tvb
, offset
, remain
, ENC_ASCII
);
3960 dissect_http2_origin(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
,
3961 unsigned offset
, uint8_t flags _U_
)
3963 uint32_t origin_len
;
3965 proto_item
*ti_origin_entry
;
3966 proto_tree
*origin_entry_tree
;
3968 while(tvb_reported_length_remaining(tvb
, offset
) > 0){
3970 ti_origin_entry
= proto_tree_add_item(http2_tree
, hf_http2_origin
, tvb
, offset
, 6, ENC_NA
);
3971 origin_entry_tree
= proto_item_add_subtree(ti_origin_entry
, ett_http2_origin
);
3973 proto_tree_add_item_ret_uint(origin_entry_tree
, hf_http2_origin_origin_len
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &origin_len
);
3976 proto_tree_add_item(origin_entry_tree
, hf_http2_origin_origin
, tvb
, offset
, origin_len
, ENC_ASCII
);
3977 offset
+= origin_len
;
3983 /* Priority Update */
3985 dissect_http2_priority_update(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*http2_tree
,
3986 unsigned offset
, uint8_t flags _U_
, uint16_t length
)
3988 int remain
= length
;
3990 proto_tree_add_item(http2_tree
, hf_http2_priority_update_stream_id
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3994 proto_tree_add_item(http2_tree
, hf_http2_priority_update_field_value
, tvb
, offset
, remain
, ENC_ASCII
);
4002 dissect_http2_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
4005 proto_tree
*http2_tree
;
4006 unsigned offset
= 0;
4007 uint8_t type
, flags
;
4010 struct HTTP2Tap
*http2_stats
;
4012 struct tcp_analysis
* tcpd
;
4013 conversation_t
* conversation
= find_or_create_conversation(pinfo
);
4014 bool use_follow_tap
= true;
4016 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "HTTP2");
4018 ti
= proto_tree_add_item(tree
, proto_http2
, tvb
, 0, -1, ENC_NA
);
4020 http2_tree
= proto_item_add_subtree(ti
, ett_http2
);
4022 if(!p_get_proto_data(wmem_file_scope(), pinfo
, proto_http2
, PROTO_DATA_KEY_HEADER
)) {
4023 http2_header_data_t
*header_data
;
4025 header_data
= wmem_new0(wmem_file_scope(), http2_header_data_t
);
4026 header_data
->header_list
= wmem_list_new(wmem_file_scope());
4028 p_add_proto_data(wmem_file_scope(), pinfo
, proto_http2
, PROTO_DATA_KEY_HEADER
, header_data
);
4034 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
4035 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4037 +---------------+---------------+---------------+
4038 | Type (8) | Flags (8) |
4039 +-+-+-----------+---------------+-------------------------------+
4040 |R| Stream Identifier (31) |
4041 +=+=============================================================+
4042 | Frame Payload (0...) ...
4043 +---------------------------------------------------------------+
4045 ti
= proto_tree_add_item(http2_tree
, hf_http2_stream
, tvb
, 0, -1, ENC_NA
);
4047 http2_tree
= proto_item_add_subtree(ti
, ett_http2_header
);
4049 /* 3.5 Connection Header
4050 Upon establishment of a TCP connection and determination that
4051 HTTP/2 will be used by both peers, each endpoint MUST send a
4052 connection preface as a final confirmation and to establish the
4053 initial SETTINGS parameters for the HTTP/2 connection.
4055 /* tvb_memeql makes certain there are enough bytes in the buffer.
4056 * returns -1 if there are not enough bytes or if there is not a
4057 * match. Returns 0 on a match
4059 if (tvb_memeql(tvb
, offset
, kMagicHello
, MAGIC_FRAME_LENGTH
) == 0 )
4061 col_append_sep_str( pinfo
->cinfo
, COL_INFO
, ", ", "Magic" );
4063 proto_item_set_len(ti
, MAGIC_FRAME_LENGTH
);
4064 proto_item_append_text(ti
, ": Magic");
4066 proto_tree_add_item(http2_tree
, hf_http2_magic
, tvb
, offset
, MAGIC_FRAME_LENGTH
, ENC_ASCII
);
4068 return MAGIC_FRAME_LENGTH
;
4071 proto_tree_add_item(http2_tree
, hf_http2_length
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
4072 length
= tvb_get_ntoh24(tvb
, offset
);
4075 proto_tree_add_item(http2_tree
, hf_http2_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4076 type
= tvb_get_uint8(tvb
, offset
);
4079 const char *type_str
= try_val_to_str_idx(type
, http2_type_vals
, &type_idx
);
4080 if (type_str
== NULL
) {
4081 type_str
= wmem_strdup_printf(pinfo
->pool
, "Unknown type (%d)", type
);
4086 flags
= dissect_http2_header_flags(tvb
, pinfo
, http2_tree
, offset
, type
);
4089 proto_tree_add_item(http2_tree
, hf_http2_r
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
4090 proto_tree_add_item(http2_tree
, hf_http2_streamid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
4091 streamid
= tvb_get_ntohl(tvb
, offset
) & MASK_HTTP2_STREAMID
;
4092 proto_item_append_text(ti
, ": %s, Stream ID: %u, Length %u", type_str
, streamid
, length
);
4095 /* append stream id after frame type on info column, like: HEADERS[1], DATA[1], HEADERS[3], DATA[3] */
4096 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, ", ", "%s[%u]", type_str
, streamid
);
4098 /* fill hash table with stream ids and skip all unknown frames */
4099 tcpd
= get_tcp_conversation_data(conversation
, pinfo
);
4100 if (tcpd
!= NULL
&& type_idx
!= -1) {
4101 entry
= (GHashTable
*)g_hash_table_lookup(streamid_hash
, GUINT_TO_POINTER(tcpd
->stream
));
4102 if (entry
== NULL
) {
4103 entry
= g_hash_table_new(NULL
, NULL
);
4104 g_hash_table_insert(streamid_hash
, GUINT_TO_POINTER(tcpd
->stream
), entry
);
4107 g_hash_table_add(entry
, GUINT_TO_POINTER(streamid
));
4110 /* Mark the current stream, used for per-stream processing later in the dissection */
4111 http2_session_t
*http2_session
= get_http2_session(pinfo
, conversation
);
4112 http2_session
->current_stream_id
= streamid
;
4115 http2_stats
= wmem_new0(pinfo
->pool
, struct HTTP2Tap
);
4116 http2_stats
->type
= type
;
4119 case HTTP2_DATA
: /* Data (0) */
4120 dissect_http2_data(tvb
, pinfo
, http2_session
, http2_tree
, offset
, flags
);
4122 use_follow_tap
= false;
4126 case HTTP2_HEADERS
: /* Headers (1) */
4127 dissect_http2_headers(tvb
, pinfo
, http2_session
, http2_tree
, offset
, flags
);
4129 use_follow_tap
= false;
4133 case HTTP2_PRIORITY
: /* Priority (2) */
4134 dissect_http2_priority(tvb
, pinfo
, http2_tree
, offset
, flags
);
4137 case HTTP2_RST_STREAM
: /* RST Stream (3) */
4138 dissect_http2_rst_stream(tvb
, pinfo
, http2_tree
, offset
, flags
);
4141 case HTTP2_SETTINGS
: /* Settings (4) */
4142 dissect_http2_settings(tvb
, pinfo
, http2_session
, http2_tree
, offset
, flags
);
4145 case HTTP2_PUSH_PROMISE
: /* PUSH Promise (5) */
4146 dissect_http2_push_promise(tvb
, pinfo
, http2_session
, http2_tree
, offset
, flags
);
4148 use_follow_tap
= false;
4152 case HTTP2_PING
: /* Ping (6) */
4153 dissect_http2_ping(tvb
, pinfo
, http2_tree
, offset
, flags
);
4156 case HTTP2_GOAWAY
: /* Goaway (7) */
4157 dissect_http2_goaway(tvb
, pinfo
, http2_tree
, offset
, flags
);
4160 case HTTP2_WINDOW_UPDATE
: /* Window Update (8) */
4161 dissect_http2_window_update(tvb
, pinfo
, http2_session
, http2_tree
, offset
, flags
);
4164 case HTTP2_CONTINUATION
: /* Continuation (9) */
4165 dissect_http2_continuation(tvb
, pinfo
, http2_session
, http2_tree
, offset
, flags
);
4167 use_follow_tap
= false;
4171 case HTTP2_ALTSVC
: /* ALTSVC (10) */
4172 dissect_http2_altsvc(tvb
, pinfo
, http2_tree
, offset
, flags
, length
);
4175 case HTTP2_BLOCKED
: /* BLOCKED (11) */
4179 case HTTP2_ORIGIN
: /* ORIGIN (12) */
4180 dissect_http2_origin(tvb
, pinfo
, http2_tree
, offset
, flags
);
4183 case HTTP2_PRIORITY_UPDATE
: /* Priority Update (16) */
4184 dissect_http2_priority_update(tvb
, pinfo
, http2_tree
, offset
, flags
, length
);
4188 proto_tree_add_item(http2_tree
, hf_http2_unknown
, tvb
, offset
, -1, ENC_NA
);
4191 const char *uri
= http2_get_request_full_uri(pinfo
, http2_session
, streamid
);
4193 proto_item
*uri_ti
= proto_tree_add_string(http2_tree
, hf_http2_header_request_full_uri
, tvb
, 0, 0, uri
);
4194 proto_item_set_url(uri_ti
);
4195 proto_item_set_generated(uri_ti
);
4198 tap_queue_packet(http2_tap
, pinfo
, http2_stats
);
4200 /* HEADERS, CONTINUATION, and PUSH_PROMISE frames are compressed,
4201 * and sent to the follow tap inside inflate_http2_header_block.
4203 if (have_tap_listener(http2_follow_tap
) && use_follow_tap
) {
4204 http2_follow_tap_data_t
*follow_data
= wmem_new0(pinfo
->pool
, http2_follow_tap_data_t
);
4206 follow_data
->tvb
= tvb
;
4207 follow_data
->stream_id
= streamid
;
4209 tap_queue_packet(http2_follow_tap
, pinfo
, follow_data
);
4212 return tvb_captured_length(tvb
);
4215 static unsigned get_http2_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
4216 int offset
, void *data _U_
)
4218 if ( tvb_memeql( tvb
, offset
, kMagicHello
, FRAME_HEADER_LENGTH
) == 0 ) {
4219 /* We're only guaranteed to have FRAME_HEADER_LENGTH here, but if
4220 * those bytes match it's not a legal ordinary frame so it's
4221 * sufficient. If we're here, we've already decided this is HTTP/2
4222 * via heuristics or setting HTTP/2 to the port.
4224 return MAGIC_FRAME_LENGTH
;
4227 return (unsigned)tvb_get_ntoh24(tvb
, offset
) + FRAME_HEADER_LENGTH
;
4232 dissect_http2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
4235 /* XXX: Should tcp_dissect_pdus() set a fence after each PDU?
4236 * If so the col_clear could be moved inside dissect_http2_pdu.
4238 col_clear(pinfo
->cinfo
, COL_INFO
);
4240 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, FRAME_HEADER_LENGTH
,
4241 get_http2_message_len
, dissect_http2_pdu
, data
);
4243 return tvb_captured_length(tvb
);
4247 dissect_http2_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
4249 conversation_t
*conversation
;
4250 http2_session_t
*session
;
4252 conversation
= find_or_create_conversation(pinfo
);
4253 session
= (http2_session_t
*)conversation_get_proto_data(conversation
,
4255 /* A http2 conversation was previously started, assume it is still active */
4257 dissect_http2(tvb
, pinfo
, tree
, data
);
4261 if (tvb_memeql(tvb
, 0, kMagicHello
, MAGIC_FRAME_LENGTH
) != 0) {
4262 /* we couldn't find the Magic Hello (PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n). */
4266 /* Remember http2 conversation. */
4267 get_http2_session(pinfo
, conversation
);
4268 dissect_http2(tvb
, pinfo
, tree
, data
);
4274 dissect_http2_heur_http(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
4276 conversation_t
*conversation
;
4277 http2_session_t
*session
;
4279 conversation
= find_or_create_conversation(pinfo
);
4280 session
= (http2_session_t
*)conversation_get_proto_data(conversation
,
4282 /* A http2 conversation was previously started, assume it is still active */
4284 dissect_http2(tvb
, pinfo
, tree
, data
);
4288 /* The HTTP dissector should hand us at least one line, but possibly only
4289 * the first (if the TCP segment length is absurdly small.) 16 bytes is
4290 * still enough to call this HTTP/2.
4292 if (tvb_memeql(tvb
, 0, kMagicHello
, MAGIC_FRAME_FIRST_LINE
) != 0) {
4293 /* we couldn't find the Magic Hello (PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n). */
4297 /* Remember http2 conversation. */
4298 get_http2_session(pinfo
, conversation
);
4300 /* XXX - Ideally we'd set the conversation dissector so that TCP calls
4301 * HTTP/2 directly instead of HTTP. (Note we don't call this path for
4302 * upgraded connections, which still go through the HTTP dissector.)
4303 * That would change pinfo->curr_layer_num for this first packet on the
4304 * second pass, though, so we'd want to make sure we're using
4305 * curr_proto_layer_num or similar to avoid that being an issue,
4306 * e.g. on reassembly of HEADERS or DATA sent along with this frame.
4307 * So for now we have the HTTP dissector call the HTTP/2 dissector.
4309 //conversation_set_dissector_from_frame_number(conversation, pinfo->num, http2_handle);
4310 dissect_http2(tvb
, pinfo
, tree
, data
);
4316 dissect_http2_heur_ssl(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
4318 struct tlsinfo
*tlsinfo
= (struct tlsinfo
*) data
;
4319 if (dissect_http2_heur(tvb
, pinfo
, tree
, NULL
)) {
4320 *(tlsinfo
->app_handle
) = http2_handle
;
4327 proto_register_http2(void)
4330 static hf_register_info hf
[] = {
4333 { "Stream", "http2.stream",
4334 FT_NONE
, BASE_NONE
, NULL
, 0x0,
4338 { "Length", "http2.length",
4339 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
4340 "The length (24 bits) of the frame payload (The 9 octets of the frame header are not included)", HFILL
}
4343 { "Type", "http2.type",
4344 FT_UINT8
, BASE_DEC
, VALS(http2_type_vals
), 0x0,
4345 "The frame type determines how the remainder of the frame header and payload are interpreted", HFILL
}
4348 { "Reserved", "http2.r",
4349 FT_UINT32
, BASE_HEX
, NULL
, MASK_HTTP2_RESERVED
,
4350 "The semantics of this bit are undefined and the bit MUST remain unset (0) when sending and MUST be ignored when receiving", HFILL
}
4354 { "Weight", "http2.headers.weight",
4355 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4356 "An 8-bit weight for the identified priority", HFILL
}
4358 { &hf_http2_weight_real
,
4359 { "Weight real", "http2.headers.weight_real",
4360 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
4361 "Real Weight value (Add one to value)", HFILL
}
4363 { &hf_http2_streamid
,
4364 { "Stream Identifier", "http2.streamid",
4365 FT_UINT32
, BASE_DEC
, NULL
, MASK_HTTP2_STREAMID
,
4366 "A 31-bit stream identifier", HFILL
}
4369 { "Magic", "http2.magic",
4370 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4373 { &hf_http2_unknown
,
4374 { "Unknown", "http2.unknown",
4375 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4380 { "Flags", "http2.flags",
4381 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
4382 "Flags are assigned semantics specific to the indicated frame type", HFILL
}
4384 { &hf_http2_flags_end_stream
,
4385 { "End Stream", "http2.flags.end_stream",
4386 FT_BOOLEAN
, 8, NULL
, HTTP2_FLAGS_END_STREAM
,
4387 "Indicates that this frame is the last that the endpoint will send for the identified stream", HFILL
}
4389 { &hf_http2_flags_end_headers
,
4390 { "End Headers", "http2.flags.eh",
4391 FT_BOOLEAN
, 8, NULL
, HTTP2_FLAGS_END_HEADERS
,
4392 "Indicates that this frame contains an entire header block and is not followed by any CONTINUATION frames.", HFILL
}
4394 { &hf_http2_flags_padded
,
4395 { "Padded", "http2.flags.padded",
4396 FT_BOOLEAN
, 8, NULL
, HTTP2_FLAGS_PADDED
,
4397 "Indicates that the Pad Length field is present", HFILL
}
4399 { &hf_http2_flags_priority
,
4400 { "Priority", "http2.flags.priority",
4401 FT_BOOLEAN
, 8, NULL
, HTTP2_FLAGS_PRIORITY
,
4402 "Indicates that the Exclusive Flag (E), Stream Dependency, and Weight fields are present", HFILL
}
4405 { &hf_http2_flags_ping_ack
,
4406 { "ACK", "http2.flags.ack.ping",
4407 FT_BOOLEAN
, 8, NULL
, HTTP2_FLAGS_ACK
,
4408 "Set indicates that this PING frame is a PING response", HFILL
}
4410 { &hf_http2_flags_unused
,
4411 { "Unused", "http2.flags.unused",
4412 FT_UINT8
, BASE_HEX
, NULL
, HTTP2_FLAGS_UNUSED
,
4413 "Must be zero", HFILL
}
4415 { &hf_http2_flags_unused_settings
,
4416 { "Unused", "http2.flags.unused_settings",
4417 FT_UINT8
, BASE_HEX
, NULL
, HTTP2_FLAGS_UNUSED_SETTINGS
,
4418 "Must be zero", HFILL
}
4420 { &hf_http2_flags_unused_ping
,
4421 { "Unused", "http2.flags.unused_ping",
4422 FT_UINT8
, BASE_HEX
, NULL
, HTTP2_FLAGS_UNUSED_PING
,
4423 "Must be zero", HFILL
}
4425 { &hf_http2_flags_unused_continuation
,
4426 { "Unused", "http2.flags.unused_continuation",
4427 FT_UINT8
, BASE_HEX
, NULL
, HTTP2_FLAGS_UNUSED_CONTINUATION
,
4428 "Must be zero", HFILL
}
4430 { &hf_http2_flags_unused_push_promise
,
4431 { "Unused", "http2.flags.unused_push_promise",
4432 FT_UINT8
, BASE_HEX
, NULL
, HTTP2_FLAGS_UNUSED_PUSH_PROMISE
,
4433 "Must be zero", HFILL
}
4435 { &hf_http2_flags_unused_data
,
4436 { "Unused", "http2.flags.unused_data",
4437 FT_UINT8
, BASE_HEX
, NULL
, HTTP2_FLAGS_UNUSED_DATA
,
4438 "Must be zero", HFILL
}
4440 { &hf_http2_flags_unused_headers
,
4441 { "Unused", "http2.flags.unused_headers",
4442 FT_UINT8
, BASE_HEX
, NULL
, HTTP2_FLAGS_UNUSED_HEADERS
,
4443 "Must be zero", HFILL
}
4445 { &hf_http2_flags_settings_ack
,
4446 { "ACK", "http2.flags.ack.settings",
4447 FT_BOOLEAN
, 8, NULL
, HTTP2_FLAGS_ACK
,
4448 "Indicates that this frame acknowledges receipt and application of the peer's SETTINGS frame", HFILL
}
4450 { &hf_http2_padding
,
4451 { "Pad Length", "http2.padding",
4452 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
4453 "Padding size", HFILL
}
4455 { &hf_http2_pad_length
,
4456 { "Pad Length", "http2.pad_length",
4457 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4460 { &hf_http2_excl_dependency
,
4461 { "Exclusive", "http2.exclusive",
4462 FT_BOOLEAN
, 32, NULL
, 0x80000000,
4463 "A single bit flag indicates that the stream dependency is exclusive", HFILL
}
4465 { &hf_http2_stream_dependency
,
4466 { "Stream Dependency", "http2.stream_dependency",
4467 FT_UINT32
, BASE_DEC
, NULL
, 0x7FFFFFFF,
4468 "An identifier for the stream that this stream depends on", HFILL
}
4472 { &hf_http2_data_segment
,
4473 { "DATA segment", "http2.data.segment",
4474 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4475 "A data segment used in reassembly", HFILL
}
4477 { &hf_http2_data_data
,
4478 { "Data", "http2.data.data",
4479 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4480 "Application data", HFILL
}
4482 { &hf_http2_data_padding
,
4483 { "Padding", "http2.data.padding",
4484 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4485 "Padding octets", HFILL
}
4487 /* Body fragments */
4488 { &hf_http2_body_fragments
,
4489 { "Body fragments", "http2.body.fragments",
4490 FT_NONE
, BASE_NONE
, NULL
, 0x0,
4493 { &hf_http2_body_fragment
,
4494 { "Body fragment", "http2.body.fragment",
4495 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
4498 { &hf_http2_body_fragment_overlap
,
4499 { "Body fragment overlap", "http2.body.fragment.overlap",
4500 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4503 { &hf_http2_body_fragment_overlap_conflicts
,
4504 { "Body fragment overlapping with conflicting data", "http2.body.fragment.overlap.conflicts",
4505 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4508 { &hf_http2_body_fragment_multiple_tails
,
4509 { "Body has multiple tail fragments", "http2.body.fragment.multiple_tails",
4510 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4513 { &hf_http2_body_fragment_too_long_fragment
,
4514 { "Body fragment too long", "http2.body.fragment.too_long_fragment",
4515 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
4518 { &hf_http2_body_fragment_error
,
4519 { "Body defragment error", "http2.body.fragment.error",
4520 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
4523 { &hf_http2_body_fragment_count
,
4524 { "Body fragment count", "http2.body.fragment.count",
4525 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4528 { &hf_http2_body_reassembled_in
,
4529 { "Reassembled body in frame", "http2.body.reassembled.in",
4530 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
4531 "Reassembled body in frame number", HFILL
}
4533 { &hf_http2_body_reassembled_length
,
4534 { "Reassembled body length", "http2.body.reassembled.length",
4535 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4536 "Reassembled body in frame number", HFILL
}
4538 { &hf_http2_body_reassembled_data
,
4539 { "Reassembled body data", "http2.body.reassembled.data",
4540 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4541 "Reassembled body data for multisegment PDU spanning across DATAs", HFILL
}
4545 { &hf_http2_headers
,
4546 { "Header Block Fragment", "http2.headers",
4547 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4548 "A header block fragment", HFILL
}
4550 { &hf_http2_headers_padding
,
4551 { "Padding", "http2.headers.padding",
4552 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4553 "Padding octets", HFILL
}
4556 { "Header", "http2.header",
4557 FT_NONE
, BASE_NONE
, NULL
, 0x0,
4560 { &hf_http2_header_length
,
4561 { "Header Length", "http2.header.length",
4562 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4565 { &hf_http2_header_count
,
4566 { "Header Count", "http2.header.count",
4567 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4570 { &hf_http2_header_name_length
,
4571 { "Name Length", "http2.header.name.length",
4572 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4575 { &hf_http2_header_name
,
4576 { "Name", "http2.header.name",
4577 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4580 { &hf_http2_header_value_length
,
4581 { "Value Length", "http2.header.value.length",
4582 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4585 { &hf_http2_header_value
,
4586 { "Value", "http2.header.value",
4587 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4590 { &hf_http2_header_unescaped
,
4591 { "Unescaped", "http2.header.unescaped",
4592 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4595 { &hf_http2_header_repr
,
4596 { "Representation", "http2.header.repr",
4597 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4600 { &hf_http2_header_index
,
4601 { "Index", "http2.header.index",
4602 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4605 { &hf_http2_header_table_size_update
,
4606 { "Header table size update", "http2.header_table_size_update",
4607 FT_NONE
, BASE_NONE
, NULL
, 0x0,
4610 { &hf_http2_header_table_size
,
4611 { "Header table size", "http2.header_table_size_update.header_table_size",
4612 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4615 { &hf_http2_fake_header_count
,
4616 { "Fake Header Count", "http2.fake.header.count",
4617 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4620 { &hf_http2_fake_header
,
4621 { "Fake Header", "http2.fake.header",
4622 FT_NONE
, BASE_NONE
, NULL
, 0x0,
4625 { &hf_http2_header_request_full_uri
,
4626 { "Full request URI", "http2.request.full_uri",
4627 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4628 "The full requested URI (including host name)", HFILL
}
4632 { &hf_http2_rst_stream_error
,
4633 { "Error", "http2.rst_stream.error",
4634 FT_UINT32
, BASE_DEC
, VALS(http2_error_codes_vals
), 0x0,
4635 "The error code indicates why the stream is being terminated", HFILL
}
4639 { &hf_http2_settings
,
4640 { "Settings", "http2.settings",
4641 FT_NONE
, BASE_NONE
, NULL
, 0x0,
4644 { &hf_http2_settings_identifier
,
4645 { "Settings Identifier", "http2.settings.id",
4646 FT_UINT16
, BASE_DEC
, VALS(http2_settings_vals
), 0x0,
4649 { &hf_http2_settings_header_table_size
,
4650 { "Header table size", "http2.settings.header_table_size",
4651 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4652 "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
}
4654 { &hf_http2_settings_enable_push
,
4655 { "Enable PUSH", "http2.settings.enable_push",
4656 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4657 "The initial value is 1, which indicates that push is permitted", HFILL
}
4659 { &hf_http2_settings_max_concurrent_streams
,
4660 { "Max concurrent streams", "http2.settings.max_concurrent_streams",
4661 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4662 "Indicates the maximum number of concurrent streams that the sender will allow", HFILL
}
4664 { &hf_http2_settings_initial_window_size
,
4665 { "Initial Window Size", "http2.settings.initial_window_size",
4666 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4667 "Indicates the sender's initial window size (in bytes) for stream level flow control", HFILL
}
4669 { &hf_http2_settings_max_frame_size
,
4670 { "Max frame size", "http2.settings.max_frame_size",
4671 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4672 "Indicates the size of the largest frame payload that the sender will allow", HFILL
}
4674 { &hf_http2_settings_max_header_list_size
,
4675 { "Max header list size", "http2.settings.max_header_list_size",
4676 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4677 "This advisory setting informs a peer of the maximum size of header list that the sender is prepared to accept.", HFILL
}
4679 { &hf_http2_settings_extended_connect
,
4680 { "Extended CONNECT", "http2.settings.extended_connect",
4681 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4682 "Indicates support for the extended CONNECT method extension defined RFC 8441.", HFILL
}
4684 { &hf_http2_settings_no_rfc7540_priorities
,
4685 { "No RFC7540 Priorities", "http2.settings.no_rfc7540_priorities",
4686 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4689 { &hf_http2_settings_unknown
,
4690 { "Unknown Settings", "http2.settings.unknown",
4691 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
4696 { &hf_http2_push_promise_r
,
4697 { "Reserved", "http2.push_promise.r",
4698 FT_UINT32
, BASE_HEX
, NULL
, MASK_HTTP2_RESERVED
,
4699 "Must be zero", HFILL
}
4702 { &hf_http2_push_promise_promised_stream_id
,
4703 { "Promised-Stream-ID", "http2.push_promise.promised_stream_id",
4704 FT_UINT32
, BASE_DEC
, NULL
, MASK_HTTP2_PRIORITY
,
4705 "Identifies the stream the endpoint intends to start sending frames for", HFILL
}
4707 { &hf_http2_push_promise_header
,
4708 { "Header Block Fragment", "http2.push_promise.header",
4709 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4710 "Containing request header fields", HFILL
}
4712 { &hf_http2_push_promise_padding
,
4713 { "Padding", "http2.push_promise.padding",
4714 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4715 "Padding octets", HFILL
}
4720 { "Ping", "http2.ping",
4721 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4725 { "Pong", "http2.pong",
4726 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4731 { &hf_http2_goaway_r
,
4732 { "Reserved", "http2.goaway.r",
4733 FT_UINT32
, BASE_HEX
, NULL
, MASK_HTTP2_RESERVED
,
4734 "Must be zero", HFILL
}
4736 { &hf_http2_goaway_last_stream_id
,
4737 { "Last-Stream-ID", "http2.goaway.last_stream_id",
4738 FT_UINT32
, BASE_DEC
, NULL
, MASK_HTTP2_PRIORITY
,
4739 "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
}
4741 { &hf_http2_goaway_error
,
4742 { "Error", "http2.goaway.error",
4743 FT_UINT32
, BASE_DEC
, VALS(http2_error_codes_vals
), 0x0,
4744 "The error code indicates the reason for closing the connection", HFILL
}
4746 { &hf_http2_goaway_addata
,
4747 { "Additional Debug Data", "http2.goaway.addata",
4748 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4753 { &hf_http2_window_update_r
,
4754 { "Reserved", "http2.window_update.r",
4755 FT_UINT32
, BASE_HEX
, NULL
, MASK_HTTP2_RESERVED
,
4756 "Must be zero", HFILL
}
4758 { &hf_http2_window_update_window_size_increment
,
4759 { "Window Size Increment", "http2.window_update.window_size_increment",
4760 FT_UINT32
, BASE_DEC
, NULL
, MASK_HTTP2_PRIORITY
,
4761 "Indicating the number of bytes that the sender can transmit in addition to the existing flow control window", HFILL
}
4765 { &hf_http2_continuation_header
,
4766 { "Header Block Fragment", "http2.continuation.header",
4767 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4768 "Continues a HEADERS or PUSH_PROMISE field block", HFILL
}
4770 { &hf_http2_continuation_padding
,
4771 { "Padding", "http2.continuation.padding",
4772 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
4773 "Padding octets", HFILL
}
4777 { &hf_http2_altsvc_origin_len
,
4778 { "Origin Length", "http2.altsvc.origin.len",
4779 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4780 "indicating the length, in octets, of the Origin field.", HFILL
}
4782 { &hf_http2_altsvc_origin
,
4783 { "Origin", "http2.altsvc.origin",
4784 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4785 "A sequence of characters containing ASCII serialisation of an "
4786 "origin that the alternate service is applicable to.", HFILL
}
4788 { &hf_http2_altsvc_field_value
,
4789 { "Field/Value", "http2.altsvc.field_value",
4790 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4791 "A sequence of octets containing a value identical to the Alt-Svc field value", HFILL
}
4796 { "Origin", "http2.origin",
4797 FT_NONE
, BASE_NONE
, NULL
, 0x0,
4800 { &hf_http2_origin_origin_len
,
4801 { "Origin Length", "http2.origin.origin_len",
4802 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
4803 "indicating the length, in octets, of the Origin field.", HFILL
}
4805 { &hf_http2_origin_origin
,
4806 { "Origin", "http2.origin.origin",
4807 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4808 "A sequence of characters containing ASCII serialisation of an "
4809 "origin that server is authoritative for.", HFILL
}
4812 /* Priority Update */
4813 { &hf_http2_priority_update_stream_id
,
4814 { "Priority Update Stream ID", "http2.priority_update_stream_id",
4815 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
4818 { &hf_http2_priority_update_field_value
,
4819 { "Priority Update Field Value", "http2.priority_update_field_value",
4820 FT_STRING
, BASE_NONE
, NULL
, 0x0,
4824 { "Time since request", "http2.time",
4825 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0,
4826 "Time since the request was sent", HFILL
}
4828 { &hf_http2_request_in
,
4829 { "Request in frame", "http2.request_in",
4830 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
4831 "This frame is a response to a HTTP2 request contained in frame with this number", HFILL
}
4833 { &hf_http2_response_in
,
4834 { "Response in frame", "http2.response_in",
4835 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
4836 "This request will be responded in the frame with this number", HFILL
}
4840 { &hf_http2_calculated_window_size_connection_before
,
4841 { "Connection window size (before)", "http2.calculated.connection.window_size.before",
4842 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4843 "The sender's current window size (in bytes) for this connection (before sending)", HFILL
}
4845 { &hf_http2_calculated_window_size_connection_after
,
4846 { "Connection window size (after)", "http2.calculated.connection.window_size.after",
4847 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4848 "The sender's current window size (in bytes) for this connection (after sending)", HFILL
}
4850 { &hf_http2_calculated_window_size_stream_before
,
4851 { "Stream window size (before)", "http2.calculated.stream.window_size.before",
4852 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4853 "The sender's current window size (in bytes) for this stream (before sending)", HFILL
}
4855 { &hf_http2_calculated_window_size_stream_after
,
4856 { "Stream window size (after)", "http2.calculated.stream.window_size.after",
4857 FT_INT32
, BASE_DEC
, NULL
, 0x0,
4858 "The sender's current window size (in bytes) for this stream (after sending)", HFILL
}
4862 static int *ett
[] = {
4867 &ett_http2_settings
,
4868 &ett_http2_encoded_entity
,
4869 &ett_http2_body_fragment
,
4870 &ett_http2_body_fragments
,
4874 /* Setup protocol expert items */
4876 * Excessive header size or lines could mean a decompression bomb. Should
4877 * these be PI_SECURITY instead?
4879 static ei_register_info ei
[] = {
4880 { &ei_http2_header_size
,
4881 { "http2.header_size_exceeded", PI_UNDECODED
, PI_ERROR
,
4882 "Decompression stopped.", EXPFILL
}
4884 { &ei_http2_header_lines
,
4885 { "http2.header_lines_exceeded", PI_UNDECODED
, PI_ERROR
,
4886 "Decompression stopped after " G_STRINGIFY(MAX_HTTP2_HEADER_LINES
) " header lines.", EXPFILL
}
4888 { &ei_http2_body_decompression_failed
,
4889 { "http2.body_decompression_failed", PI_UNDECODED
, PI_WARN
,
4890 "Body decompression failed", EXPFILL
}
4892 { &ei_http2_reassembly_error
,
4893 { "http2.reassembly_error", PI_UNDECODED
, PI_WARN
,
4894 "Reassembly failed", EXPFILL
}
4898 module_t
*http2_module
;
4899 expert_module_t
*expert_http2
;
4901 proto_http2
= proto_register_protocol("HyperText Transfer Protocol 2", "HTTP2", "http2");
4903 proto_register_field_array(proto_http2
, hf
, array_length(hf
));
4904 proto_register_subtree_array(ett
, array_length(ett
));
4906 http2_module
= prefs_register_protocol(proto_http2
, NULL
);
4908 expert_http2
= expert_register_protocol(proto_http2
);
4909 expert_register_field_array(expert_http2
, ei
, array_length(ei
));
4911 prefs_register_obsolete_preference(http2_module
, "heuristic_http2");
4916 static const value_string http2_custom_type_vals
[] = {
4917 { val_string
, "string" },
4918 { val_uint64
, "unsigned 64-bit integer" },
4922 static uat_field_t custom_header_uat_fields
[] = {
4923 UAT_FLD_CSTRING(header_fields
, header_name
, "Header name", "HTTP2 header name"),
4924 UAT_FLD_VS(header_fields
, header_type
, "Header type", http2_custom_type_vals
, "Field type"),
4925 UAT_FLD_CSTRING(header_fields
, header_desc
, "Field desc", "Description of the value contained in the header"),
4929 headers_uat
= uat_new("Custom HTTP2 Header Fields",
4930 sizeof(header_field_t
),
4931 "custom_http2_header_fields",
4935 /* specifies named fields, so affects dissection
4936 and the set of named fields */
4937 UAT_AFFECTS_DISSECTION
|UAT_AFFECTS_FIELDS
,
4939 header_fields_copy_cb
,
4940 header_fields_update_cb
,
4941 header_fields_free_cb
,
4942 header_fields_post_update_cb
,
4943 header_fields_reset_cb
,
4944 custom_header_uat_fields
4947 prefs_register_uat_preference(http2_module
, "custom_http2_header_fields", "Custom HTTP2 header fields",
4948 "A table to define custom HTTP2 header for which fields can be setup and used for filtering/data extraction etc.",
4951 uat_t
* fake_headers_uat
;
4953 static uat_field_t http2_fake_header_uat_fields
[] = {
4954 UAT_FLD_RANGE(http2_fake_headers
, server_port_range
, "Server ports", 0xFFFF,
4955 "Server ports providing HTTP2 service"),
4956 UAT_FLD_DEC(http2_fake_headers
, stream_id
, "Stream ID",
4957 "The HTTP2 Stream ID this rule will apply to. The 0 means applicable to all streams."),
4958 UAT_FLD_VS(http2_fake_headers
, direction
, "Direction", http2_direction_type_vals
,
4959 "This rule applies to the message sent to (IN) or from (OUT) server."),
4960 UAT_FLD_CSTRING(http2_fake_headers
, header_name
, "Header name", "HTTP2 header name"),
4961 UAT_FLD_CSTRING(http2_fake_headers
, header_value
, "Header value", "HTTP2 header value"),
4962 UAT_FLD_BOOL(http2_fake_headers
, override
, "Override", "Override existing header"),
4963 UAT_FLD_BOOL(http2_fake_headers
, enable
, "Enable", "Enable this rule"),
4967 fake_headers_uat
= uat_new("HTTP2 Fake Headers",
4968 sizeof(http2_fake_header_t
),
4969 "http2_fake_headers",
4971 &http2_fake_headers
,
4972 &num_http2_fake_headers
,
4973 UAT_AFFECTS_DISSECTION
| UAT_AFFECTS_FIELDS
,
4975 http2_fake_headers_copy_cb
,
4976 http2_fake_headers_update_cb
,
4977 http2_fake_headers_free_cb
,
4980 http2_fake_header_uat_fields
4983 prefs_register_uat_preference(http2_module
, "fake_headers", "HTTP2 Fake Headers",
4984 "A table to define HTTP2 fake headers for parsing a HTTP2 stream conversation that first HEADERS frame is missing.",
4987 /* Fill hash table with static headers */
4988 register_static_headers();
4990 /* Decode As handling */
4991 static build_valid_func http2_current_stream_values
[1] = { http2_current_stream_id_value
};
4992 static decode_as_value_t http2_da_stream_id_values
[1] = { {http2_streamid_prompt
, 1, http2_current_stream_values
} };
4993 static decode_as_t http2_da_stream_id
= { "http2", "http2.streamid", 1, 0, http2_da_stream_id_values
, "HTTP2", "Stream ID as",
4994 decode_as_http2_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
4995 register_decode_as(&http2_da_stream_id
);
4998 register_init_routine(&http2_init_protocol
);
4999 register_cleanup_routine(&http2_cleanup_protocol
);
5001 http2_handle
= register_dissector("http2", dissect_http2
, proto_http2
);
5003 reassembly_table_register(&http2_body_reassembly_table
,
5004 &addresses_ports_reassembly_table_functions
);
5005 reassembly_table_register(&http2_streaming_reassembly_table
,
5006 &addresses_ports_reassembly_table_functions
);
5008 streaming_content_type_dissector_table
=
5009 register_dissector_table("streaming_content_type",
5010 "Data Transmitted over HTTP2 in Streaming Mode", proto_http2
, FT_STRING
, STRING_CASE_SENSITIVE
);
5012 stream_id_content_type_dissector_table
=
5013 register_dissector_table("http2.streamid", "HTTP2 content type in stream", proto_http2
, FT_UINT32
, BASE_DEC
);
5015 http2_tap
= register_tap("http2");
5016 http2_follow_tap
= register_tap("http2_follow");
5018 register_follow_stream(proto_http2
, "http2_follow", http2_follow_conv_filter
, http2_follow_index_filter
, tcp_follow_address_filter
,
5019 tcp_port_to_display
, follow_http2_tap_listener
, get_tcp_stream_count
,
5020 http2_get_sub_stream_id
);
5023 static void http2_stats_tree_init(stats_tree
* st
)
5025 st_node_http2
= stats_tree_create_node(st
, st_str_http2
, 0, STAT_DT_INT
, true);
5026 st_node_http2_type
= stats_tree_create_pivot(st
, st_str_http2_type
, st_node_http2
);
5030 static tap_packet_status
http2_stats_tree_packet(stats_tree
* st
, packet_info
* pinfo _U_
, epan_dissect_t
* edt _U_
, const void* p
, tap_flags_t flags _U_
)
5032 const struct HTTP2Tap
*pi
= (const struct HTTP2Tap
*)p
;
5033 tick_stat_node(st
, st_str_http2
, 0, false);
5034 stats_tree_tick_pivot(st
, st_node_http2_type
,
5035 val_to_str(pi
->type
, http2_type_vals
, "Unknown type (%d)"));
5037 return TAP_PACKET_REDRAW
;
5041 proto_reg_handoff_http2(void)
5044 media_type_dissector_table
= find_dissector_table("media_type");
5047 data_handle
= find_dissector("data");
5049 dissector_add_uint_range_with_preference("tcp.port", "", http2_handle
);
5050 dissector_add_for_decode_as("tcp.port", http2_handle
);
5053 * SSL/TLS Application-Layer Protocol Negotiation (ALPN) protocol ID.
5055 dissector_add_string("tls.alpn", "h2", http2_handle
);
5056 dissector_add_string("http.upgrade", "h2", http2_handle
);
5057 dissector_add_string("http.upgrade", "h2c", http2_handle
);
5059 heur_dissector_add("tls", dissect_http2_heur_ssl
, "HTTP2 over TLS", "http2_tls", proto_http2
, HEURISTIC_ENABLE
);
5060 heur_dissector_add("tcp", dissect_http2_heur
, "HTTP2 over TCP", "http2_tcp", proto_http2
, HEURISTIC_ENABLE
);
5061 heur_dissector_add("http", dissect_http2_heur_http
, "HTTP2 on an HTTP port", "http2_http", proto_http2
, HEURISTIC_ENABLE
);
5063 stats_tree_register("http2", "http2", "HTTP2", 0, http2_stats_tree_packet
, http2_stats_tree_init
, NULL
);
5066 register_eo_t
*http_eo
= get_eo_by_name("http");
5068 http_eo_tap
= find_tap_id(get_eo_tap_listener_name(http_eo
));
5074 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5079 * indent-tabs-mode: nil
5082 * vi: set shiftwidth=4 tabstop=8 expandtab:
5083 * :indentSize=4:tabSize=8:noTabs=true: