static void dissect_icep_request_common(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *icep_sub_tree, proto_item* icep_sub_item, gint32 *total_consumed) { /* p. 613, chapter 23.3.3 and p. 612 chapter 23.3.2: * Request and BatchRequest differ only in the first 4 bytes (requestID) * so them share this part * * Ice::Identity id; * Ice::StringSeq facet; * string operation; * byte mode; * Ice::Context context; * Encapsulation params; * } */ gint32 consumed = 0; char *namestr = NULL; char *opstr = NULL; (*total_consumed) = 0; /* check common header (i.e. the batch request one)*/ if ( !tvb_bytes_exist(tvb, offset, ICEP_MIN_COMMON_REQ_HEADER_SIZE) ) { if (icep_sub_item) expert_add_info_format(pinfo, icep_sub_item, PI_MALFORMED, PI_ERROR, "too short header"); col_append_str(mypinfo->cinfo, COL_INFO, " (too short header)"); goto error; } /* got at least 15 bytes */ /* "id" is a: * struct Identity { * string name; * string category; * } */ dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_id_name, tvb, offset, &consumed, &namestr); if ( consumed == -1 ) goto error; offset += consumed; DBG1("consumed --> %d\n", consumed); (*total_consumed) += consumed; dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_id_category, tvb, offset, &consumed, NULL); if ( consumed == -1 ) goto error; offset += consumed; DBG1("consumed --> %d\n", consumed); (*total_consumed) += consumed; /* "facet" is a: * sequence<string> StringSeq * */ dissect_ice_facet(pinfo, icep_sub_tree, icep_sub_item, hf_icep_facet, tvb, offset, &consumed); if ( consumed == -1 ) goto error; offset += consumed; DBG1("consumed --> %d\n", consumed); (*total_consumed) += consumed; /* "operation" is an ice_string * */ dissect_ice_string(pinfo, icep_sub_tree, icep_sub_item, hf_icep_operation, tvb, offset, &consumed, &opstr); if ( consumed == -1 ) goto error; else { offset += consumed; DBG1("consumed --> %d\n", consumed); (*total_consumed) += consumed; if ( opstr && namestr ) { DBG2("operation --> %s.%s()\n", namestr, opstr); if ( check_col(mypinfo->cinfo, COL_INFO) ) { col_append_fstr(mypinfo->cinfo, COL_INFO, " %s.%s()", namestr, opstr); } opstr = NULL; namestr = NULL; } } /* check and get mode byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (icep_sub_item) expert_add_info_format(pinfo, icep_sub_item, PI_MALFORMED, PI_ERROR, "mode field missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (mode field missing)"); goto error; } if (icep_sub_tree) proto_tree_add_item(icep_sub_tree, hf_icep_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; DBG0("consumed --> 1\n"); (*total_consumed)++; /* "context" is a dictionary<string, string> * */ dissect_ice_context(pinfo, icep_sub_tree, icep_sub_item, tvb, offset, &consumed); if ( consumed == -1 ) goto error; offset += consumed; DBG1("consumed --> %d\n", consumed); (*total_consumed) += consumed; /* "params" is a Encapsulation * */ dissect_ice_params(pinfo, icep_sub_tree, icep_sub_item, tvb, offset, &consumed); if ( consumed == -1 ) goto error; /*offset += consumed;*/ DBG1("consumed --> %d\n", consumed); (*total_consumed) += consumed; return; error: (*total_consumed) = -1; }
/* * This function dissects an "Ice context", adds hf(s) to "tree" and returns consumed * bytes in "*consumed", if errors "*consumed" is -1. */ static void dissect_ice_context(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, guint32 offset, gint32 *consumed) { /* p. 588, chapter 23.2.7 and p. 613, 23.3.2: * "context" is a dictionary<string, string> * * dictionary<string, string> == Size + SizeKeyValuePairs * dictionary<string, string> = 1byte (0..254) + SizeKeyValuePairs * or * dictionary<string, string>= 1byte (255) + 1int (255..2^32-1)+SizeKeyValuePairs * */ guint32 Size = 0; /* number of key-value in the dictionary */ guint32 i = 0; const char *s = NULL; (*consumed) = 0; /* check first byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "context missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (context missing)"); (*consumed) = -1; return; } /* get first byte of Size */ Size = tvb_get_guint8(tvb, offset); offset++; (*consumed)++; if ( Size == 255 ) { /* check for next 4 bytes */ if ( !tvb_bytes_exist(tvb, offset, 4) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "second field of Size missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (second field of Size missing)"); (*consumed) = -1; return; } /* get second field of Size */ Size = tvb_get_letohl(tvb, offset); offset += 4; (*consumed) += 4; } DBG1("context.Size --> %d\n", Size); if ( Size > icep_max_ice_context_pairs ) { if (item) /* display the XX Size byte when click here */ expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "too long context"); col_append_str(mypinfo->cinfo, COL_INFO, " (too long context)"); (*consumed) = -1; return; } if (Size == 0) { s = "(empty)"; /* display the 0x00 Size byte when click on a empty context */ if (tree) proto_tree_add_string(tree, hf_icep_context, tvb, offset - 1, 1, s); return; } /* looping through the dictionary */ for ( i = 0; i < Size; i++ ) { /* key */ gint32 consumed_key = 0; char *str_key = NULL; /* value */ gint32 consumed_value = 0; char *str_value = NULL; proto_item *ti = NULL; DBG1("looping through context dictionary, loop #%d\n", i); ti = proto_tree_add_text(tree, tvb, offset, -1, "Invocation Context"); dissect_ice_string(pinfo, tree, ti, hf_icep_invocation_key, tvb, offset, &consumed_key, &str_key); if ( consumed_key == -1 ) { (*consumed) = -1; return; } offset += consumed_key; (*consumed) += consumed_key; dissect_ice_string(pinfo, tree, ti, hf_icep_invocation_value, tvb, offset, &consumed_value, &str_value); if ( consumed_value == -1 ) { (*consumed) = -1; return; } offset += consumed_value; (*consumed) += consumed_value; if (ti) proto_item_set_len(ti, (consumed_key + consumed_value) + 1); } }
/* * This function dissects an "Ice context", adds hf(s) to "tree" and returns consumed * bytes in "*consumed", if errors "*consumed" is -1. */ static void dissect_ice_context(proto_tree *tree, tvbuff_t *tvb, guint32 offset, gint32 *consumed) { /* p. 588, chapter 23.2.7 and p. 613, 23.3.2: * "context" is a dictionary<string, string> * * dictionary<string, string> == Size + SizeKeyValuePairs * dictionary<string, string> = 1byte (0..254) + SizeKeyValuePairs * or * dictionary<string, string>= 1byte (255) + 1int (255..2^32-1)+SizeKeyValuePairs * */ guint32 Size = 0; /* number of key-value in the dictionary */ guint32 i = 0; const char *s = NULL; (*consumed) = 0; /* check first byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (tree) proto_tree_add_text(tree, tvb, offset, -1, "context missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (context missing)"); (*consumed) = -1; return; } /* get first byte of Size */ Size = tvb_get_guint8(tvb, offset); offset++; (*consumed)++; if ( Size == 255 ) { /* check for next 4 bytes */ if ( !tvb_bytes_exist(tvb, offset, 4) ) { if (tree) proto_tree_add_text(tree, tvb, offset, -1, "second field of Size missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (second field of Size missing)"); (*consumed) = -1; return; } /* get second field of Size */ Size = tvb_get_letohl(tvb, offset); offset += 4; (*consumed) += 4; } DBG1("context.Size --> %d\n", Size); if ( Size > ICEP_MAX_ICE_CONTEXT_PAIRS ) { if (tree) /* display the XX Size byte when click here */ proto_tree_add_text(tree, tvb, offset - 1, 1, "too long context"); col_append_str(mypinfo->cinfo, COL_INFO, " (too long context)"); (*consumed) = -1; return; } if (Size == 0) { s = "(empty)"; /* display the 0x00 Size byte when click on a empty context */ if (tree) proto_tree_add_string(tree, hf_icep_context, tvb, offset - 1, 1, s); return; } /* looping through the dictionary */ for ( i = 0; i < Size; i++ ) { /* key */ gint32 consumed_key = 0; char *str_key = NULL; /* value */ gint32 consumed_value = 0; char *str_value = NULL; DBG1("looping through context dictionary, loop #%d\n", i); dissect_ice_string(tree, -1, tvb, offset, &consumed_key, &str_key, FALSE); if ( consumed_key == -1 ) { (*consumed) = -1; return; } offset += consumed_key; (*consumed) += consumed_key; dissect_ice_string(tree, -1, tvb, offset, &consumed_value, &str_value, FALSE); if ( consumed_value == -1 ) { (*consumed) = -1; return; } offset += consumed_value; (*consumed) += consumed_value; if (tree && str_value && str_key) { proto_tree_add_text(tree, tvb, offset - (consumed_key + consumed_value) - 1, (consumed_key + consumed_value) + 1, "Invocation Context: %s/%s", str_key, str_value); } } }
/* * This function dissects an "Ice facet", adds hf(s) to "tree" and returns consumed * bytes in "*consumed", if errors "*consumed" is -1. */ static void dissect_ice_facet(packet_info *pinfo, proto_tree *tree, proto_item *item, int hf_icep, tvbuff_t *tvb, guint32 offset, gint32 *consumed) { /* p. 588, chapter 23.2.6: * "facet" is a StringSeq, a StringSeq is a: * sequence<string> * * * sequence == Size + SizeElements * sequence = 1byte (0..254) + SizeElements * or * sequence = 1byte (255) + 1int (255..2^32-1) + SizeElements * * * p.613. chapter 23.3.2 * "facet has either zero elements (empty) or one element" * * */ guint32 Size = 0; /* number of elements in the sequence */ (*consumed) = 0; /* check first byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (item) expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "facet field missing"); col_append_str(mypinfo->cinfo, COL_INFO, " (facet field missing)"); (*consumed) = -1; return; } /* get first byte of Size */ Size = tvb_get_guint8(tvb, offset); offset++; (*consumed)++; if ( Size == 0 ) { if (tree) { /* display the 0x00 Size byte when click on a empty ice_string */ proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, "(empty)"); } return; } if ( Size == 1 ) { gint32 consumed_facet = 0; dissect_ice_string(pinfo, tree, item, hf_icep, tvb, offset, &consumed_facet, NULL); if ( consumed_facet == -1 ) { (*consumed) = -1; return; } /*offset += consumed_facet;*/ (*consumed) += consumed_facet; return; } /* if here => Size > 1 => not possible */ if (item) /* display the XX Size byte when click here */ expert_add_info_format(pinfo, item, PI_PROTOCOL, PI_WARN, "facet can be max one element"); col_append_str(mypinfo->cinfo, COL_INFO, " (facet can be max one element)"); (*consumed) = -1; return; }
/* * This function dissects an "Ice facet", adds hf(s) to "tree" and returns consumed * bytes in "*consumed", if errors "*consumed" is -1. */ static void dissect_ice_facet(proto_tree *tree, int hf_icep, tvbuff_t *tvb, guint32 offset, gint32 *consumed) { /* p. 588, chapter 23.2.6: * "facet" is a StringSeq, a StringSeq is a: * sequence<string> * * * sequence == Size + SizeElements * sequence = 1byte (0..254) + SizeElements * or * sequence = 1byte (255) + 1int (255..2^32-1) + SizeElements * * * p.613. chapter 23.3.2 * "facet has either zero elements (empty) or one element" * * */ guint32 Size = 0; /* number of elements in the sequence */ char *s = NULL; (*consumed) = 0; /* check first byte */ if ( !tvb_bytes_exist(tvb, offset, 1) ) { if (tree) proto_tree_add_text(tree, tvb, offset, -1, "facet field missing"); if ( check_col(mypinfo->cinfo, COL_INFO) ) { col_append_str(mypinfo->cinfo, COL_INFO, " (facet field missing)"); } (*consumed) = -1; return; } /* get first byte of Size */ Size = tvb_get_guint8(tvb, offset); offset++; (*consumed)++; if ( Size == 0 ) { if (tree) { s = ep_strdup( "(empty)" ); /* display the 0x00 Size byte when click on a empty ice_string */ proto_tree_add_string(tree, hf_icep, tvb, offset - 1, 1, s); } return; } if ( Size == 1 ) { gint32 consumed_facet = 0; dissect_ice_string(tree, hf_icep, tvb, offset, &consumed_facet, NULL, TRUE); if ( consumed_facet == -1 ) { (*consumed) = -1; return; } offset += consumed_facet; (*consumed) += consumed_facet; return; } /* if here => Size > 1 => not possible */ if (tree) /* display the XX Size byte when click here */ proto_tree_add_text(tree, tvb, offset - 1, 1, "facet can be max one element"); if ( check_col(mypinfo->cinfo, COL_INFO) ) { col_append_str(mypinfo->cinfo, COL_INFO, " (facet can be max one element)"); } (*consumed) = -1; return; }