static int TvbRange_ustringz_any(lua_State* L, gboolean little_endian) { /* Obtain a zero terminated string from a TvbRange */ gint count; TvbRange tvbr = checkTvbRange(L,1); gint offset; gunichar2 uchar; if ( !(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } offset = tvbr->offset; do { if (!tvb_bytes_exist (tvbr->tvb->ws_tvb, offset, 2)) { luaL_error(L,"out of bounds"); return 0; } /* Endianness doesn't matter when looking for null */ uchar = tvb_get_ntohs (tvbr->tvb->ws_tvb, offset); offset += 2; } while (uchar != 0); lua_pushstring(L, (gchar*)tvb_get_stringz_enc(wmem_packet_scope(),tvbr->tvb->ws_tvb,tvbr->offset,&count,(little_endian ? ENC_UTF_16|ENC_LITTLE_ENDIAN : ENC_UTF_16|ENC_BIG_ENDIAN)) ); lua_pushinteger(L,count); return 2; /* The zero terminated string, the length found in tvbr */ }
/* 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_stringz_enc(wmem_packet_scope(), tvb, 4, &str_size, ENC_ASCII); 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)"); } }
/* 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; proto_tree *subtree; 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_stringz_enc(wmem_packet_scope(), tvb, 4, &str_size, ENC_ASCII); ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, ENC_ASCII|ENC_NA); if (strcmp(str, "FPXR") == 0) { proto_tree_add_item(tree, hf_exif_flashpix_marker, tvb, 0, -1, ENC_NA); } else { proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, 4 + str_size, -1, NULL, "%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_reported_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_stringz_enc(wmem_packet_scope(), tvb, offset, &string_len, ENC_ASCII); proto_tree_add_item(ts2_tree, hf_ts2_channel_name, tvb, offset,string_len , ENC_ASCII|ENC_NA); offset+=string_len; tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &string_len, ENC_ASCII); proto_tree_add_item(ts2_tree, hf_ts2_channel_topic, tvb, offset,string_len ,ENC_ASCII|ENC_NA); offset+=string_len; tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &string_len, ENC_ASCII); 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 */ #define WSLUA_OPTARG_TvbRange_stringz_ENCODING 2 /* The encoding to use. Defaults to ENC_ASCII. */ TvbRange tvbr = checkTvbRange(L,1); guint encoding = (guint)luaL_optint(L,WSLUA_OPTARG_TvbRange_stringz_ENCODING, ENC_ASCII|ENC_NA); gint offset; gunichar2 uchar; if ( !(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } switch (encoding & ENC_CHARENCODING_MASK) { case ENC_UTF_16: case ENC_UCS_2: offset = tvbr->offset; do { if (!tvb_bytes_exist (tvbr->tvb->ws_tvb, offset, 2)) { luaL_error(L,"out of bounds"); return 0; } /* Endianness doesn't matter when looking for null */ uchar = tvb_get_ntohs (tvbr->tvb->ws_tvb, offset); offset += 2; } while(uchar != 0); break; default: if (tvb_find_guint8 (tvbr->tvb->ws_tvb, tvbr->offset, -1, 0) == -1) { luaL_error(L,"out of bounds"); return 0; } break; } lua_pushstring(L, (gchar*)tvb_get_stringz_enc(wmem_packet_scope(),tvbr->tvb->ws_tvb,tvbr->offset,NULL,encoding)); WSLUA_RETURN(1); /* The zero terminated string */ }
static void dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int direction) { proto_tree *cl_tree = NULL; proto_tree *text_tree = NULL; guint8 *text; int len; int offset; guint32 marker; int command_len; const char *command = ""; gboolean command_finished = FALSE; marker = tvb_get_ntohl(tvb, 0); if (tree) { proto_item *cl_item; cl_item = proto_tree_add_text(tree, tvb, 0, -1, "Connectionless"); cl_tree = proto_item_add_subtree(cl_item, ett_quakeworld_connectionless); proto_tree_add_uint(cl_tree, hf_quakeworld_connectionless_marker, tvb, 0, 4, marker); } /* all the rest of the packet is just text */ offset = 4; text = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII|ENC_NA); /* actually, we should look for a eol char and stop already there */ if (cl_tree) { proto_item *text_item; text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text, tvb, offset, len, text); text_tree = proto_item_add_subtree(text_item, ett_quakeworld_connectionless_text); } if (direction == DIR_C2S) { /* client to server commands */ const char *c; Cmd_TokenizeString(text); c = Cmd_Argv(0); /* client to sever commands */ if (strcmp(c,"ping") == 0) { command = "Ping"; command_len = 4; } else if (strcmp(c,"status") == 0) { command = "Status"; command_len = 6; } else if (strcmp(c,"log") == 0) { command = "Log"; command_len = 3; } else if (strcmp(c,"connect") == 0) { int version; int qport; int challenge; const char *infostring; proto_tree *argument_tree = NULL; command = "Connect"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } version = atoi(Cmd_Argv(1)); qport = atoi(Cmd_Argv(2)); challenge = atoi(Cmd_Argv(3)); infostring = Cmd_Argv(4); if (argument_tree) { proto_item *info_item; proto_tree *info_tree; proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_version, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), version); proto_tree_add_uint(argument_tree, hf_quakeworld_connectionless_connect_qport, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_length(2), qport); proto_tree_add_int(argument_tree, hf_quakeworld_connectionless_connect_challenge, tvb, offset + Cmd_Argv_start(3), Cmd_Argv_length(3), challenge); info_item = proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_connect_infostring, tvb, offset + Cmd_Argv_start(4), Cmd_Argv_length(4), infostring); info_tree = proto_item_add_subtree( info_item, ett_quakeworld_connectionless_connect_infostring); dissect_id_infostring(tvb, info_tree, offset + Cmd_Argv_start(4), wmem_strdup(wmem_packet_scope(), infostring), ett_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key_value, hf_quakeworld_connectionless_connect_infostring_key, hf_quakeworld_connectionless_connect_infostring_value); } } else if (strcmp(c,"getchallenge") == 0) { command = "Get Challenge"; command_len = Cmd_Argv_length(0); } else if (strcmp(c,"rcon") == 0) { const char* password; int i; char remaining[MAX_TEXT_SIZE+1]; proto_tree *argument_tree = NULL; command = "Remote Command"; command_len = Cmd_Argv_length(0); if (text_tree) { proto_item *argument_item; proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, tvb, offset + Cmd_Argv_start(1), len - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); command_finished=TRUE; } password = Cmd_Argv(1); if (argument_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_password, tvb, offset + Cmd_Argv_start(1), Cmd_Argv_length(1), password); } remaining[0] = '\0'; for (i=2; i<Cmd_Argc() ; i++) { g_strlcat (remaining, Cmd_Argv(i), MAX_TEXT_SIZE+1); g_strlcat (remaining, " ", MAX_TEXT_SIZE+1); } if (text_tree) { proto_tree_add_string(argument_tree, hf_quakeworld_connectionless_rcon_command, tvb, offset + Cmd_Argv_start(2), Cmd_Argv_start(Cmd_Argc()-1) + Cmd_Argv_length(Cmd_Argc()-1) - Cmd_Argv_start(2), remaining); } } else if (c[0]==A2A_PING && ( c[1]=='\0' || c[1]=='\n')) { command = "Ping"; command_len = 1; } else if (c[0]==A2A_ACK && ( c[1]=='\0' || c[1]=='\n')) { command = "Ack"; command_len = 1; } else { command = "Unknown"; command_len = len - 1; } } else { /* server to client commands */ if (text[0] == S2C_CONNECTION) { command = "Connected"; command_len = 1; } else if (text[0] == A2C_CLIENT_COMMAND) { command = "Client Command"; command_len = 1; /* stringz (command), stringz (localid) */ } else if (text[0] == A2C_PRINT) { command = "Print"; command_len = 1; /* string */ } else if (text[0] == A2A_PING) { command = "Ping"; command_len = 1; } else if (text[0] == S2C_CHALLENGE) { command = "Challenge"; command_len = 1; /* string, atoi */ } else { command = "Unknown"; command_len = len - 1; } } col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command); if (!command_finished) { proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); } /*offset += len;*/ }
/* 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_length(tvb, offset+header_length, 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_stringz_enc(wmem_packet_scope(), next_tvb, 0, NULL, ENC_ASCII)); 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; } }
static void dissect_pgsql_be_msg(guchar type, guint length, tvbuff_t *tvb, gint n, proto_tree *tree) { guchar c; gint i, siz; char *s, *t; proto_item *ti; proto_tree *shrub; switch (type) { /* Authentication request */ case 'R': proto_tree_add_item(tree, hf_authtype, tvb, n, 4, ENC_BIG_ENDIAN); i = tvb_get_ntohl(tvb, n); if (i == 4 || i == 5) { /* i -= (6-i); :-) */ n += 4; siz = (i == 4 ? 2 : 4); proto_tree_add_item(tree, hf_salt, tvb, n, siz, ENC_NA); } break; /* Key data */ case 'K': proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_key, tvb, n+4, 4, ENC_BIG_ENDIAN); break; /* Parameter status */ case 'S': s = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n, &siz, ENC_ASCII); proto_tree_add_string(tree, hf_parameter_name, tvb, n, siz, s); n += siz; t = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n, &i, ENC_ASCII); proto_tree_add_string(tree, hf_parameter_value, tvb, n, i, t); break; /* Parameter description */ case 't': i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameters: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; } break; /* Row description */ case 'T': i = tvb_get_ntohs(tvb, n); ti = proto_tree_add_item(tree, hf_field_count, tvb, n, 2, ENC_BIG_ENDIAN); shrub = proto_item_add_subtree(ti, ett_values); n += 2; while (i-- > 0) { proto_tree *twig; siz = tvb_strsize(tvb, n); ti = proto_tree_add_item(shrub, hf_val_name, tvb, n, siz, ENC_ASCII|ENC_NA); twig = proto_item_add_subtree(ti, ett_values); n += siz; proto_tree_add_item(twig, hf_tableoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; proto_tree_add_item(twig, hf_val_idx, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; proto_tree_add_item(twig, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; proto_tree_add_item(twig, hf_val_length, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; proto_tree_add_item(twig, hf_val_mod, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; proto_tree_add_item(twig, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } break; /* Data row */ case 'D': i = tvb_get_ntohs(tvb, n); ti = proto_tree_add_item(tree, hf_field_count, tvb, n, 2, ENC_BIG_ENDIAN); shrub = proto_item_add_subtree(ti, ett_values); n += 2; while (i-- > 0) { siz = tvb_get_ntohl(tvb, n); proto_tree_add_int(shrub, hf_val_length, tvb, n, 4, siz); n += 4; if (siz > 0) { proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA); n += siz; } } break; /* Command completion */ case 'C': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_tag, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Ready */ case 'Z': proto_tree_add_item(tree, hf_status, tvb, n, 1, ENC_NA); break; /* Error, Notice */ case 'E': case 'N': length -= 4; while ((signed)length > 0) { c = tvb_get_guint8(tvb, n); if (c == '\0') break; s = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n+1, &siz, ENC_ASCII); i = hf_text; switch (c) { case 'S': i = hf_severity; break; case 'C': i = hf_code; break; case 'M': i = hf_message; break; case 'D': i = hf_detail; break; case 'H': i = hf_hint; break; case 'P': i = hf_position; break; case 'p': i = hf_internal_position; break; case 'q': i = hf_internal_query; break; case 'W': i = hf_where; break; case 's': i = hf_schema_name; break; case 't': i = hf_table_name; break; case 'c': i = hf_column_name; break; case 'd': i = hf_type_name; break; case 'n': i = hf_constraint_name; break; case 'F': i = hf_file; break; case 'L': i = hf_line; break; case 'R': i = hf_routine; break; } proto_tree_add_string(tree, i, tvb, n, siz+1, s); length -= siz+1; n += siz+1; } break; /* NOTICE response */ case 'A': proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_condition, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; siz = tvb_strsize(tvb, n); if (siz > 1) proto_tree_add_item(tree, hf_text, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Copy in/out */ case 'G': case 'H': proto_tree_add_item(tree, hf_format, tvb, n, 1, ENC_BIG_ENDIAN); n += 1; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Columns: %d", i); n += 2; while (i-- > 2) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } break; /* Copy data */ case 'd': proto_tree_add_item(tree, hf_copydata, tvb, n, length-n+1, ENC_NA); break; /* Function call response */ case 'V': siz = tvb_get_ntohl(tvb, n); proto_tree_add_int(tree, hf_val_length, tvb, n, 4, siz); if (siz > 0) proto_tree_add_item(tree, hf_val_data, tvb, n+4, siz, ENC_NA); break; } }
/* * It appears that browser announcements sent to \MAILSLOT\LANMAN aren't * the same as browser announcements sent to \MAILSLOT\BROWSE. * Was that an older version of the protocol? * * The document at * * http://www.samba.org/samba/ftp/specs/brow_rev.txt * * gives both formats of host announcement packets, saying that * "[The first] format seems wrong", that one being what appears to * show up in \MAILSLOT\LANMAN packets, and that "[The second one] * may be better", that one being what appears to show up in * \MAILSLOT\BROWSE packets. * * XXX - what other browser packets go out to that mailslot? */ static void dissect_mailslot_lanman(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; const guint8 *host_name; guint8 os_major_ver, os_minor_ver; const gchar *windows_version; guint namelen; 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")); if (parent_tree) { 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; /* server type flags */ offset = dissect_smb_server_type_flags( tvb, offset, pinfo, tree, NULL, TRUE); /* OS version string (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); proto_tree_add_string(tree, hf_windows_version, tvb, offset, 2, 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; /* periodicity (in seconds; convert to milliseconds) */ periodicity = tvb_get_letohs(tvb, offset)*1000; proto_tree_add_uint_format_value(tree, hf_periodicity, tvb, offset, 2, periodicity, "%s", time_msecs_to_str(wmem_packet_scope(), periodicity)); offset += 2; /* server name */ host_name = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &namelen, ENC_CP437|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", host_name); proto_tree_add_item(tree, hf_server_name, tvb, offset, namelen, ENC_ASCII|ENC_NA); offset += namelen; /* 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_CP437|ENC_NA); break; } }
static void dissect_pgsql_be_msg(guchar type, guint length, tvbuff_t *tvb, gint n, proto_tree *tree, pgsql_conn_data_t *conv_data) { guchar c; gint i, siz; char *s, *t; gint32 num_nonsupported_options; proto_item *ti; proto_tree *shrub; guint32 auth_type; switch (type) { /* Authentication request */ case 'R': proto_tree_add_item_ret_uint(tree, hf_authtype, tvb, n, 4, ENC_BIG_ENDIAN, &auth_type); switch (auth_type) { case PGSQL_AUTH_TYPE_CRYPT: case PGSQL_AUTH_TYPE_MD5: n += 4; siz = (auth_type == PGSQL_AUTH_TYPE_CRYPT ? 2 : 4); proto_tree_add_item(tree, hf_salt, tvb, n, siz, ENC_NA); break; case PGSQL_AUTH_TYPE_GSSAPI_SSPI_CONTINUE: conv_data->auth_state = PGSQL_AUTH_GSSAPI_SSPI_DATA; proto_tree_add_item(tree, hf_gssapi_sspi_data, tvb, n, length-8, ENC_NA); break; case PGSQL_AUTH_TYPE_SASL: conv_data->auth_state = PGSQL_AUTH_SASL_REQUESTED; n += 4; while ((guint)n < length) { siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_sasl_auth_mech, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; } break; case PGSQL_AUTH_TYPE_SASL_CONTINUE: case PGSQL_AUTH_TYPE_SASL_COMPLETE: conv_data->auth_state = PGSQL_AUTH_SASL_CONTINUE; n += 4; if ((guint)n < length) { proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, length-8, ENC_NA); } break; } break; /* Key data */ case 'K': proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_key, tvb, n+4, 4, ENC_BIG_ENDIAN); break; /* Parameter status */ case 'S': s = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n, &siz, ENC_ASCII); proto_tree_add_string(tree, hf_parameter_name, tvb, n, siz, s); n += siz; t = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n, &i, ENC_ASCII); proto_tree_add_string(tree, hf_parameter_value, tvb, n, i, t); break; /* Parameter description */ case 't': i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameters: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; } break; /* Row description */ case 'T': i = tvb_get_ntohs(tvb, n); ti = proto_tree_add_item(tree, hf_field_count, tvb, n, 2, ENC_BIG_ENDIAN); shrub = proto_item_add_subtree(ti, ett_values); n += 2; while (i-- > 0) { proto_tree *twig; siz = tvb_strsize(tvb, n); ti = proto_tree_add_item(shrub, hf_val_name, tvb, n, siz, ENC_ASCII|ENC_NA); twig = proto_item_add_subtree(ti, ett_values); n += siz; proto_tree_add_item(twig, hf_tableoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; proto_tree_add_item(twig, hf_val_idx, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; proto_tree_add_item(twig, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; proto_tree_add_item(twig, hf_val_length, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; proto_tree_add_item(twig, hf_val_mod, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; proto_tree_add_item(twig, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } break; /* Data row */ case 'D': i = tvb_get_ntohs(tvb, n); ti = proto_tree_add_item(tree, hf_field_count, tvb, n, 2, ENC_BIG_ENDIAN); shrub = proto_item_add_subtree(ti, ett_values); n += 2; while (i-- > 0) { siz = tvb_get_ntohl(tvb, n); proto_tree_add_int(shrub, hf_val_length, tvb, n, 4, siz); n += 4; if (siz > 0) { proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA); n += siz; } } break; /* Command completion */ case 'C': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_tag, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Ready */ case 'Z': proto_tree_add_item(tree, hf_status, tvb, n, 1, ENC_BIG_ENDIAN); break; /* Error, Notice */ case 'E': case 'N': length -= 4; while ((signed)length > 0) { c = tvb_get_guint8(tvb, n); if (c == '\0') break; s = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n+1, &siz, ENC_ASCII); i = hf_text; switch (c) { case 'S': i = hf_severity; break; case 'C': i = hf_code; break; case 'M': i = hf_message; break; case 'D': i = hf_detail; break; case 'H': i = hf_hint; break; case 'P': i = hf_position; break; case 'p': i = hf_internal_position; break; case 'q': i = hf_internal_query; break; case 'W': i = hf_where; break; case 's': i = hf_schema_name; break; case 't': i = hf_table_name; break; case 'c': i = hf_column_name; break; case 'd': i = hf_type_name; break; case 'n': i = hf_constraint_name; break; case 'F': i = hf_file; break; case 'L': i = hf_line; break; case 'R': i = hf_routine; break; } proto_tree_add_string(tree, i, tvb, n, siz+1, s); length -= siz+1; n += siz+1; } break; /* NOTICE response */ case 'A': proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_condition, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; siz = tvb_strsize(tvb, n); if (siz > 1) proto_tree_add_item(tree, hf_text, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Copy in/out */ case 'G': case 'H': proto_tree_add_item(tree, hf_format, tvb, n, 1, ENC_BIG_ENDIAN); n += 1; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Columns: %d", i); n += 2; while (i-- > 2) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } break; /* Copy data */ case 'd': proto_tree_add_item(tree, hf_copydata, tvb, n, length-n+1, ENC_NA); break; /* Function call response */ case 'V': siz = tvb_get_ntohl(tvb, n); proto_tree_add_int(tree, hf_val_length, tvb, n, 4, siz); if (siz > 0) proto_tree_add_item(tree, hf_val_data, tvb, n+4, siz, ENC_NA); break; /* Negotiate Protocol Version */ case 'v': proto_tree_add_item(tree, hf_supported_minor_version, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; proto_tree_add_item_ret_int(tree, hf_number_nonsupported_options, tvb, n, 4, ENC_BIG_ENDIAN, &num_nonsupported_options); n += 4; while (num_nonsupported_options > 0) { siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_nonsupported_option, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; num_nonsupported_options--; } break; } }
static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, gint n, proto_tree *tree, pgsql_conn_data_t *conv_data) { guchar c; gint i, siz; char *s; proto_tree *shrub; gint32 data_length; switch (type) { /* Password, SASL or GSSAPI Response, depending on context */ case 'p': switch(conv_data->auth_state) { case PGSQL_AUTH_SASL_REQUESTED: /* SASLInitResponse */ siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_sasl_auth_mech, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; proto_tree_add_item_ret_int(tree, hf_sasl_auth_data_length, tvb, n, 4, ENC_BIG_ENDIAN, &data_length); n += 4; if (data_length) { proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, data_length, ENC_NA); n += data_length; } break; case PGSQL_AUTH_SASL_CONTINUE: proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, length-4, ENC_NA); break; case PGSQL_AUTH_GSSAPI_SSPI_DATA: proto_tree_add_item(tree, hf_gssapi_sspi_data, tvb, n, length-4, ENC_NA); break; default: siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_passwd, tvb, n, siz, ENC_ASCII|ENC_NA); break; } break; /* Simple query */ case 'Q': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_query, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Parse */ case 'P': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_statement, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_query, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameters: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; } break; /* Bind */ case 'B': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_portal, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_statement, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter formats: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter values: %d", i); n += 2; while (i-- > 0) { siz = tvb_get_ntohl(tvb, n); proto_tree_add_int(shrub, hf_val_length, tvb, n, 4, siz); n += 4; if (siz > 0) { proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA); n += siz; } } i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Result formats: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } break; /* Execute */ case 'E': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_portal, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; i = tvb_get_ntohl(tvb, n); if (i == 0) proto_tree_add_uint_format_value(tree, hf_return, tvb, n, 4, i, "all rows"); else proto_tree_add_uint_format_value(tree, hf_return, tvb, n, 4, i, "%d rows", i); break; /* Describe, Close */ case 'D': case 'C': c = tvb_get_guint8(tvb, n); if (c == 'P') i = hf_portal; else i = hf_statement; n += 1; s = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n, &siz, ENC_ASCII); proto_tree_add_string(tree, i, tvb, n, siz, s); break; /* Messages without a type identifier */ case '\0': i = tvb_get_ntohl(tvb, n); n += 4; length -= n; switch (i) { /* Startup message */ case 196608: proto_tree_add_item(tree, hf_version_major, tvb, n-4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_version_minor, tvb, n-2, 2, ENC_BIG_ENDIAN); while ((signed)length > 0) { siz = tvb_strsize(tvb, n); length -= siz; if ((signed)length <= 0) { break; } proto_tree_add_item(tree, hf_parameter_name, tvb, n, siz, ENC_ASCII|ENC_NA); i = tvb_strsize(tvb, n+siz); proto_tree_add_item(tree, hf_parameter_value, tvb, n + siz, i, ENC_ASCII|ENC_NA); length -= i; n += siz+i; if (length == 1 && tvb_get_guint8(tvb, n) == 0) break; } break; /* SSL request */ case 80877103: /* Next reply will be a single byte. */ conv_data->ssl_requested = TRUE; break; /* Cancellation request */ case 80877102: proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_key, tvb, n+4, 4, ENC_BIG_ENDIAN); break; } break; /* Copy data */ case 'd': proto_tree_add_item(tree, hf_copydata, tvb, n, length-n+1, ENC_NA); break; /* Copy failure */ case 'f': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_error, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Function call */ case 'F': proto_tree_add_item(tree, hf_oid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter formats: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter values: %d", i); n += 2; while (i-- > 0) { siz = tvb_get_ntohl(tvb, n); proto_tree_add_item(shrub, hf_val_length, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; if (siz > 0) { proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA); n += siz; } } proto_tree_add_item(tree, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); break; } }
tvb, 0, 4, marker); /* all the rest of the packet is just text */ offset = 4; /* * XXX - is there ever more than one null-terminated string in * the packet? * * XXX - is the string guaranteed to be null-terminated (so * that if there's no NUL at the end, it's an error)? * * XXX - are non-ASCII characters supported and, if so, what * encoding is used for them? */ text = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII|ENC_NA); if (cl_tree) { text_item = proto_tree_add_string(cl_tree, hf_quake3_connectionless_text, tvb, offset, len, text); text_tree = proto_item_add_subtree(text_item, ett_quake3_connectionless_text); } command = COMMAND_UNKNOWN; command_len = 0; if (strncmp(text, "statusResponse", 14) == 0) { command = COMMAND_statusResponse; *direction = DIR_S2C; command_len = 14; }
/* Process an APP1 block. * * XXX - This code only works on US-ASCII systems!!! */ static int process_app1_segment(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, guint32 len, guint16 marker, const char *marker_name, gboolean show_first_identifier_not_jfif) { proto_item *ti; proto_tree *subtree; 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_stringz_enc(wmem_packet_scope(), tvb, offset, &str_size, ENC_ASCII); ti = proto_tree_add_item(subtree, hf_identifier, tvb, offset, str_size, ENC_ASCII|ENC_NA); offset += str_size; if (show_first_identifier_not_jfif && strcmp(str, "JFIF") != 0) { expert_add_info_format(pinfo, ti, &ei_file_jpeg_first_identifier_not_jfif, "Initial App0 segment with \"JFIF\" Identifier not found"); } 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_const(tag, vals_exif_tags, "Unknown Exif tag"), type, val_to_str_const(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; }
static void dissect_rsh(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 *rsh_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; rsh_hash_entry_t *hash_info; conversation = find_or_create_conversation(pinfo); /* Retrieve information from conversation * or add it if it isn't there yet */ hash_info = (rsh_hash_entry_t *)conversation_get_proto_data(conversation, proto_rsh); if(!hash_info){ hash_info = wmem_new(wmem_file_scope(), rsh_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->client_username=NULL; hash_info->server_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_rsh, 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, "RSH"); /* First, clear the info column */ col_clear(pinfo->cinfo, COL_INFO); /* Client username */ if(hash_info->client_username && preference_info_show_client_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Client username:%s ", hash_info->client_username); } /* Server username */ if(hash_info->server_username && preference_info_show_server_username == TRUE){ col_append_fstr(pinfo->cinfo, COL_INFO, "Server username:%s ", hash_info->server_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_rsh, tvb, 0, -1, ENC_NA); rsh_tree = proto_item_add_subtree(ti, ett_rsh); /* 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_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII); /* 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 || (isdigit_string(field_stringz) && length <= RSH_STDERR_PORT_LEN)){ proto_tree_add_string(rsh_tree, hf_rsh_stderr_port, tvb, offset, length, (gchar*)field_stringz); /* Next field we need */ hash_info->state = WAIT_FOR_CLIENT_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_CLIENT_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII); /* Check if this looks like the username field */ if(length != 1 && length <= RSH_CLIENT_USERNAME_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_client_username, tvb, offset, length, (gchar*)field_stringz); /* Store the client username so we can display it in the * info column of the entire conversation */ if(!hash_info->client_username){ hash_info->client_username=wmem_strdup(wmem_file_scope(), (gchar*)field_stringz); } /* Next field we need */ hash_info->state = WAIT_FOR_SERVER_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_SERVER_USERNAME && tvb_length_remaining(tvb, offset)){ field_stringz = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII); /* Check if this looks like the password field */ if(length != 1 && length <= RSH_SERVER_USERNAME_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_server_username, tvb, offset, length, (gchar*)field_stringz); /* Store the server username so we can display it in the * info column of the entire conversation */ if(!hash_info->server_username){ hash_info->server_username=wmem_strdup(wmem_file_scope(), (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_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII); /* Check if this looks like the command field */ if(length != 1 && length <= RSH_COMMAND_LEN && isprint_string(field_stringz)){ proto_tree_add_string(rsh_tree, hf_rsh_command, tvb, offset, length, (gchar*)field_stringz); /* Store the command so we can display it in the * info column of the entire conversation */ if(!hash_info->command){ hash_info->command=wmem_strdup(wmem_file_scope(), (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 == RSH_PORT){ /* Packet going to the server */ /* offset = 0 since the whole packet is data */ proto_tree_add_text(rsh_tree, tvb, 0, -1, "Client -> Server Data"); 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(rsh_tree, tvb, 0, -1, "Server -> Client Data"); 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 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(pinfo, ti, &ei_mongo_document_recursion_exceeded, "BSON document recursion exceeds %u", BSON_MAX_NESTING); /* return the number of bytes we consumed, these are at least the 4 bytes for the length field */ return MAX(4, document_length); } if (document_length < 5) { expert_add_info_format(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too short: %u", document_length); return MAX(4, document_length); /* see the comment above */ } if (document_length > BSON_MAX_DOC_SIZE) { expert_add_info_format(pinfo, ti, &ei_mongo_document_length_bad, "BSON document length too long: %u", document_length); return document_length; } if (document_length == 5) { /* document with length 5 is an empty document */ /* don't display the element subtree */ proto_tree_add_item(doc_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; /* 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_stringz_enc(wmem_packet_scope(), tvb, offset+1, &str_len, ENC_ASCII); 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_stringz_enc(wmem_packet_scope(), tvb, offset, &str_len, ENC_ASCII); 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_stringz_enc(wmem_packet_scope(), tvb, offset, &str_len, ENC_ASCII); 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_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_reported_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_stringz_enc(wmem_packet_scope(), tvb, 0x14, &str_len, ENC_ASCII); 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_reported_length_remaining(tvb,0x34 + 8*i) > 6) && (i<32)) { proto_tree_add_item(network_tree, hf_turbocell_station, 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_reported_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_item(subframe_tree, hf_turbocell_aggregate_msdu_len, next_tvb, msdu_offset, 2, ENC_LITTLE_ENDIAN); 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; guint8 *host_name; gint namelen; guint8 server_count; guint8 os_major_ver, os_minor_ver; const gchar *windows_version; 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_value(tree, hf_periodicity, tvb, offset, 4, periodicity, "%s", time_msecs_to_str(wmem_packet_scope(), periodicity)); offset += 4; /* server name */ host_name = tvb_get_stringzpad(wmem_packet_scope(), tvb, offset, HOST_NAME_LEN, ENC_CP437|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", host_name); proto_tree_add_string_format(tree, hf_server_name, tvb, offset, HOST_NAME_LEN, host_name, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? "Domain/Workgroup: %s": "Host Name: %s", host_name); offset += HOST_NAME_LEN; /* 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); proto_tree_add_string(tree, hf_windows_version, tvb, offset, 2, 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_item(tree, hf_mysterious_field, tvb, offset, 4, ENC_LITTLE_ENDIAN); 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_stringz_enc(wmem_packet_scope(), tvb, offset, &namelen, ENC_ASCII); 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_value(tree, hf_server_uptime, tvb, offset, 4, uptime, "%s", time_msecs_to_str(wmem_packet_scope(), 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: { static const int * flags[] = { &hf_mb_reset_demote, &hf_mb_reset_flush, &hf_mb_reset_stop, NULL }; proto_tree_add_bitmask(tree, tvb, offset, hf_mb_reset_command, ett_browse_reset_cmd_flags, flags, ENC_NA); 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; } }
/* 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; proto_tree *subtree; proto_tree *subtree_details = NULL; guint32 offset; char *str; gint str_size; guint16 x, y; 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_stringz_enc(wmem_packet_scope(), tvb, 4, &str_size, ENC_ASCII); 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); x = tvb_get_guint8(tvb, 16); 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); /* XXX - dissect the extension based on its extension code */ offset = 10; } else { /* Unknown */ proto_item_append_text(ti, " (unknown identifier)"); offset = 4 + str_size; proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, offset, -1, NULL, "%u bytes", len - 2 - str_size); } return offset; }
static void dissect_pgsql_fe_msg(guchar type, guint length, tvbuff_t *tvb, gint n, proto_tree *tree) { guchar c; gint i, siz; char *s; proto_tree *shrub; switch (type) { /* Password */ case 'p': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_passwd, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Simple query */ case 'Q': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_query, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Parse */ case 'P': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_statement, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_query, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameters: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; } break; /* Bind */ case 'B': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_portal, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_statement, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter formats: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter values: %d", i); n += 2; while (i-- > 0) { siz = tvb_get_ntohl(tvb, n); proto_tree_add_int(shrub, hf_val_length, tvb, n, 4, siz); n += 4; if (siz > 0) { proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA); n += siz; } } i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Result formats: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } break; /* Execute */ case 'E': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_portal, tvb, n, siz, ENC_ASCII|ENC_NA); n += siz; i = tvb_get_ntohl(tvb, n); if (i == 0) proto_tree_add_uint_format_value(tree, hf_return, tvb, n, 4, i, "all rows"); else proto_tree_add_uint_format_value(tree, hf_return, tvb, n, 4, i, "%d rows", i); break; /* Describe, Close */ case 'D': case 'C': c = tvb_get_guint8(tvb, n); if (c == 'P') i = hf_portal; else i = hf_statement; n += 1; s = tvb_get_stringz_enc(wmem_packet_scope(), tvb, n, &siz, ENC_ASCII); proto_tree_add_string(tree, i, tvb, n, siz, s); break; /* Messages without a type identifier */ case '\0': i = tvb_get_ntohl(tvb, n); n += 4; length -= n; switch (i) { /* Startup message */ case 196608: while ((signed)length > 0) { siz = tvb_strsize(tvb, n); length -= siz; if ((signed)length <= 0) { break; } proto_tree_add_item(tree, hf_parameter_name, tvb, n, siz, ENC_ASCII|ENC_NA); i = tvb_strsize(tvb, n+siz); proto_tree_add_item(tree, hf_parameter_value, tvb, n + siz, i, ENC_ASCII|ENC_NA); length -= i; n += siz+i; if (length == 1 && tvb_get_guint8(tvb, n) == 0) break; } break; /* SSL request */ case 80877103: /* There's nothing to parse here, but what do we do if the SSL negotiation succeeds? */ break; /* Cancellation request */ case 80877102: proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_key, tvb, n+4, 4, ENC_BIG_ENDIAN); break; } break; /* Copy data */ case 'd': proto_tree_add_item(tree, hf_copydata, tvb, n, length-n+1, ENC_NA); break; /* Copy failure */ case 'f': siz = tvb_strsize(tvb, n); proto_tree_add_item(tree, hf_error, tvb, n, siz, ENC_ASCII|ENC_NA); break; /* Function call */ case 'F': proto_tree_add_item(tree, hf_oid, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter formats: %d", i); n += 2; while (i-- > 0) { proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); n += 2; } i = tvb_get_ntohs(tvb, n); shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL, "Parameter values: %d", i); n += 2; while (i-- > 0) { siz = tvb_get_ntohl(tvb, n); proto_tree_add_item(shrub, hf_val_length, tvb, n, 4, ENC_BIG_ENDIAN); n += 4; if (siz > 0) { proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA); n += siz; } } proto_tree_add_item(tree, hf_format, tvb, n, 2, ENC_BIG_ENDIAN); 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, packet_info *pinfo, guint32 len, guint16 marker, const char *marker_name, gboolean show_first_identifier_not_jfif) { proto_item *ti; proto_tree *subtree; char *str; gint str_size; int offset = 0; int tiff_start; 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_stringz_enc(wmem_packet_scope(), tvb, offset, &str_size, ENC_ASCII); ti = proto_tree_add_item(subtree, hf_identifier, tvb, offset, str_size, ENC_ASCII|ENC_NA); offset += str_size; if (show_first_identifier_not_jfif && strcmp(str, "JFIF") != 0) { expert_add_info(pinfo, ti, &ei_file_jpeg_first_identifier_not_jfif); } if (strcmp(str, "Exif") == 0) { /* * Endianness */ int encoding; guint16 val_16; guint32 val_32, num_fields; proto_item* tiff_item; offset++; /* Skip a byte supposed to be 0x00 */ tiff_start = offset; val_16 = tvb_get_ntohs(tvb, offset); if (val_16 == 0x4949) { encoding = ENC_LITTLE_ENDIAN; proto_tree_add_uint_format_value(subtree, hf_endianness, tvb, offset, 2, val_16, "little endian"); } else if (val_16 == 0x4D4D) { encoding = ENC_BIG_ENDIAN; proto_tree_add_uint_format_value(subtree, hf_endianness, tvb, offset, 2, val_16, "big endian"); } else { /* Error: invalid endianness encoding */ proto_tree_add_uint_format_value(subtree, hf_endianness, tvb, offset, 2, val_16, "Incorrect encoding 0x%04x- skipping the remainder of this application marker", val_16); return offset; } offset += 2; /* * Fixed value 42 = 0x002a */ offset += 2; /* * Offset to IFD */ val_32 = tvb_get_guint32(tvb, offset, encoding); tiff_item = proto_tree_add_uint_format_value(subtree, hf_start_ifd_offset, tvb, offset, 4, val_32, "%u bytes", val_32); offset += 4; /* * 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) { expert_add_info_format(pinfo, tiff_item, &ei_start_ifd_offset, " (bogus, should be >= %u)", offset- tiff_start); return offset; } /* * Skip the following portion */ if (val_32 + tiff_start > (guint32)offset) { proto_tree_add_bytes_format_value(subtree, hf_skipped_tiff_data, tvb, offset, val_32 + tiff_start - offset, NULL, "%u bytes", val_32 + tiff_start - offset); } for (;;) { offset = val_32 + tiff_start; /* * Process the IFD */ proto_tree_add_item_ret_uint(subtree, hf_ifd_num_fields, tvb, offset, 2, encoding, &num_fields); offset += 2; while (num_fields-- > 0) { proto_tree_add_item(subtree, hf_idf_tag, tvb, offset, 2, encoding); offset += 2; proto_tree_add_item(subtree, hf_idf_type, tvb, offset, 2, encoding); offset += 2; proto_tree_add_item(subtree, hf_idf_count, tvb, offset, 4, encoding); offset += 4; proto_tree_add_item(subtree, hf_idf_offset, tvb, offset, 4, encoding); offset += 4; } /* * Offset to the next IFD */ val_32 = tvb_get_guint32(tvb, offset, encoding); tiff_item = proto_tree_add_uint_format_value(subtree, hf_next_ifd_offset, tvb, offset, 4, val_32, "%u bytes", val_32); offset += 4; if (val_32 != 0 && val_32 + tiff_start < (guint32)offset) { expert_add_info_format(pinfo, tiff_item, &ei_next_ifd_offset, " (bogus, should be >= %u)", offset + tiff_start); return offset; } if (val_32 == 0) break; } } else { proto_tree_add_bytes_format_value(subtree, hf_remain_seg_data, tvb, offset, -1, NULL, "%u bytes", len - 2 - str_size); proto_item_append_text(ti, " (Unknown identifier)"); } return offset; }
static gint dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *arg0_item; proto_tree *arg0_tree; proto_item *arg1_item; proto_tree *arg1_tree; proto_item *magic_item; proto_item *crc_item; proto_tree *crc_tree = NULL; proto_item *sub_item; gint offset = 0; guint32 command; guint32 arg0; guint32 arg1; guint32 data_length = 0; guint32 crc32 = 0; usb_conv_info_t *usb_conv_info = NULL; wmem_tree_key_t key[5]; guint32 interface_id; guint32 bus_id; guint32 device_address; guint32 side_id; guint32 frame_number; gboolean is_command = TRUE; gboolean is_next_fragment = FALSE; gboolean is_service = FALSE; gint proto; gint direction = P2P_DIR_UNKNOWN; wmem_tree_t *wmem_tree; command_data_t *command_data = NULL; service_data_t *service_data = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ADB"); col_clear(pinfo->cinfo, COL_INFO); main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_adb); frame_number = pinfo->fd->num; /* XXX: Why? If interface is USB only first try is correct * (and seems strange...), in other cases standard check for * previous protocol is correct */ proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers)))); if (proto != proto_usb) { proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))); } if (proto == proto_usb) { usb_conv_info = (usb_conv_info_t *) data; DISSECTOR_ASSERT(usb_conv_info); direction = usb_conv_info->direction; } else if (proto == proto_tcp) { if (pinfo->destport == ADB_TCP_PORT) direction = P2P_DIR_SENT; else direction = P2P_DIR_RECV; } else { return offset; } if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) interface_id = pinfo->phdr->interface_id; else interface_id = 0; if (proto == proto_usb) { bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[1].key = &bus_id; key[2].length = 1; key[2].key = &device_address; key[3].length = 0; key[3].key = NULL; } else { /* tcp */ key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[2].length = 1; if (direction == P2P_DIR_SENT) { key[1].key = &pinfo->srcport; key[2].key = &pinfo->destport; } else { key[1].key = &pinfo->destport; key[2].key = &pinfo->srcport; } key[3].length = 0; key[3].key = NULL; } wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); if (wmem_tree) { command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (command_data && command_data->completed_in_frame >= frame_number && command_data->command_in_frame <= frame_number) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if (direction == P2P_DIR_SENT) if (command_data->command == A_CLSE) side_id = command_data->arg1; /* OUT: local id */ else side_id = command_data->arg0; /* OUT: local id */ else if (command_data->command == A_OKAY) { side_id = command_data->arg1; /* IN: remote id */ } else side_id = command_data->arg1; /* IN: remote id */ key[3].length = 1; key[3].key = &side_id; key[4].length = 0; key[4].key = NULL; wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key); if (wmem_tree) { service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number); if (service_data && command_data->command == A_OPEN) { is_service = TRUE; } } } } /* Simple heuristics to check if packet is command or data */ if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) { if (tvb_reported_length(tvb) < 24) { is_command = FALSE; } else if (tvb_reported_length(tvb) >= 24) { command = tvb_get_letohl(tvb, offset); if (command != A_SYNC && command != A_CLSE && command != A_WRTE && command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY) is_command = FALSE; else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20))) is_command = FALSE; if (is_command) { data_length = tvb_get_letohl(tvb, offset + 12); crc32 = tvb_get_letohl(tvb, offset + 16); } if (command == A_OPEN) is_service = TRUE; } } if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) { sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data) { sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); if (service_data->close_local_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (service_data->close_remote_in_frame < max_in_frame) { sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } } if (is_command) { proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN); command = tvb_get_letohl(tvb, offset); offset += 4; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command")); arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0); arg0 = tvb_get_letohl(tvb, offset); offset += 4; arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN); arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1); arg1 = tvb_get_letohl(tvb, offset); offset += 4; switch (command) { case A_CNXN: proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4)); break; case A_AUTH: proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown")); break; case A_OPEN: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8)); break; case A_WRTE: proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4)); break; case A_CLSE: case A_OKAY: proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4)); break; case A_SYNC: proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4)); break; } proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (data_length > 0) col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length); crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); crc32 = tvb_get_letohl(tvb, offset); offset += 4; magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN); if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) { proto_tree *expert_tree; expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic); proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4); } if (!pinfo->fd->flags.visited) save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data); offset += 4; } if (!pinfo->fd->flags.visited && command_data) { if (command_data->command_in_frame != frame_number) { is_command = FALSE; is_next_fragment = TRUE; } data_length = command_data->data_length; crc32 = command_data->crc32; if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) || (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24) ) { command_data->reassemble_data_length = command_data->data_length; command_data->completed_in_frame = frame_number; } } if (is_next_fragment && command_data) { sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command); PROTO_ITEM_SET_GENERATED(sub_item); sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length); PROTO_ITEM_SET_GENERATED(sub_item); crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32); crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc); PROTO_ITEM_SET_GENERATED(crc_item); } if (command_data && command_data->completed_in_frame != frame_number) { sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame); PROTO_ITEM_SET_GENERATED(sub_item); } if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) { guint32 crc = 0; guint32 i_offset; if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */ if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) { tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset)); command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset); if (command_data->reassemble_data_length >= command_data->data_length) command_data->completed_in_frame = frame_number; } proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA); col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment"); offset = tvb_captured_length(tvb); if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length); add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data"); adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } } else { /* full message */ for (i_offset = 0; i_offset < data_length; ++i_offset) crc += tvb_get_guint8(tvb, offset + i_offset); if (crc32 > 0 && crc32 != crc) proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1); if (is_service) { proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA); if (!pinfo->fd->flags.visited && service_data) { service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII); } col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII)); offset = tvb_captured_length(tvb); } else if (command_data && command_data->command == A_CNXN) { gchar *info; gint len; info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII); col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info); proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA); offset += len; } else { col_append_str(pinfo->cinfo, COL_INFO, "Data"); /* Decode service payload */ if (service_data) { tvbuff_t *next_tvb; adb_service_data_t adb_service_data; adb_service_data.service = service_data->service; adb_service_data.direction = direction; adb_service_data.session_key_length = 3; adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32)); adb_service_data.session_key[0] = interface_id; if (proto == proto_usb) { adb_service_data.session_key[1] = usb_conv_info->bus_id; adb_service_data.session_key[2] = usb_conv_info->device_address; } else { /* tcp */ if (direction == P2P_DIR_SENT) { adb_service_data.session_key[1] = pinfo->srcport; adb_service_data.session_key[2] = pinfo->destport; } else { adb_service_data.session_key[1] = pinfo->destport; adb_service_data.session_key[2] = pinfo->srcport; } } next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset)); call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data); } else { proto_item *data_item; gchar *data_str; data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA); data_str = tvb_format_text(tvb, offset, data_length); proto_item_append_text(data_item, ": %s", data_str); col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str); } offset = tvb_captured_length(tvb); } } } 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_stringz_enc(wmem_packet_scope(), tvb, 4, &str_size, ENC_ASCII); 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; }