From 982fc7184d46621948e53b485c7504c9d11f3350 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 17 May 2024 17:00:59 +0200 Subject: Merging upstream version 4.2.5. Signed-off-by: Daniel Baumann --- epan/dissectors/packet-grpc.c | 137 +++++++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 48 deletions(-) (limited to 'epan/dissectors/packet-grpc.c') diff --git a/epan/dissectors/packet-grpc.c b/epan/dissectors/packet-grpc.c index a459fde2..b71a272b 100644 --- a/epan/dissectors/packet-grpc.c +++ b/epan/dissectors/packet-grpc.c @@ -136,11 +136,14 @@ static int ett_grpc_message = -1; static int ett_grpc_encoded_entity = -1; static dissector_handle_t grpc_handle; +static dissector_handle_t grpc_web_handle; +static dissector_handle_t grpc_web_text_handle; static dissector_handle_t data_text_lines_handle; /* the information used during dissecting a grpc message */ typedef struct { gboolean is_request; /* is request or response message */ + grpc_protocol_type_t proto_type; const gchar* path; /* is http2 ":path" or http request_uri, format: "/" Service-Name "/" {method name} */ const gchar* content_type; /* is http2 or http content-type, like: application/grpc */ const gchar* encoding; /* is grpc-encoding header containing compressed method, for example "gzip" */ @@ -158,18 +161,6 @@ typedef struct { */ static dissector_table_t grpc_message_type_subdissector_table; -static grpc_protocol_type_t -get_grpc_protocol_type(const gchar* content_type) { - if (content_type != NULL) { - if (g_str_has_prefix(content_type, "application/grpc-web-text")) { - return GRPC_PTYPE_GRPC_WEB_TEXT; - } else if (g_str_has_prefix(content_type, "application/grpc-web")) { - return GRPC_PTYPE_GRPC_WEB; - } - } - return GRPC_PTYPE_GRPC; -} - /* Try to dissect grpc message according to grpc message info or http2 content_type. */ static void dissect_body_data(proto_tree *grpc_tree, packet_info *pinfo, tvbuff_t *tvb, const gint offset, @@ -335,13 +326,11 @@ dissect_grpc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, grpc_co guint32 message_length; guint offset = 0; guint tvb_len = tvb_reported_length(tvb); - grpc_protocol_type_t proto_type; const gchar* proto_name; - DISSECTOR_ASSERT_HINT(grpc_ctx && grpc_ctx->content_type && grpc_ctx->path, "The content_type and path of grpc context must be set."); + DISSECTOR_ASSERT(grpc_ctx != NULL); - proto_type = get_grpc_protocol_type(grpc_ctx->content_type); - proto_name = val_to_str_const(proto_type, grpc_protocol_type_vals, "GRPC"); + proto_name = val_to_str_const(grpc_ctx->proto_type, grpc_protocol_type_vals, "GRPC"); if (!grpc_embedded_under_http2 && proto_tree_get_parent_tree(tree)) { tree = proto_tree_get_parent_tree(tree); @@ -395,41 +384,31 @@ dissect_grpc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, grpc_co return tvb_captured_length(tvb); } -static int -dissect_grpc(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) +static grpc_context_info_t* +get_grpc_context(packet_info *pinfo, const media_content_info_t *content_info) { - int ret; http_req_res_t* curr_req_res; - tvbuff_t* real_data_tvb; - grpc_context_info_t grpc_ctx = { 0 }; - media_content_info_t* content_info = (media_content_info_t*)data; - gboolean is_grpc_web_text = g_str_has_prefix(pinfo->match_string, "application/grpc-web-text"); - - if (is_grpc_web_text) { - real_data_tvb = base64_tvb_to_new_tvb(tvb, 0, tvb_reported_length(tvb)); - add_new_data_source(pinfo, real_data_tvb, "Decoded base64 body"); - } else { - real_data_tvb = tvb; - } + grpc_context_info_t* grpc_ctx = wmem_new0(pinfo->pool, grpc_context_info_t); if (proto_is_frame_protocol(pinfo->layers, "http2")) { - grpc_ctx.path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, FALSE); - grpc_ctx.is_request = (grpc_ctx.path != NULL); - if (grpc_ctx.path == NULL) { + grpc_ctx->path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, FALSE); + grpc_ctx->is_request = (grpc_ctx->path != NULL); + if (grpc_ctx->path == NULL) { /* this must be response, so we get it from http2 request stream */ - grpc_ctx.path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, TRUE); + /* XXX - Not necessarily true if the data has errors. */ + grpc_ctx->path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, TRUE); } - grpc_ctx.content_type = http2_get_header_value(pinfo, HTTP2_HEADER_CONTENT_TYPE, FALSE); - grpc_ctx.encoding = http2_get_header_value(pinfo, HTTP2_HEADER_GRPC_ENCODING, FALSE); + grpc_ctx->content_type = http2_get_header_value(pinfo, HTTP2_HEADER_CONTENT_TYPE, FALSE); + grpc_ctx->encoding = http2_get_header_value(pinfo, HTTP2_HEADER_GRPC_ENCODING, FALSE); } else if (proto_is_frame_protocol(pinfo->layers, "http")) { curr_req_res = (http_req_res_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_http, 0); DISSECTOR_ASSERT_HINT(curr_req_res && content_info, "Unexpected error: HTTP request/reply or HTTP message info not available."); - grpc_ctx.is_request = (content_info->type == MEDIA_CONTAINER_HTTP_REQUEST); - grpc_ctx.path = curr_req_res->request_uri; - grpc_ctx.content_type = pinfo->match_string; /* only for grpc-web(-text) over http1.1 */ + grpc_ctx->is_request = (content_info->type == MEDIA_CONTAINER_HTTP_REQUEST); + grpc_ctx->path = curr_req_res->request_uri; + grpc_ctx->content_type = pinfo->match_string; /* only for grpc-web(-text) over http1.1 */ if (content_info->data) { - grpc_ctx.encoding = (const gchar*)wmem_map_lookup((wmem_map_t *)content_info->data, HTTP2_HEADER_GRPC_ENCODING); + grpc_ctx->encoding = (const gchar*)wmem_map_lookup((wmem_map_t *)content_info->data, HTTP2_HEADER_GRPC_ENCODING); } } else { @@ -437,13 +416,52 @@ dissect_grpc(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) DISSECTOR_ASSERT_NOT_REACHED(); } - ret = dissect_grpc_common(real_data_tvb, pinfo, tree, &grpc_ctx); + return grpc_ctx; +} - if (is_grpc_web_text) { - /* convert reassembly the lengths of offset and remaining bytes back to the base64 lengths */ - pinfo->desegment_offset = BASE64_ENCODE_SIZE(pinfo->desegment_offset); - pinfo->desegment_len = BASE64_ENCODE_SIZE(pinfo->desegment_len); - } +static int +dissect_grpc(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) +{ + grpc_context_info_t* grpc_ctx; + media_content_info_t* content_info = (media_content_info_t*)data; + + grpc_ctx = get_grpc_context(pinfo, content_info); + grpc_ctx->proto_type = GRPC_PTYPE_GRPC; + + return dissect_grpc_common(tvb, pinfo, tree, grpc_ctx); +} + +static int +dissect_grpc_web(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) +{ + grpc_context_info_t* grpc_ctx; + media_content_info_t* content_info = (media_content_info_t*)data; + + grpc_ctx = get_grpc_context(pinfo, content_info); + grpc_ctx->proto_type = GRPC_PTYPE_GRPC_WEB; + + return dissect_grpc_common(tvb, pinfo, tree, grpc_ctx); +} + +static int +dissect_grpc_web_text(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) +{ + int ret; + tvbuff_t* real_data_tvb; + grpc_context_info_t* grpc_ctx; + media_content_info_t* content_info = (media_content_info_t*)data; + + real_data_tvb = base64_tvb_to_new_tvb(tvb, 0, tvb_reported_length(tvb)); + add_new_data_source(pinfo, real_data_tvb, "Decoded base64 body"); + + grpc_ctx = get_grpc_context(pinfo, content_info); + grpc_ctx->proto_type = GRPC_PTYPE_GRPC_WEB_TEXT; + + ret = dissect_grpc_common(real_data_tvb, pinfo, tree, grpc_ctx); + + /* convert reassembly the lengths of offset and remaining bytes back to the base64 lengths */ + pinfo->desegment_offset = BASE64_ENCODE_SIZE(pinfo->desegment_offset); + pinfo->desegment_len = BASE64_ENCODE_SIZE(pinfo->desegment_len); return ret; } @@ -525,7 +543,9 @@ proto_register_grpc(void) expert_grpc = expert_register_protocol(proto_grpc); expert_register_field_array(expert_grpc, ei, array_length(ei)); - grpc_handle = register_dissector("grpc", dissect_grpc, proto_grpc); + grpc_handle = register_dissector_with_description("grpc", "gRPC", dissect_grpc, proto_grpc); + grpc_web_handle = register_dissector_with_description("grpc_web", "gRPC Web", dissect_grpc_web, proto_grpc); + grpc_web_text_handle = register_dissector_with_description("grpc_web_text", "gRPC Web Text", dissect_grpc_web_text, proto_grpc); /* * Dissectors can register themselves in this table as grpc message @@ -539,17 +559,26 @@ proto_register_grpc(void) void proto_reg_handoff_grpc(void) { + int i; + char *content_types[] = { "application/grpc", "application/grpc+proto", "application/grpc+json", + NULL /* end flag */ + }; + + char *content_types_web[] = { "application/grpc-web", "application/grpc-web+proto", + NULL /* end flag */ + }; + + char *content_types_web_text[] = { "application/grpc-web-text", "application/grpc-web-text+proto", NULL /* end flag */ }; - int i; /* register native grpc handler */ for (i = 0; content_types[i]; i++) { @@ -557,6 +586,18 @@ proto_reg_handoff_grpc(void) dissector_add_string("media_type", content_types[i], grpc_handle); } + /* register gRPC Web handler */ + for (i = 0; content_types_web[i]; i++) { + dissector_add_string("streaming_content_type", content_types_web[i], grpc_web_handle); + dissector_add_string("media_type", content_types_web[i], grpc_web_handle); + } + + /* register gRPC Web Text handler */ + for (i = 0; content_types_web_text[i]; i++) { + dissector_add_string("streaming_content_type", content_types_web_text[i], grpc_web_text_handle); + dissector_add_string("media_type", content_types_web_text[i], grpc_web_text_handle); + } + proto_http = proto_get_id_by_filter_name("http"); data_text_lines_handle = find_dissector_add_dependency("data-text-lines", proto_grpc); } -- cgit v1.2.3