/* Parses a ts2 channel list (TS2T_CHANNELLIST) and adds it to the tree */ static void ts2_parse_channellist(tvbuff_t *tvb, proto_tree *ts2_tree) { gint32 offset; guint32 string_len; offset=0; proto_tree_add_item(ts2_tree, hf_ts2_number_of_channels, tvb, offset, 4, TRUE); offset+=4; while(offset<tvb_length_remaining(tvb, 0)) { proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, TRUE); offset+=4; proto_tree_add_item(ts2_tree, hf_ts2_channel_flags, tvb, offset, 1, TRUE); offset+=1; proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 1, TRUE); offset+=1; proto_tree_add_item(ts2_tree, hf_ts2_codec, tvb, offset, 2, TRUE); offset+=2; proto_tree_add_item(ts2_tree, hf_ts2_endmarker, tvb, offset, 4, TRUE); offset+=4; proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 4, TRUE); offset+=4; tvb_get_ephemeral_stringz(tvb, offset, &string_len); proto_tree_add_item(ts2_tree, hf_ts2_channel_name, tvb, offset,string_len , TRUE); offset+=string_len; tvb_get_ephemeral_stringz(tvb, offset, &string_len); proto_tree_add_item(ts2_tree, hf_ts2_channel_topic, tvb, offset,string_len ,TRUE); offset+=string_len; tvb_get_ephemeral_stringz(tvb, offset, &string_len); proto_tree_add_item(ts2_tree, hf_ts2_channel_description, tvb, offset,string_len , TRUE); offset+=string_len; } }
/* Process an APP2 block. * * XXX - This code only works on US-ASCII systems!!! */ static void process_app2_segment(proto_tree *tree, tvbuff_t *tvb, guint32 len, guint16 marker, const char *marker_name) { proto_item *ti = NULL; proto_tree *subtree = NULL; char *str; gint str_size; if (!tree) return; ti = proto_tree_add_item(tree, hf_marker_segment, tvb, 0, -1, ENC_NA); subtree = proto_item_add_subtree(ti, ett_marker_segment); proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker); proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN); str = tvb_get_ephemeral_stringz(tvb, 4, &str_size); ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, ENC_ASCII|ENC_NA); if (strcmp(str, "FPXR") == 0) { proto_tree_add_text(tree, tvb, 0, -1, "Exif FlashPix APP2 application marker"); } else { proto_tree_add_text(subtree, tvb, 4 + str_size, -1, "Remaining segment data (%u bytes)", len - 2 - str_size); proto_item_append_text(ti, " (Unknown identifier)"); } }
/* Parses a ts2 channel list (TS2T_CHANNELLIST) and adds it to the tree */ static void ts2_parse_channellist(tvbuff_t *tvb, proto_tree *ts2_tree) { gint32 offset; guint32 string_len; proto_tree *subtree; proto_item *item; offset=0; proto_tree_add_item(ts2_tree, hf_ts2_number_of_channels, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=4; while(offset<tvb_length_remaining(tvb, 0)) { proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=4; /* Channel flags */ item = proto_tree_add_item(ts2_tree, hf_ts2_channel_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); subtree = proto_item_add_subtree(item, ett_ts2_channel_flags); proto_tree_add_item(subtree, hf_ts2_channel_unregistered, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_ts2_channel_moderated, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_ts2_channel_password, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_ts2_channel_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_ts2_channel_default, tvb, offset, 1, ENC_BIG_ENDIAN); offset+=1; proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 1, ENC_NA); offset+=1; proto_tree_add_item(ts2_tree, hf_ts2_codec, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset+=2; proto_tree_add_item(ts2_tree, hf_ts2_parent_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=4; proto_tree_add_item(ts2_tree, hf_ts2_channel_order, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset+=2; proto_tree_add_item(ts2_tree, hf_ts2_max_users, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset+=2; tvb_get_ephemeral_stringz(tvb, offset, &string_len); proto_tree_add_item(ts2_tree, hf_ts2_channel_name, tvb, offset,string_len , ENC_ASCII|ENC_NA); offset+=string_len; tvb_get_ephemeral_stringz(tvb, offset, &string_len); proto_tree_add_item(ts2_tree, hf_ts2_channel_topic, tvb, offset,string_len ,ENC_ASCII|ENC_NA); offset+=string_len; tvb_get_ephemeral_stringz(tvb, offset, &string_len); proto_tree_add_item(ts2_tree, hf_ts2_channel_description, tvb, offset,string_len , ENC_ASCII|ENC_NA); offset+=string_len; } }
WSLUA_METHOD TvbRange_stringz(lua_State* L) { /* Obtain a zero terminated string from a TvbRange */ TvbRange tvbr = checkTvbRange(L,1); if ( !(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } lua_pushstring(L, (gchar*)tvb_get_ephemeral_stringz(tvbr->tvb->ws_tvb,tvbr->offset,NULL) ); WSLUA_RETURN(1); /* The zero terminated string */ }
int display_ms_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data) { char *str; gint len; /* display a string from the tree and return the new offset */ str = tvb_get_ephemeral_stringz(tvb, offset, &len); proto_tree_add_string(tree, hf_index, tvb, offset, len, str); /* Return a copy of the string if requested */ if (data) *data = str; return offset+len; }
static void dissect_wow_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti; proto_tree *wow_tree, *wow_realms_tree; gchar *string, *realm_name; guint8 cmd, srp_i_len, srp_g_len, srp_n_len; guint16 num_realms; guint32 offset = 0; gint len, i; col_set_str(pinfo->cinfo, COL_PROTOCOL, "WOW"); col_clear(pinfo->cinfo, COL_INFO); cmd = tvb_get_guint8(tvb, offset); if(check_col(pinfo->cinfo, COL_INFO)) { col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd, cmd_vs, "Unrecognized packet type")); } if(tree) { ti = proto_tree_add_item(tree, proto_wow, tvb, 0, -1, ENC_NA); wow_tree = proto_item_add_subtree(ti, ett_wow); proto_tree_add_item(wow_tree, hf_wow_command, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; switch(cmd) { case AUTH_LOGON_CHALLENGE : if(WOW_CLIENT_TO_SERVER) { proto_tree_add_item(wow_tree, hf_wow_error, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_tree, hf_wow_pkt_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; string = g_strreverse(tvb_get_ephemeral_string(tvb, offset, 4)); proto_tree_add_string(wow_tree, hf_wow_gamename, tvb, offset, 4, string); offset += 4; proto_tree_add_item(wow_tree, hf_wow_version1, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_tree, hf_wow_version2, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_tree, hf_wow_version3, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_tree, hf_wow_build, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; string = g_strreverse(tvb_get_ephemeral_string(tvb, offset, 4)); proto_tree_add_string(wow_tree, hf_wow_platform, tvb, offset, 4, string); offset += 4; string = g_strreverse(tvb_get_ephemeral_string(tvb, offset, 4)); proto_tree_add_string(wow_tree, hf_wow_os, tvb, offset, 4, string); offset += 4; string = g_strreverse(tvb_get_ephemeral_string(tvb, offset, 4)); proto_tree_add_string(wow_tree, hf_wow_country, tvb, offset, 4, string); offset += 4; proto_tree_add_item(wow_tree, hf_wow_timezone_bias, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(wow_tree, hf_wow_ip, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(wow_tree, hf_wow_srp_i_len, tvb, offset, 1, ENC_LITTLE_ENDIAN); srp_i_len = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(wow_tree, hf_wow_srp_i, tvb, offset, srp_i_len, ENC_ASCII|ENC_NA); offset += srp_i_len; } else if(WOW_SERVER_TO_CLIENT) { proto_tree_add_item(wow_tree, hf_wow_error, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; offset += 1; /* Unknown field */ proto_tree_add_item(wow_tree, hf_wow_srp_b, tvb, offset, 32, ENC_NA); offset += 32; proto_tree_add_item(wow_tree, hf_wow_srp_g_len, tvb, offset, 1, ENC_LITTLE_ENDIAN); srp_g_len = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(wow_tree, hf_wow_srp_g, tvb, offset, srp_g_len, ENC_NA); offset += srp_g_len; proto_tree_add_item(wow_tree, hf_wow_srp_n_len, tvb, offset, 1, ENC_LITTLE_ENDIAN); srp_n_len = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(wow_tree, hf_wow_srp_n, tvb, offset, srp_n_len, ENC_NA); offset += srp_n_len; proto_tree_add_item(wow_tree, hf_wow_srp_s, tvb, offset, 32, ENC_NA); offset += 32; offset += 16; /* Unknown field */ } break; case AUTH_LOGON_PROOF : if(WOW_CLIENT_TO_SERVER) { proto_tree_add_item(wow_tree, hf_wow_srp_a, tvb, offset, 32, ENC_NA); offset += 32; proto_tree_add_item(wow_tree, hf_wow_srp_m1, tvb, offset, 20, ENC_NA); offset += 20; proto_tree_add_item(wow_tree, hf_wow_crc_hash, tvb, offset, 20, ENC_NA); offset += 20; proto_tree_add_item(wow_tree, hf_wow_num_keys, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; offset += 1; /* Unknown field */ } else if(WOW_SERVER_TO_CLIENT) { proto_tree_add_item(wow_tree, hf_wow_error, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_tree, hf_wow_srp_m2, tvb, offset, 20, ENC_NA); offset += 20; offset += 4; /* Unknown field */ offset += 2; /* Unknown field */ } break; case REALM_LIST : if(WOW_CLIENT_TO_SERVER) { } else if(WOW_SERVER_TO_CLIENT) { proto_tree_add_item(wow_tree, hf_wow_pkt_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; offset += 4; /* Unknown field; always 0 */ proto_tree_add_item(wow_tree, hf_wow_num_realms, tvb, offset, 2, ENC_LITTLE_ENDIAN); num_realms = tvb_get_letohs(tvb, offset); offset += 2; for(i = 1; i <= num_realms; i++) { realm_name = tvb_get_ephemeral_stringz(tvb, offset + 3, &len); ti = proto_tree_add_text(wow_tree, tvb, offset, 0, "%s", realm_name); wow_realms_tree = proto_item_add_subtree(ti, ett_wow_realms); proto_tree_add_item(wow_realms_tree, hf_wow_realm_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_realms_tree, hf_wow_realm_status, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_realms_tree, hf_wow_realm_color, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_string(wow_realms_tree, hf_wow_realm_name, tvb, offset, len, realm_name); offset += len; string = tvb_get_ephemeral_stringz(tvb, offset, &len); proto_tree_add_string(wow_realms_tree, hf_wow_realm_socket, tvb, offset, len, string); offset += len; proto_tree_add_item(wow_realms_tree, hf_wow_realm_population_level, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(wow_realms_tree, hf_wow_realm_num_characters, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(wow_realms_tree, hf_wow_realm_timezone, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; offset += 1; /* Unknown field */ } break; } } } }
/* Process an APP1 block. * * XXX - This code only works on US-ASCII systems!!! */ static int process_app1_segment(proto_tree *tree, tvbuff_t *tvb, guint32 len, guint16 marker, const char *marker_name) { proto_item *ti = NULL; proto_tree *subtree = NULL; char *str; gint str_size; int offset = 0; int tiff_start; if (!tree) return 0; ti = proto_tree_add_item(tree, hf_marker_segment, tvb, 0, -1, ENC_NA); subtree = proto_item_add_subtree(ti, ett_marker_segment); proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker); proto_tree_add_item(subtree, hf_marker, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(subtree, hf_len, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; str = tvb_get_ephemeral_stringz(tvb, offset, &str_size); ti = proto_tree_add_item(subtree, hf_identifier, tvb, offset, str_size, ENC_ASCII|ENC_NA); offset += str_size; if (strcmp(str, "Exif") == 0) { /* * Endianness */ gboolean is_little_endian; guint16 val_16; guint32 val_32; guint16 num_fields; offset++; /* Skip a byte supposed to be 0x00 */ tiff_start = offset; val_16 = tvb_get_ntohs(tvb, offset); if (val_16 == 0x4949) { is_little_endian = TRUE; proto_tree_add_text(subtree, tvb, offset, 2, "Endianness: little endian"); } else if (val_16 == 0x4D4D) { is_little_endian = FALSE; proto_tree_add_text(subtree, tvb, offset, 2, "Endianness: big endian"); } else { /* Error: invalid endianness encoding */ proto_tree_add_text(subtree, tvb, offset, 2, "Incorrect endianness encoding - skipping the remainder of this application marker"); return offset; } offset += 2; /* * Fixed value 42 = 0x002a */ offset += 2; /* * Offset to IFD */ if (is_little_endian) { val_32 = tvb_get_letohl(tvb, offset); } else { val_32 = tvb_get_ntohl(tvb, offset); } /* * Check for a bogus val_32 value. * XXX - bogus value message should also deal with a * value that's too large and causes an overflow. * Or should it just check against the segment length, * which is 16 bits? */ if (val_32 + tiff_start < (guint32)offset + 4) { proto_tree_add_text(subtree, tvb, offset, 4, "Start offset of IFD starting from the TIFF header start: %u bytes (bogus, should be >= %u", val_32, offset + 4 - tiff_start); return offset; } proto_tree_add_text(subtree, tvb, offset, 4, "Start offset of IFD starting from the TIFF header start: %u bytes", val_32); offset += 4; /* * Skip the following portion */ if (val_32 + tiff_start > (guint32)offset) { proto_tree_add_text(subtree, tvb, offset, val_32 + tiff_start - offset, "Skipped data between end of TIFF header and start of IFD (%u bytes)", val_32 + tiff_start - offset); } for (;;) { offset = val_32 + tiff_start; /* * Process the IFD */ if (is_little_endian) { num_fields = tvb_get_letohs(tvb, offset); } else { num_fields = tvb_get_ntohs(tvb, offset); } proto_tree_add_text(subtree, tvb, offset, 2, "Number of fields in this IFD: %u", num_fields); offset += 2; while (num_fields-- > 0) { guint16 tag, type; guint32 count, off; if (is_little_endian) { tag = tvb_get_letohs(tvb, offset); type = tvb_get_letohs(tvb, offset + 2); count = tvb_get_letohl(tvb, offset + 4); off = tvb_get_letohl(tvb, offset + 8); } else { tag = tvb_get_ntohs(tvb, offset); type = tvb_get_ntohs(tvb, offset + 2); count = tvb_get_ntohl(tvb, offset + 4); off = tvb_get_ntohl(tvb, offset + 8); } /* TODO - refine this */ proto_tree_add_text(subtree, tvb, offset, 2, "Exif Tag: 0x%04X (%s), Type: %u (%s), Count: %u, " "Value offset from start of TIFF header: %u", tag, val_to_str(tag, vals_exif_tags, "Unknown Exif tag"), type, val_to_str(type, vals_exif_types, "Unknown Exif type"), count, off); offset += 12; } /* * Offset to the next IFD */ if (is_little_endian) { val_32 = tvb_get_letohl(tvb, offset); } else { val_32 = tvb_get_ntohl(tvb, offset); } if (val_32 != 0 && val_32 + tiff_start < (guint32)offset + 4) { proto_tree_add_text(subtree, tvb, offset, 4, "Offset to next IFD from start of TIFF header: %u bytes (bogus, should be >= %u)", val_32, offset + 4 - tiff_start); return offset; } proto_tree_add_text(subtree, tvb, offset, 4, "Offset to next IFD from start of TIFF header: %u bytes", val_32); offset += 4; if (val_32 == 0) break; } } else { proto_tree_add_text(subtree, tvb, offset, -1, "Remaining segment data (%u bytes)", len - 2 - str_size); proto_item_append_text(ti, " (Unknown identifier)"); } return offset; }
/* Process an APP0 block. * * XXX - This code only works on US-ASCII systems!!! */ static int process_app0_segment(proto_tree *tree, tvbuff_t *tvb, guint32 len, guint16 marker, const char *marker_name) { proto_item *ti = NULL; proto_tree *subtree = NULL; proto_tree *subtree_details = NULL; guint32 offset; char *str; gint str_size; if (!tree) return 0 ; ti = proto_tree_add_item(tree, hf_marker_segment, tvb, 0, -1, ENC_NA); subtree = proto_item_add_subtree(ti, ett_marker_segment); proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker); proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_len, tvb, 2, 2, ENC_BIG_ENDIAN); str = tvb_get_ephemeral_stringz(tvb, 4, &str_size); ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, ENC_ASCII|ENC_NA); if (strcmp(str, "JFIF") == 0) { /* Version */ ti = proto_tree_add_none_format(subtree, hf_version, tvb, 9, 2, "Version: %u.%u", tvb_get_guint8(tvb, 9), tvb_get_guint8(tvb, 10)); subtree_details = proto_item_add_subtree(ti, ett_details); proto_tree_add_item(subtree_details, hf_version_major, tvb, 9, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree_details, hf_version_minor, tvb, 10, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_units, tvb, 11, 1, ENC_BIG_ENDIAN); /* Aspect ratio */ proto_tree_add_item(subtree, hf_xdensity, tvb, 12, 2, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_ydensity, tvb, 14, 2, ENC_BIG_ENDIAN); /* Thumbnail */ proto_tree_add_item(subtree, hf_xthumbnail, tvb, 16, 1, ENC_BIG_ENDIAN); proto_tree_add_item(subtree, hf_ythumbnail, tvb, 17, 1, ENC_BIG_ENDIAN); { guint16 x = tvb_get_guint8(tvb, 16); guint16 y = tvb_get_guint8(tvb, 17); if (x || y) { proto_tree_add_item(subtree, hf_rgb, tvb, 18, 3 * (x * y), ENC_NA); offset = 18 + (3 * (x * y)); } else { offset = 18; } } } else if (strcmp(str, "JFXX") == 0) { proto_tree_add_item(subtree, hf_extension_code, tvb, 9, 1, ENC_BIG_ENDIAN); { guint8 code = tvb_get_guint8(tvb, 9); switch (code) { case 0x10: /* Thumbnail coded using JPEG */ break; case 0x11: /* thumbnail stored using 1 byte per pixel */ break; case 0x13: /* thumbnail stored using 3 bytes per pixel */ break; default: /* Error */ break; } } offset = 10; } else { /* Unknown */ proto_item_append_text(ti, " (unknown identifier)"); offset = 4 + str_size; proto_tree_add_text(subtree, tvb, offset, -1, "Remaining segment data (%u bytes)", len - 2 - str_size); } return offset; }
static int dissect_bson_document(tvbuff_t *tvb, packet_info *pinfo, guint offset, proto_tree *tree, int hf_mongo_doc, int nest_level) { gint32 document_length; guint final_offset; proto_item *ti, *elements, *element, *objectid, *js_code, *js_scope; proto_tree *doc_tree, *elements_tree, *element_sub_tree, *objectid_sub_tree, *js_code_sub_tree, *js_scope_sub_tree; document_length = tvb_get_letohl(tvb, offset); ti = proto_tree_add_item(tree, hf_mongo_doc, tvb, offset, document_length, ENC_NA); doc_tree = proto_item_add_subtree(ti, ett_mongo_doc); proto_tree_add_item(doc_tree, hf_mongo_document_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (nest_level > BSON_MAX_NESTING) { expert_add_info_format_text(pinfo, ti, &ei_mongo_document_recursion_exceeded, "BSON document recursion exceeds %u", BSON_MAX_NESTING); THROW(ReportedBoundsError); } if (document_length < 5) { expert_add_info_format_text(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too short: %u", document_length); THROW(ReportedBoundsError); } if (document_length > BSON_MAX_DOC_SIZE) { expert_add_info_format_text(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too long: %u", document_length); THROW(ReportedBoundsError); } if (document_length == 5) { /* document with length 5 is an empty document */ /* don't display the element subtree */ proto_tree_add_item(tree, hf_mongo_document_empty, tvb, offset, document_length, ENC_NA); return document_length; } final_offset = offset + document_length; offset += 4; elements = proto_tree_add_item(doc_tree, hf_mongo_elements, tvb, offset, document_length-5, ENC_NA); elements_tree = proto_item_add_subtree(elements, ett_mongo_elements); do { /* Read document elements */ guint8 e_type = -1; /* Element type */ gint str_len = -1; /* String length */ gint e_len = -1; /* Element length */ gint doc_len = -1; /* Document length */ e_type = tvb_get_guint8(tvb, offset); tvb_get_ephemeral_stringz(tvb, offset+1, &str_len); element = proto_tree_add_item(elements_tree, hf_mongo_element_name, tvb, offset+1, str_len-1, ENC_UTF_8|ENC_NA); element_sub_tree = proto_item_add_subtree(element, ett_mongo_element); proto_tree_add_item(element_sub_tree, hf_mongo_element_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += str_len+1; switch(e_type) { case BSON_ELEMENT_TYPE_DOUBLE: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; break; case BSON_ELEMENT_TYPE_STRING: case BSON_ELEMENT_TYPE_JS_CODE: case BSON_ELEMENT_TYPE_SYMBOL: str_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA); offset += str_len+4; break; case BSON_ELEMENT_TYPE_DOC: case BSON_ELEMENT_TYPE_ARRAY: offset += dissect_bson_document(tvb, pinfo, offset, element_sub_tree, hf_mongo_document, nest_level+1); break; case BSON_ELEMENT_TYPE_BINARY: e_len = tvb_get_letohl(tvb, offset); /* TODO - Add functions to decode various binary subtypes */ proto_tree_add_item(element_sub_tree, hf_mongo_element_value_binary_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_binary, tvb, offset+5, e_len, ENC_NA); offset += e_len+5; break; case BSON_ELEMENT_TYPE_UNDEF: case BSON_ELEMENT_TYPE_NULL: case BSON_ELEMENT_TYPE_MIN_KEY: case BSON_ELEMENT_TYPE_MAX_KEY: /* Nothing to do, as there is no element content */ break; case BSON_ELEMENT_TYPE_OBJ_ID: objectid = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_objectid, tvb, offset, 12, ENC_NA); objectid_sub_tree = proto_item_add_subtree(objectid, ett_mongo_objectid); /* Unlike most BSON elements, parts of ObjectID are stored Big Endian, so they can be compared bit by bit */ proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_time, tvb, offset, 4, ENC_BIG_ENDIAN); proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_machine, tvb, offset+4, 3, ENC_LITTLE_ENDIAN); proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_pid, tvb, offset+7, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(objectid_sub_tree, hf_mongo_element_value_objectid_inc, tvb, offset+9, 3, ENC_BIG_ENDIAN); offset += 12; break; case BSON_ELEMENT_TYPE_BOOL: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_boolean, tvb, offset, 1, ENC_NA); offset += 1; break; case BSON_ELEMENT_TYPE_REGEX: /* regex pattern */ tvb_get_ephemeral_stringz(tvb, offset, &str_len); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_regex_pattern, tvb, offset, str_len, ENC_UTF_8|ENC_NA); offset += str_len; /* regex options */ tvb_get_ephemeral_stringz(tvb, offset, &str_len); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_regex_options, tvb, offset, str_len, ENC_UTF_8|ENC_NA); offset += str_len; break; case BSON_ELEMENT_TYPE_DB_PTR: str_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(element_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA); offset += str_len; proto_tree_add_item(element_sub_tree, hf_mongo_element_value_db_ptr, tvb, offset, 12, ENC_NA); offset += 12; break; case BSON_ELEMENT_TYPE_JS_CODE_SCOPE: /* code_w_s ::= int32 string document */ proto_tree_add_item(element_sub_tree, hf_mongo_element_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); e_len = tvb_get_letohl(tvb, offset); offset += 4; str_len = tvb_get_letohl(tvb, offset); js_code = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_js_code, tvb, offset, str_len+4, ENC_NA); js_code_sub_tree = proto_item_add_subtree(js_code, ett_mongo_code); proto_tree_add_item(js_code_sub_tree, hf_mongo_element_value_string_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(js_code_sub_tree, hf_mongo_element_value_string, tvb, offset+4, str_len, ENC_UTF_8|ENC_NA); offset += str_len+4; doc_len = e_len - (str_len + 8); js_scope = proto_tree_add_item(element_sub_tree, hf_mongo_element_value_js_scope, tvb, offset, doc_len, ENC_NA); js_scope_sub_tree = proto_item_add_subtree(js_scope, ett_mongo_code); offset += dissect_bson_document(tvb, pinfo, offset, js_scope_sub_tree, hf_mongo_document, nest_level+1); break; case BSON_ELEMENT_TYPE_INT32: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_int32, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; break; case BSON_ELEMENT_TYPE_DATETIME: case BSON_ELEMENT_TYPE_TIMESTAMP: /* TODO Implement routine to convert datetime & timestamp values to UTC date/time */ /* for now, simply display the integer value */ case BSON_ELEMENT_TYPE_INT64: proto_tree_add_item(element_sub_tree, hf_mongo_element_value_int64, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; break; default: break; } /* end switch() */ } while (offset < final_offset-1); return document_length; }
static void dissect_exec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *exec_tree=NULL; /* Variables for extracting and displaying data from the packet */ guchar *field_stringz; /* Temporary storage for each field we extract */ gint length; guint offset = 0; conversation_t *conversation; exec_hash_entry_t *hash_info; conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); if(!conversation){ /* Conversation does not exist yet - create it */ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0); } /* Retrieve information from conversation * or add it if it isn't there yet */ hash_info = conversation_get_proto_data(conversation, proto_exec); if(!hash_info){ hash_info = se_alloc(sizeof(exec_hash_entry_t)); hash_info->first_packet_number = pinfo->fd->num; hash_info->second_packet_number = 0; hash_info->third_packet_number = 0; hash_info->fourth_packet_number = 0; hash_info->state = WAIT_FOR_STDERR_PORT; /* The first field we'll see */ /* Start with empty username and command strings */ hash_info->username=NULL; hash_info->command=NULL; /* These will be set on the first pass by the first * four packets of the conversation */ hash_info->first_packet_state = NONE; hash_info->second_packet_state = NONE; hash_info->third_packet_state = NONE; hash_info->fourth_packet_state = NONE; conversation_add_proto_data(conversation, proto_exec, hash_info); } /* Store the number of the first three packets of this conversation * as we reach them the first time */ if(!hash_info->second_packet_number && pinfo->fd->num > hash_info->first_packet_number){ /* We're on the second packet of the conversation */ hash_info->second_packet_number = pinfo->fd->num; } else if(hash_info->second_packet_number && !hash_info->third_packet_number && pinfo->fd->num > hash_info->second_packet_number) { /* We're on the third packet of the conversation */ hash_info->third_packet_number = pinfo->fd->num; } else if(hash_info->third_packet_number && !hash_info->fourth_packet_number && pinfo->fd->num > hash_info->third_packet_number) { /* We're on the fourth packet of the conversation */ hash_info->fourth_packet_number = pinfo->fd->num; } /* Save this packet's state so we can retrieve it if this packet * is selected again later. If the packet's state was already stored, * then retrieve it */ if(pinfo->fd->num == hash_info->first_packet_number){ if(hash_info->first_packet_state == NONE){ hash_info->first_packet_state = hash_info->state; } else { hash_info->state = hash_info->first_packet_state; } } if(pinfo->fd->num == hash_info->second_packet_number){ if(hash_info->second_packet_state == NONE){ hash_info->second_packet_state = hash_info->state; } else { hash_info->state = hash_info->second_packet_state; } } if(pinfo->fd->num == hash_info->third_packet_number){ if(hash_info->third_packet_state == NONE){ hash_info->third_packet_state = hash_info->state; } else { hash_info->state = hash_info->third_packet_state; } } if(pinfo->fd->num == hash_info->fourth_packet_number){ if(hash_info->fourth_packet_state == NONE){ hash_info->fourth_packet_state = hash_info->state; } else { hash_info->state = hash_info->fourth_packet_state; } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "EXEC"); if(check_col(pinfo->cinfo, COL_INFO)){ /* First, clear the info column */ col_clear(pinfo->cinfo, COL_INFO); /*username */ if(hash_info->username && preference_info_show_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Username:%s ", hash_info->username); } /* Command */ if(hash_info->command && preference_info_show_command == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Command:%s ", hash_info->command); } } /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_exec, tvb, 0, -1, FALSE); exec_tree = proto_item_add_subtree(ti, ett_exec); /* If this packet doesn't end with a null terminated string, * then it must be session data only and we can skip looking * for the other fields. */ if(tvb_find_guint8(tvb, tvb_length(tvb)-1, 1, '\0') == -1){ hash_info->state = WAIT_FOR_DATA; } if(hash_info->state == WAIT_FOR_STDERR_PORT && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the stderr_port field. * It is optional, so it may only be 1 character long * (the NULL) */ if(length == 1 || (exec_isdigit_string(field_stringz) && length <= EXEC_STDERR_PORT_LEN)){ proto_tree_add_string(exec_tree, hf_exec_stderr_port, tvb, offset, length, (gchar*)field_stringz); /* Next field we need */ hash_info->state = WAIT_FOR_USERNAME; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the username field */ if(length != 1 && length <= EXEC_USERNAME_LEN && exec_isprint_string(field_stringz)){ proto_tree_add_string(exec_tree, hf_exec_username, tvb, offset, length, (gchar*)field_stringz); /* Store the username so we can display it in the * info column of the entire conversation */ if(!hash_info->username){ hash_info->username=se_strdup((gchar*)field_stringz); } /* Next field we need */ hash_info->state = WAIT_FOR_PASSWORD; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; } if(hash_info->state == WAIT_FOR_PASSWORD && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the password field */ if(length != 1 && length <= EXEC_PASSWORD_LEN && exec_isprint_string(field_stringz)){ proto_tree_add_string(exec_tree, hf_exec_password, tvb, offset, length, (gchar*)field_stringz); /* Next field we need */ hash_info->state = WAIT_FOR_COMMAND; } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } /* Used if the next field is in the same packet */ offset += length; /* Next field we are looking for */ hash_info->state = WAIT_FOR_COMMAND; } if(hash_info->state == WAIT_FOR_COMMAND && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length); /* Check if this looks like the command field */ if(length != 1 && length <= EXEC_COMMAND_LEN && exec_isprint_string(field_stringz)){ proto_tree_add_string(exec_tree, hf_exec_command, tvb, offset, length, (gchar*)field_stringz); /* Store the username so we can display it in the * info column of the entire conversation */ if(!hash_info->command){ hash_info->command=se_strdup((gchar*)field_stringz); } } else { /* Since the data doesn't match this field, it must be data only */ hash_info->state = WAIT_FOR_DATA; } } if(hash_info->state == WAIT_FOR_DATA && tvb_length_remaining(tvb, offset)){ if(pinfo->destport == EXEC_PORT){ /* Packet going to the server */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(exec_tree, tvb, 0, -1, "Client -> Server Data"); if(check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, "Client -> Server data"); } else { /* This packet must be going back to the client */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(exec_tree, tvb, 0, -1, "Server -> Client Data"); if(check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, "Server -> Client Data"); } } /* We haven't seen all of the fields yet */ if(hash_info->state < WAIT_FOR_DATA){ col_set_str(pinfo->cinfo, COL_INFO, "Session Establishment"); } }
static void dissect_turbocell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti, *name_item; proto_tree *turbocell_tree = NULL, *network_tree; tvbuff_t *next_tvb; int i=0; guint8 packet_type; guint8 * str_name; guint str_len; gint remaining_length; packet_type = tvb_get_guint8(tvb, 0); if (!(packet_type & 0x0F)) { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Beacon)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else if ( packet_type == TURBOCELL_TYPE_MANAGEMENT ) { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Management)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else if ( packet_type == TURBOCELL_TYPE_DATA ) { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Data)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } else { col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Unknown)"); col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell"); } if (tree) { ti = proto_tree_add_item(tree, proto_turbocell, tvb, 0, 20, ENC_NA); turbocell_tree = proto_item_add_subtree(ti, ett_turbocell); proto_tree_add_item(turbocell_tree, hf_turbocell_type, tvb, 0, 1, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_satmode, tvb, 1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_nwid, tvb, 1, 1, ENC_BIG_ENDIAN); /* it seem when we have this magic number,that means an alternate header version */ if (tvb_get_bits64(tvb, 64,48,ENC_BIG_ENDIAN) != G_GINT64_CONSTANT(0x000001fe23dc45ba)) { proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x02, 2, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x04, 6, ENC_NA); proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x0A, 3, ENC_BIG_ENDIAN); } else { proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x02, 3, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x05, 3, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x08, 6, ENC_NA); } proto_tree_add_item(turbocell_tree, hf_turbocell_unknown, tvb, 0x0E, 2, ENC_BIG_ENDIAN); proto_tree_add_item(turbocell_tree, hf_turbocell_ip, tvb, 0x10, 4, ENC_BIG_ENDIAN); } remaining_length=tvb_length_remaining(tvb, 0x14); if (remaining_length > 6) { /* If the first character is a printable character that means we have a payload with network info */ /* I couldn't find anything in the header that would definitvely indicate if payload is either data or network info */ /* Since the frame size is limited this should work ok */ if (tvb_get_guint8(tvb, 0x14)>=0x20) { name_item = proto_tree_add_item(turbocell_tree, hf_turbocell_name, tvb, 0x14, 30, ENC_ASCII|ENC_NA); network_tree = proto_item_add_subtree(name_item, ett_network); str_name=tvb_get_ephemeral_stringz(tvb, 0x14, &str_len); if (check_col (pinfo->cinfo, COL_INFO) && str_len > 0) col_append_fstr(pinfo->cinfo, COL_INFO, ", Network=\"%s\"",format_text(str_name, str_len-1)); while(tvb_get_guint8(tvb, 0x34 + 8*i)==0x00 && (tvb_length_remaining(tvb,0x34 + 8*i) > 6) && (i<32)) { proto_tree_add_item(network_tree, hf_turbocell_station[i], tvb, 0x34+8*i, 6, ENC_NA); i++; } /*Couldn't make sense of the apparently random data in the end*/ next_tvb = tvb_new_subset_remaining(tvb, 0x34 + 8*i); call_dissector(data_handle, next_tvb, pinfo, tree); } else { tvbuff_t *volatile msdu_tvb = NULL; guint32 msdu_offset = 0x04; guint16 j = 1; guint16 msdu_length; proto_item *parent_item; proto_tree *mpdu_tree; proto_tree *subframe_tree; next_tvb = tvb_new_subset(tvb, 0x14, -1, tvb_get_ntohs(tvb, 0x14)); parent_item = proto_tree_add_protocol_format(tree, proto_aggregate, next_tvb, 0, tvb_reported_length_remaining(next_tvb, 0), "Turbocell Aggregate Frames"); mpdu_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_parent_tree); proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_len, next_tvb, 0x00, 2, ENC_BIG_ENDIAN); proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_unknown1, next_tvb, 0x02, 2, ENC_BIG_ENDIAN); remaining_length=tvb_length_remaining(next_tvb, msdu_offset); do { msdu_length = (tvb_get_letohs(next_tvb, msdu_offset) & 0x0FFF); if (msdu_length==0) break; parent_item = proto_tree_add_uint_format(mpdu_tree, hf_turbocell_aggregate_msdu_header_text, next_tvb,msdu_offset, msdu_length + 0x02,j, "A-MSDU Subframe #%u", j); subframe_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_subframe_tree); j++; proto_tree_add_uint_format(subframe_tree, hf_turbocell_aggregate_msdu_len, next_tvb, msdu_offset, 2, msdu_length, "MSDU length: %u (0x%04X)", msdu_length,msdu_length); proto_tree_add_item(subframe_tree, hf_turbocell_aggregate_unknown2, next_tvb, msdu_offset+1, 1, ENC_BIG_ENDIAN); msdu_offset += 0x02; remaining_length -= 0x02; msdu_tvb = tvb_new_subset(next_tvb, msdu_offset, (msdu_length>remaining_length)?remaining_length:msdu_length, msdu_length); call_dissector(eth_handle, msdu_tvb, pinfo, subframe_tree); msdu_offset += msdu_length; remaining_length -= msdu_length; } while (remaining_length > 6); if (remaining_length > 2) { next_tvb = tvb_new_subset_remaining(next_tvb, msdu_offset); call_dissector(data_handle, next_tvb, pinfo, tree); } } } }
static void dissect_mailslot_browse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { int offset = 0; guint8 cmd; proto_tree *tree = NULL; proto_item *item = NULL; guint32 periodicity; gchar host_name[17]; gchar *utf8_host_name; gint namelen; guint8 server_count, reset_cmd; guint8 os_major_ver, os_minor_ver; const gchar *windows_version = NULL; int i; guint32 uptime; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BROWSER"); col_clear(pinfo->cinfo, COL_INFO); cmd = tvb_get_guint8(tvb, offset); /* Put in something, and replace it later */ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown command:0x%02x")); item = proto_tree_add_item(parent_tree, proto_smb_browse, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_browse); /* command */ proto_tree_add_uint(tree, hf_command, tvb, offset, 1, cmd); offset += 1; switch (cmd) { case BROWSE_DOMAIN_ANNOUNCEMENT: case BROWSE_LOCAL_MASTER_ANNOUNCEMENT: case BROWSE_HOST_ANNOUNCE: { /* update count */ proto_tree_add_item(tree, hf_update_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* periodicity (in milliseconds) */ periodicity = tvb_get_letohl(tvb, offset); proto_tree_add_uint_format(tree, hf_periodicity, tvb, offset, 4, periodicity, "Update Periodicity: %s", time_msecs_to_str(periodicity)); offset += 4; /* server name */ tvb_get_nstringz0(tvb, offset, sizeof(host_name), host_name); utf8_host_name = g_convert(host_name, strlen(host_name), "UTF-8", "CP437", NULL, NULL, NULL); if (utf8_host_name == NULL) utf8_host_name = host_name; col_append_fstr(pinfo->cinfo, COL_INFO, " %s", utf8_host_name); proto_tree_add_string_format(tree, hf_server_name, tvb, offset, 16, utf8_host_name, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? "Domain/Workgroup: %s": "Host Name: %s", utf8_host_name); if (utf8_host_name != host_name) g_free(utf8_host_name); offset += 16; /* Windows version (See "OSVERSIONINFO Structure" on MSDN) */ os_major_ver = tvb_get_guint8(tvb, offset); os_minor_ver = tvb_get_guint8(tvb, offset+1); SET_WINDOWS_VERSION_STRING(os_major_ver, os_minor_ver, windows_version); if(windows_version) proto_tree_add_text(tree, tvb, offset, 2, "Windows version: %s", windows_version); /* OS major version */ proto_tree_add_item(tree, hf_os_major, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* OS minor version */ proto_tree_add_item(tree, hf_os_minor, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* server type flags */ offset = dissect_smb_server_type_flags( tvb, offset, pinfo, tree, NULL, TRUE); if (cmd == BROWSE_DOMAIN_ANNOUNCEMENT && tvb_get_letohs (tvb, offset + 2) != 0xAA55) { /* * Network Monitor claims this is a "Comment * Pointer". I don't believe it. * * It's not a browser protocol major/minor * version number, and signature constant, * however. */ proto_tree_add_text(tree, tvb, offset, 4, "Mysterious Field: 0x%08x", tvb_get_letohl(tvb, offset)); offset += 4; } else { /* browser protocol major version */ proto_tree_add_item(tree, hf_proto_major, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* browser protocol minor version */ proto_tree_add_item(tree, hf_proto_minor, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* signature constant */ proto_tree_add_item(tree, hf_sig_const, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } /* master browser server name or server comment */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? hf_mb_server_name : hf_server_comment, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; } case BROWSE_REQUEST_ANNOUNCE: { guint8 *computer_name; /* unused/unknown flags */ proto_tree_add_item(tree, hf_unused_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* name of computer to which to send reply */ computer_name = tvb_get_ephemeral_stringz(tvb, offset, &namelen); proto_tree_add_string(tree, hf_response_computer_name, tvb, offset, namelen, computer_name); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", computer_name); break; } case BROWSE_ELECTION_REQUEST: /* election version */ proto_tree_add_item(tree, hf_election_version, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* criterion */ dissect_election_criterion(tvb, tree, offset); offset += 4; /* server uptime */ uptime = tvb_get_letohl(tvb, offset); proto_tree_add_uint_format(tree, hf_server_uptime, tvb, offset, 4, uptime, "Uptime: %s", time_msecs_to_str(uptime)); offset += 4; /* next 4 bytes must be zero */ offset += 4; /* server name */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_server_name, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; case BROWSE_BACKUP_LIST_REQUEST: /* backup list requested count */ proto_tree_add_item(tree, hf_backup_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* backup requested token */ proto_tree_add_item(tree, hf_backup_token, tvb, offset, 4, ENC_LITTLE_ENDIAN); break; case BROWSE_BACKUP_LIST_RESPONSE: /* backup list requested count */ server_count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_backup_count, tvb, offset, 1, server_count); offset += 1; /* backup requested token */ proto_tree_add_item(tree, hf_backup_token, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* backup server names */ for (i = 0; i < server_count; i++) { namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_backup_server, tvb, offset, namelen, ENC_ASCII|ENC_NA); offset += namelen; } break; case BROWSE_MASTER_ANNOUNCEMENT: /* master browser server name */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_mb_server_name, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; case BROWSE_RESETBROWSERSTATE_ANNOUNCEMENT: { proto_tree *sub_tree; proto_item *reset_item; /* the subcommand follows ... one of three values */ reset_cmd = tvb_get_guint8(tvb, offset); reset_item = proto_tree_add_uint(tree, hf_mb_reset_command, tvb, offset, 1, reset_cmd); sub_tree = proto_item_add_subtree(reset_item, ett_browse_reset_cmd_flags); proto_tree_add_boolean(sub_tree, hf_mb_reset_demote, tvb, offset, 1, reset_cmd); proto_tree_add_boolean(sub_tree, hf_mb_reset_flush, tvb, offset, 1, reset_cmd); proto_tree_add_boolean(sub_tree, hf_mb_reset_stop, tvb, offset, 1, reset_cmd); break; } case BROWSE_BECOME_BACKUP: /* name of browser to promote */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_browser_to_promote, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; } }
/* Code to actually dissect the packets */ static void dissect_ipa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint remaining; gint header_length = 3; int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPA"); col_clear(pinfo->cinfo, COL_INFO); while ((remaining = tvb_reported_length_remaining(tvb, offset)) > 0) { proto_item *ti; proto_tree *ipa_tree = NULL; guint16 len, msg_type; tvbuff_t *next_tvb; len = tvb_get_ntohs(tvb, offset); msg_type = tvb_get_guint8(tvb, offset+2); col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(msg_type, ipa_protocol_vals, "unknown 0x%02x")); /* * The IPA header is different depending on the transport protocol. * With UDP there seems to be a fourth byte for the IPA header. * We attempt to detect this by checking if the length from the * header + four bytes of the IPA header equals the remaining size. */ if ((pinfo->ipproto == IP_PROTO_UDP) && (len + 4 == remaining)) { header_length++; } if (tree) { ti = proto_tree_add_protocol_format(tree, proto_ipa, tvb, offset, len+header_length, "IPA protocol ip.access, type: %s", val_to_str(msg_type, ipa_protocol_vals, "unknown 0x%02x")); ipa_tree = proto_item_add_subtree(ti, ett_ipa); proto_tree_add_item(ipa_tree, hf_ipa_data_len, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(ipa_tree, hf_ipa_protocol, tvb, offset+2, 1, ENC_BIG_ENDIAN); } next_tvb = tvb_new_subset(tvb, offset+header_length, len, len); switch (msg_type) { case ABISIP_OML: /* hand this off to the standard A-bis OML dissector */ if (sub_handles[SUB_OML]) call_dissector(sub_handles[SUB_OML], next_tvb, pinfo, tree); break; case ABISIP_IPACCESS: dissect_ipaccess(next_tvb, pinfo, tree); break; case AIP_SCCP: /* hand this off to the standard SCCP dissector */ call_dissector(sub_handles[SUB_SCCP], next_tvb, pinfo, tree); break; case IPA_MGCP: /* hand this off to the standard MGCP dissector */ call_dissector(sub_handles[SUB_MGCP], next_tvb, pinfo, tree); break; case OSMO_EXT: dissect_osmo(next_tvb, pinfo, ipa_tree, tree); break; case HSL_DEBUG: if (tree) { proto_tree_add_item(ipa_tree, hf_ipa_hsl_debug, next_tvb, 0, len, ENC_ASCII|ENC_NA); if (global_ipa_in_root == TRUE) proto_tree_add_item(tree, hf_ipa_hsl_debug, next_tvb, 0, len, ENC_ASCII|ENC_NA); } if (global_ipa_in_info == TRUE) col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", tvb_get_ephemeral_stringz(next_tvb, 0, NULL)); break; default: if (msg_type < ABISIP_RSL_MAX) { /* hand this off to the standard A-bis RSL dissector */ call_dissector(sub_handles[SUB_RSL], next_tvb, pinfo, tree); } break; } offset += len + header_length; } }