From András Veres-Szentkirályi: Added cursor type decoding to MySQL dissector
[obnox/wireshark/wip.git] / epan / dissectors / packet-mysql.c
index 7ac449aebefa89308fbbd521431d5de635131146..2afee644176f7084637188033d278255aee8fdeb 100644 (file)
@@ -48,6 +48,7 @@
 
 #include <epan/dissectors/packet-tcp.h>
 #include <epan/prefs.h>
+#include <epan/expert.h>
 
 /* port for protocol registration */
 #define TCP_PORT_MySQL   3306
 #define MYSQL_RFSH_SLAVE   64  /* Reset master info and restart slave thread */
 #define MYSQL_RFSH_MASTER  128 /* Remove all bin logs in the index and truncate the index */
 
-/* MySQL operation codes */
+/* MySQL command codes */
 #define MYSQL_SLEEP               0  /* not from client */
 #define MYSQL_QUIT                1
 #define MYSQL_INIT_DB             2
 #define MYSQL_SET_OPTION          27
 #define MYSQL_STMT_FETCH          28
 
+/* MySQL cursor types */
 
-/* decoding table: opcodes */
-static const value_string mysql_opcode_vals[] = {
+#define MYSQL_CURSOR_TYPE_NO_CURSOR  0
+#define MYSQL_CURSOR_TYPE_READ_ONLY  1
+#define MYSQL_CURSOR_TYPE_FOR_UPDATE 2
+#define MYSQL_CURSOR_TYPE_SCROLLABLE 4
+
+
+/* decoding table: command */
+static const value_string mysql_command_vals[] = {
        {MYSQL_SLEEP,   "SLEEP"},
        {MYSQL_QUIT,   "Quit"},
        {MYSQL_INIT_DB,  "Use Database"},
@@ -176,6 +184,14 @@ static const value_string mysql_opcode_vals[] = {
        {0, NULL}
 };
 
+/* decoding table: exec_flags */
+static const value_string mysql_exec_flags_vals[] = {
+       {MYSQL_CURSOR_TYPE_NO_CURSOR, "Defaults"},
+       {MYSQL_CURSOR_TYPE_READ_ONLY, "Read-only cursor"},
+       {MYSQL_CURSOR_TYPE_FOR_UPDATE, "Cursor for update"},
+       {MYSQL_CURSOR_TYPE_SCROLLABLE, "Scrollable cursor"},
+       {0, NULL}
+};
 
 /* charset: pre-4.1 used the term 'charset', later changed to 'collation' */
 static const value_string mysql_charset_vals[] = {
@@ -343,6 +359,7 @@ static gboolean mysql_showquery = FALSE;
 /* expand-the-tree flags */
 static gint ett_mysql = -1;
 static gint ett_server_greeting = -1;
+static gint ett_login_request = -1;
 static gint ett_caps = -1;
 static gint ett_extcaps = -1;
 static gint ett_stat = -1;
@@ -351,80 +368,93 @@ static gint ett_refresh = -1;
 static gint ett_field_flags = -1;
 
 /* protocol fields */
-static int hf_mysql_caps= -1;
-static int hf_mysql_cap_long_password= -1;
-static int hf_mysql_cap_found_rows= -1;
-static int hf_mysql_cap_long_flag= -1;
-static int hf_mysql_cap_connect_with_db= -1;
-static int hf_mysql_cap_no_schema= -1;
-static int hf_mysql_cap_compress= -1;
-static int hf_mysql_cap_odbc= -1;
-static int hf_mysql_cap_local_files= -1;
-static int hf_mysql_cap_ignore_space= -1;
-static int hf_mysql_cap_change_user= -1;
-static int hf_mysql_cap_interactive= -1;
-static int hf_mysql_cap_ssl= -1;
-static int hf_mysql_cap_ignore_sigpipe= -1;
-static int hf_mysql_cap_transactions= -1;
-static int hf_mysql_cap_reserved= -1;
-static int hf_mysql_cap_secure_connect= -1;
-static int hf_mysql_extcaps= -1;
-static int hf_mysql_cap_multi_statements= -1;
-static int hf_mysql_cap_multi_results= -1;
-static int hf_mysql_status= -1;
-static int hf_mysql_stat_it= -1;
-static int hf_mysql_stat_ac= -1;
-static int hf_mysql_stat_mr= -1;
-static int hf_mysql_stat_mu= -1;
-static int hf_mysql_stat_bi= -1;
-static int hf_mysql_stat_ni= -1;
-static int hf_mysql_stat_cr= -1;
-static int hf_mysql_stat_lr= -1;
-static int hf_mysql_stat_dr= -1;
-static int hf_mysql_stat_bs= -1;
-static int hf_mysql_refresh= -1;
-static int hf_mysql_rfsh_grants= -1;
-static int hf_mysql_rfsh_log= -1;
-static int hf_mysql_rfsh_tables= -1;
-static int hf_mysql_rfsh_hosts= -1;
-static int hf_mysql_rfsh_status= -1;
-static int hf_mysql_rfsh_threads= -1;
-static int hf_mysql_rfsh_slave= -1;
-static int hf_mysql_rfsh_master= -1;
-static int hf_mysql_packet_length= -1;
-static int hf_mysql_packet_number= -1;
-static int hf_mysql_opcode= -1;
-static int hf_mysql_error_code= -1;
-static int hf_mysql_error_string= -1;
-static int hf_mysql_sqlstate= -1;
-static int hf_mysql_message= -1;
-static int hf_mysql_payload= -1;
-static int hf_mysql_protocol= -1;
-static int hf_mysql_version = -1;
-static int hf_mysql_max_packet= -1;
-static int hf_mysql_user= -1;
-static int hf_mysql_schema= -1;
-static int hf_mysql_thread_id = -1;
-static int hf_mysql_salt= -1;
-static int hf_mysql_salt2= -1;
-static int hf_mysql_charset= -1;
-static int hf_mysql_passwd= -1;
-static int hf_mysql_unused= -1;
-static int hf_mysql_affected_rows= -1;
-static int hf_mysql_insert_id= -1;
-static int hf_mysql_num_warn= -1;
-static int hf_mysql_thd_id= -1;
-static int hf_mysql_stmt_id= -1;
-static int hf_mysql_query= -1;
-static int hf_mysql_option= -1;
-static int hf_mysql_num_rows= -1;
-static int hf_mysql_param= -1;
-static int hf_mysql_exec_flags= -1;
-static int hf_mysql_exec_iter= -1;
-static int hf_mysql_eof= -1;
-static int hf_mysql_num_fields= -1;
-static int hf_mysql_extra= -1;
-static int hf_mysql_fld_catalog = -1;
+static int hf_mysql_caps_server = -1;
+static int hf_mysql_caps_client = -1;
+static int hf_mysql_cap_long_password = -1;
+static int hf_mysql_cap_found_rows = -1;
+static int hf_mysql_cap_long_flag = -1;
+static int hf_mysql_cap_connect_with_db = -1;
+static int hf_mysql_cap_no_schema = -1;
+static int hf_mysql_cap_compress = -1;
+static int hf_mysql_cap_odbc = -1;
+static int hf_mysql_cap_local_files = -1;
+static int hf_mysql_cap_ignore_space = -1;
+static int hf_mysql_cap_change_user = -1;
+static int hf_mysql_cap_interactive = -1;
+static int hf_mysql_cap_ssl = -1;
+static int hf_mysql_cap_ignore_sigpipe = -1;
+static int hf_mysql_cap_transactions = -1;
+static int hf_mysql_cap_reserved = -1;
+static int hf_mysql_cap_secure_connect = -1;
+static int hf_mysql_extcaps_client = -1;
+static int hf_mysql_cap_multi_statements = -1;
+static int hf_mysql_cap_multi_results = -1;
+static int hf_mysql_server_language = -1;
+static int hf_mysql_server_status = -1;
+static int hf_mysql_stat_it = -1;
+static int hf_mysql_stat_ac = -1;
+static int hf_mysql_stat_mr = -1;
+static int hf_mysql_stat_mu = -1;
+static int hf_mysql_stat_bi = -1;
+static int hf_mysql_stat_ni = -1;
+static int hf_mysql_stat_cr = -1;
+static int hf_mysql_stat_lr = -1;
+static int hf_mysql_stat_dr = -1;
+static int hf_mysql_stat_bs = -1;
+static int hf_mysql_refresh = -1;
+static int hf_mysql_rfsh_grants = -1;
+static int hf_mysql_rfsh_log = -1;
+static int hf_mysql_rfsh_tables = -1;
+static int hf_mysql_rfsh_hosts = -1;
+static int hf_mysql_rfsh_status = -1;
+static int hf_mysql_rfsh_threads = -1;
+static int hf_mysql_rfsh_slave = -1;
+static int hf_mysql_rfsh_master = -1;
+static int hf_mysql_packet_length = -1;
+static int hf_mysql_packet_number = -1;
+static int hf_mysql_request = -1;
+static int hf_mysql_command = -1;
+static int hf_mysql_error_code = -1;
+static int hf_mysql_error_string = -1;
+static int hf_mysql_sqlstate = -1;
+static int hf_mysql_message = -1;
+static int hf_mysql_payload = -1;
+static int hf_mysql_server_greeting = -1;
+static int hf_mysql_protocol = -1;
+static int hf_mysql_version  = -1;
+static int hf_mysql_login_request = -1;
+static int hf_mysql_max_packet = -1;
+static int hf_mysql_user = -1;
+static int hf_mysql_table_name = -1;
+static int hf_mysql_schema = -1;
+static int hf_mysql_thread_id  = -1;
+static int hf_mysql_salt = -1;
+static int hf_mysql_salt2 = -1;
+static int hf_mysql_charset = -1;
+static int hf_mysql_passwd = -1;
+static int hf_mysql_unused = -1;
+static int hf_mysql_affected_rows = -1;
+static int hf_mysql_insert_id = -1;
+static int hf_mysql_num_warn = -1;
+static int hf_mysql_thd_id = -1;
+static int hf_mysql_stmt_id = -1;
+static int hf_mysql_query = -1;
+static int hf_mysql_shutdown = -1;
+static int hf_mysql_option = -1;
+static int hf_mysql_num_rows = -1;
+static int hf_mysql_param = -1;
+static int hf_mysql_num_params = -1;
+static int hf_mysql_exec_flags4 = -1;
+static int hf_mysql_exec_flags5 = -1;
+static int hf_mysql_exec_iter = -1;
+static int hf_mysql_binlog_position = -1;
+static int hf_mysql_binlog_flags = -1;
+static int hf_mysql_binlog_server_id = -1;
+static int hf_mysql_binlog_file_name = -1;
+static int hf_mysql_eof = -1;
+static int hf_mysql_num_fields = -1;
+static int hf_mysql_extra = -1;
+static int hf_mysql_fld_catalog  = -1;
 static int hf_mysql_fld_db = -1;
 static int hf_mysql_fld_table = -1;
 static int hf_mysql_fld_org_table = -1;
@@ -495,7 +525,8 @@ typedef enum mysql_state
        FIELD_PACKET,
        ROW_PACKET,
        RESPONSE_PREPARE,
-       PARAM_PACKET
+    PREPARED_PARAMETERS,
+    PREPARED_FIELDS
 } mysql_state_t;
 
 #ifdef CTDEBUG
@@ -510,7 +541,8 @@ static const value_string state_vals[] = {
        {FIELD_PACKET,         "field packet"},
        {ROW_PACKET,           "row packet"},
        {RESPONSE_PREPARE,     "response to PREPARE"},
-       {PARAM_PACKET,         "parameter packet"},
+       {RESPONSE_PARAMETERS,  "parameters in response to PREPARE"},
+       {RESPONSE_FIELDS,      "fields in response to PREPARE"},
        {0, NULL}
 };
 #endif
@@ -521,10 +553,13 @@ typedef struct mysql_conn_data
        guint16 clnt_caps;
        guint16 clnt_caps_ext;
        mysql_state_t state;
+       guint16 stmt_num_params;
+       guint16 stmt_num_fields;
        GHashTable* stmts;
 #ifdef CTDEBUG
        guint32 generation;
 #endif
+       guint8 major_version;
 } mysql_conn_data_t;
 
 struct mysql_frame_data {
@@ -548,14 +583,13 @@ static int mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo, int offset,
 static int mysql_dissect_error_packet(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
 static int mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
 static int mysql_dissect_server_status(tvbuff_t *tvb, int offset, proto_tree *tree);
-static void mysql_dissect_collation(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 caps, gint charset, int field);
-static int mysql_dissect_caps(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps, const char* whom);
-static int mysql_dissect_ext_caps(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps, const char* whom);
+static int mysql_dissect_caps_server(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps);
+static int mysql_dissect_caps_client(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps);
+static int mysql_dissect_ext_caps_client(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps);
 static int mysql_dissect_result_header(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
 static int mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
 static int mysql_dissect_row_packet(tvbuff_t *tvb, int offset, proto_tree *tree);
-static int mysql_dissect_response_prepare(tvbuff_t *tvb, int offset, proto_tree *tree);
-static int mysql_dissect_param_packet(tvbuff_t *tvb, int offset, proto_tree *tree);
+static int mysql_dissect_response_prepare(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data);
 static gint my_tvb_strsize(tvbuff_t *tvb, int offset);
 static int tvb_get_fle(tvbuff_t *tvb, int offset, guint64 *res, guint8 *is_null);
 
@@ -609,6 +643,7 @@ dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 #ifdef CTDEBUG
                conn_data->generation= 0;
 #endif
+                conn_data->major_version= 0;
                conversation_add_proto_data(conversation, proto_mysql, conn_data);
        }
 
@@ -683,18 +718,18 @@ dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if (is_response) {
                if (packet_number == 0) {
                        col_set_str(pinfo->cinfo, COL_INFO, "Server Greeting");
-                       offset= mysql_dissect_greeting(tvb, pinfo, offset, mysql_tree, conn_data);
+                       offset = mysql_dissect_greeting(tvb, pinfo, offset, mysql_tree, conn_data);
                } else {
                        col_set_str(pinfo->cinfo, COL_INFO, "Response");
-                       offset= mysql_dissect_response(tvb, pinfo, offset, mysql_tree, conn_data);
+                       offset = mysql_dissect_response(tvb, pinfo, offset, mysql_tree, conn_data);
                }
        } else {
                if (packet_number == 1) {
                        col_set_str(pinfo->cinfo, COL_INFO, "Login Request");
-                       offset= mysql_dissect_login(tvb, pinfo, offset, mysql_tree, conn_data);
+                       offset = mysql_dissect_login(tvb, pinfo, offset, mysql_tree, conn_data);
                } else {
                        col_set_str(pinfo->cinfo, COL_INFO, "Request");
-                       offset= mysql_dissect_request(tvb, pinfo, offset, mysql_tree, conn_data);
+                       offset = mysql_dissect_request(tvb, pinfo, offset, mysql_tree, conn_data);
                }
        }
 
@@ -709,8 +744,8 @@ dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        /* remaining payload indicates an error */
        if (tree && tvb_reported_length_remaining(tvb, offset) > 0) {
-               proto_tree_add_string(mysql_tree, hf_mysql_payload, tvb, offset, -1,
-                                     "FIXME - dissector is incomplete");
+               ti = proto_tree_add_item(mysql_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
+               expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, "FIXME - dissector is incomplete");
        }
 }
 
@@ -721,6 +756,7 @@ mysql_dissect_greeting(tvbuff_t *tvb, packet_info *pinfo, int offset,
 {
        gint protocol;
        gint strlen;
+       int ver_offset;
 
        proto_item *tf;
        proto_item *greeting_tree= NULL;
@@ -734,15 +770,15 @@ mysql_dissect_greeting(tvbuff_t *tvb, packet_info *pinfo, int offset,
        conn_data->state= LOGIN;
 
        if (tree) {
-               tf= proto_tree_add_text(tree, tvb, offset, -1, "Server Greeting");
-               greeting_tree= proto_item_add_subtree(tf, ett_server_greeting);
+               tf = proto_tree_add_item(tree, hf_mysql_server_greeting, tvb, offset, -1, ENC_NA);
+               greeting_tree = proto_item_add_subtree(tf, ett_server_greeting);
        }
 
        if (check_col(pinfo->cinfo, COL_INFO)) {
                col_append_fstr(pinfo->cinfo, COL_INFO, " proto=%d", protocol) ;
        }
        proto_tree_add_item(greeting_tree, hf_mysql_protocol, tvb, offset, 1, ENC_NA);
-       
+
        offset += 1;
 
        /* version string */
@@ -751,6 +787,12 @@ mysql_dissect_greeting(tvbuff_t *tvb, packet_info *pinfo, int offset,
                col_append_fstr(pinfo->cinfo, COL_INFO, " version=%s", tvb_get_ephemeral_string(tvb, offset, strlen));
        }
        proto_tree_add_item(greeting_tree, hf_mysql_version, tvb, offset, strlen, ENC_NA);
+       conn_data->major_version = 0;
+       for (ver_offset = 0; ver_offset < strlen; ver_offset++) {
+               guint8 ver_char = tvb_get_guint8(tvb, offset + ver_offset);
+               if (ver_char == '.') break;
+               conn_data->major_version = conn_data->major_version * 10 + ver_char - '0';
+       }
        offset += strlen;
 
        /* 4 bytes little endian thread_id */
@@ -760,19 +802,20 @@ mysql_dissect_greeting(tvbuff_t *tvb, packet_info *pinfo, int offset,
        /* salt string */
        strlen = tvb_strsize(tvb,offset);
        proto_tree_add_item(greeting_tree, hf_mysql_salt, tvb, offset, strlen, ENC_NA);
-       offset+=strlen;
+       offset += strlen;
 
        /* rest is optional */
        if (!tvb_reported_length_remaining(tvb, offset)) return offset;
 
        /* 2 bytes CAPS */
-       offset = mysql_dissect_caps(tvb, offset, greeting_tree, &conn_data->srv_caps, "Server");
+       offset = mysql_dissect_caps_server(tvb, offset, greeting_tree, &conn_data->srv_caps);
 
        /* rest is optional */
        if (!tvb_reported_length_remaining(tvb, offset)) return offset;
 
-       mysql_dissect_collation(tvb, offset, greeting_tree, conn_data->srv_caps, tvb_get_guint8(tvb, offset), hf_mysql_charset);
+       proto_tree_add_item(greeting_tree, hf_mysql_server_language, tvb, offset, 1, ENC_NA);
        offset += 1; /* for charset */
+
        offset = mysql_dissect_server_status(tvb, offset, greeting_tree);
 
        /* 13 bytes unused */
@@ -794,8 +837,7 @@ static int
 mysql_dissect_login(tvbuff_t *tvb, packet_info *pinfo, int offset,
                    proto_tree *tree, mysql_conn_data_t *conn_data)
 {
-       guint16  ext_caps;
-       gint     strlen;
+       gint strlen;
 
        proto_item *tf;
        proto_item *login_tree= NULL;
@@ -804,25 +846,23 @@ mysql_dissect_login(tvbuff_t *tvb, packet_info *pinfo, int offset,
        conn_data->state = RESPONSE_OK;
 
        if (tree) {
-               tf = proto_tree_add_text(tree, tvb, offset, -1, "Login Request");
-               login_tree = proto_item_add_subtree(tf, ett_server_greeting);
+               tf = proto_tree_add_item(tree, hf_mysql_login_request, tvb, offset, -1, ENC_NA);
+               login_tree = proto_item_add_subtree(tf, ett_login_request);
        }
 
-       offset = mysql_dissect_caps(tvb, offset, login_tree, &conn_data->clnt_caps, "Client");
+       offset = mysql_dissect_caps_client(tvb, offset, login_tree, &conn_data->clnt_caps);
 
        if (conn_data->clnt_caps & MYSQL_CAPS_CU) /* 4.1 protocol */
        {
-               offset = mysql_dissect_ext_caps(tvb, offset, login_tree, &ext_caps, "Client");
-               conn_data->clnt_caps_ext= ext_caps;
+               offset = mysql_dissect_ext_caps_client(tvb, offset, login_tree, &conn_data->clnt_caps_ext);
 
                proto_tree_add_item(login_tree, hf_mysql_max_packet, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;
 
-               mysql_dissect_collation(tvb, offset, login_tree, conn_data->clnt_caps,
-                                       tvb_get_guint8(tvb, offset), hf_mysql_charset);
-               offset++; /* for charset */
+               proto_tree_add_item(login_tree, hf_mysql_charset, tvb, offset, 1, ENC_NA);
+               offset += 1; /* for charset */
 
-               offset+= 23; /* filler bytes */
+               offset += 23; /* filler bytes */
 
        } else { /* pre-4.1 */
                proto_tree_add_item(login_tree, hf_mysql_max_packet, tvb, offset, 3, ENC_LITTLE_ENDIAN);
@@ -877,25 +917,21 @@ mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo, int offset,
 {
        gint opcode;
        gint strlen;
-       proto_item *tf;
-       proto_item *req_tree= NULL;
-       guint16 option;
+       proto_item *tf = NULL, *ti;
+       proto_item *req_tree = NULL;
 
        if (tree) {
-               tf= proto_tree_add_text(tree, tvb, offset, -1, "Command");
-               req_tree= proto_item_add_subtree(tf, ett_request);
+               tf = proto_tree_add_item(tree, hf_mysql_request, tvb, offset, 1, ENC_NA);
+               req_tree = proto_item_add_subtree(tf, ett_request);
        }
 
-       opcode= tvb_get_guint8(tvb, offset);
+       opcode = tvb_get_guint8(tvb, offset);
        if (check_col(pinfo->cinfo, COL_INFO)) {
-               col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
-                               val_to_str(opcode, mysql_opcode_vals, "Unknown (%u)"));
+               col_append_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str(opcode, mysql_command_vals, "Unknown (%u)"));
        }
-       proto_tree_add_uint_format(req_tree, hf_mysql_opcode, tvb,
-                                  offset, 1, opcode, "Command: %s (%u)",
-                                  val_to_str(opcode, mysql_opcode_vals, "Unknown (%u)"),
-                                  opcode);
-       offset+= 1;
+       proto_tree_add_item(req_tree, hf_mysql_command, tvb, offset, 1, ENC_NA);
+       proto_item_append_text(tf, " %s", val_to_str(opcode, mysql_command_vals, "Unknown (%u)"));
+       offset += 1;
 
 
        switch (opcode) {
@@ -903,102 +939,92 @@ mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo, int offset,
        case MYSQL_QUIT:
                if (conn_data->stmts) {
                        g_hash_table_destroy(conn_data->stmts);
-                       conn_data->stmts= NULL;
+                       conn_data->stmts = NULL;
                }
                break;
 
        case MYSQL_PROCESS_INFO:
-               conn_data->state= RESPONSE_TABULAR;
+               conn_data->state = RESPONSE_TABULAR;
                break;
 
        case MYSQL_DEBUG:
        case MYSQL_PING:
-               conn_data->state= RESPONSE_OK;
+               conn_data->state = RESPONSE_OK;
                break;
 
        case MYSQL_STATISTICS:
-               conn_data->state= RESPONSE_MESSAGE;
+               conn_data->state = RESPONSE_MESSAGE;
                break;
 
        case MYSQL_INIT_DB:
        case MYSQL_CREATE_DB:
        case MYSQL_DROP_DB:
-               strlen= my_tvb_strsize(tvb, offset);
-               proto_tree_add_item(req_tree, hf_mysql_schema, tvb,
-                                   offset, strlen, ENC_LITTLE_ENDIAN);
-               offset+= strlen;
-               conn_data->state= RESPONSE_OK;
+               strlen = my_tvb_strsize(tvb, offset);
+               proto_tree_add_item(req_tree, hf_mysql_schema, tvb, offset, strlen, ENC_NA);
+               offset += strlen;
+               conn_data->state = RESPONSE_OK;
                break;
 
        case MYSQL_QUERY:
-               strlen= my_tvb_strsize(tvb, offset);
-               proto_tree_add_item(req_tree, hf_mysql_query, tvb,
-                                   offset, strlen, ENC_LITTLE_ENDIAN);
+               strlen = my_tvb_strsize(tvb, offset);
+               proto_tree_add_item(req_tree, hf_mysql_query, tvb, offset, strlen, ENC_NA);
                if (mysql_showquery) {
                        if (check_col(pinfo->cinfo, COL_INFO))
-                               col_append_fstr(pinfo->cinfo, COL_INFO, " { %s } ",
-                                               tvb_get_ephemeral_string(tvb, offset, strlen));
+                               col_append_fstr(pinfo->cinfo, COL_INFO, " { %s } ", tvb_get_ephemeral_string(tvb, offset, strlen));
                }
-               offset+= strlen;
-               conn_data->state= RESPONSE_TABULAR;
+               offset += strlen;
+               conn_data->state = RESPONSE_TABULAR;
                break;
 
        case MYSQL_STMT_PREPARE:
-               strlen= my_tvb_strsize(tvb, offset);
-               proto_tree_add_item(req_tree, hf_mysql_query, tvb,
-                                   offset, strlen, ENC_LITTLE_ENDIAN);
-               offset+= strlen;
-               conn_data->state= RESPONSE_PREPARE;
+               strlen = my_tvb_strsize(tvb, offset);
+               proto_tree_add_item(req_tree, hf_mysql_query, tvb, offset, strlen, ENC_NA);
+               offset += strlen;
+               conn_data->state = RESPONSE_PREPARE;
                break;
 
        case MYSQL_STMT_CLOSE:
                if (conn_data->stmts) {
-                       gint stmt= tvb_get_letohl(tvb, offset);
+                       gint stmt = tvb_get_letohl(tvb, offset);
                        g_hash_table_remove(conn_data->stmts, &stmt);
                }
-               proto_tree_add_item(req_tree, hf_mysql_stmt_id,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
-               conn_data->state= REQUEST;
+               proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
+               conn_data->state = REQUEST;
                break;
 
        case MYSQL_STMT_RESET:
-               proto_tree_add_item(req_tree, hf_mysql_stmt_id,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
-               conn_data->state= RESPONSE_OK;
+               proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
+               conn_data->state = RESPONSE_OK;
                break;
 
        case MYSQL_FIELD_LIST:
-               strlen= my_tvb_strsize(tvb, offset);
-               proto_tree_add_text(req_tree, tvb, offset, strlen, "Table name: %s",
-                                   tvb_get_ephemeral_string(tvb, offset, strlen));
-               offset+= strlen;
-               conn_data->state= RESPONSE_SHOW_FIELDS;
+               strlen = my_tvb_strsize(tvb, offset);
+               proto_tree_add_item(req_tree, hf_mysql_table_name, tvb,  offset, strlen, ENC_NA);
+               offset += strlen;
+               conn_data->state = RESPONSE_SHOW_FIELDS;
                break;
 
        case MYSQL_PROCESS_KILL:
-               proto_tree_add_item(req_tree, hf_mysql_thd_id,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
-               conn_data->state= RESPONSE_OK;
+               proto_tree_add_item(req_tree, hf_mysql_thd_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
+               conn_data->state = RESPONSE_OK;
                break;
 
        case MYSQL_CHANGE_USER:
-               strlen= tvb_strsize(tvb, offset);
-               proto_tree_add_item(req_tree, hf_mysql_user, tvb,
-                                   offset, strlen, ENC_LITTLE_ENDIAN);
-               offset+= strlen;
-
-               strlen= tvb_strsize(tvb, offset);
-               proto_tree_add_item(req_tree, hf_mysql_passwd, tvb,
-                                   offset, strlen, ENC_LITTLE_ENDIAN);
-               offset+= strlen;
-
-               strlen= my_tvb_strsize(tvb, offset);
-               proto_tree_add_item(req_tree, hf_mysql_schema, tvb,
-                                   offset, strlen, ENC_LITTLE_ENDIAN);
-               offset+= strlen;
+               strlen = tvb_strsize(tvb, offset);
+               proto_tree_add_item(req_tree, hf_mysql_user, tvb,  offset, strlen, ENC_NA);
+               offset += strlen;
+
+               strlen = tvb_strsize(tvb, offset);
+               proto_tree_add_item(req_tree, hf_mysql_passwd, tvb, offset, strlen, ENC_NA);
+               offset += strlen;
+
+               strlen = my_tvb_strsize(tvb, offset);
+               proto_tree_add_item(req_tree, hf_mysql_schema, tvb, offset, strlen, ENC_NA);
+               offset += strlen;
+
                conn_data->state= RESPONSE_OK;
                break;
 
@@ -1006,115 +1032,121 @@ mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo, int offset,
                {
                        proto_item *tff;
                        proto_item *rfsh_tree;
-                       gint refresh= tvb_get_guint8(tvb, offset);
-
-                       if (req_tree) {
-                               tff= proto_tree_add_uint_format(req_tree, hf_mysql_refresh, tvb, offset, 1, refresh, "Refresh Bitmap: 0x%02X ", refresh);
-                               rfsh_tree= proto_item_add_subtree(tff, ett_refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_grants, tvb, offset, 1, refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_log, tvb, offset, 1, refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_tables, tvb, offset, 1, refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_hosts, tvb, offset, 1, refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_status, tvb, offset, 1, refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_threads, tvb, offset, 1, refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_slave, tvb, offset, 1, refresh);
-                               proto_tree_add_boolean(rfsh_tree, hf_mysql_rfsh_master, tvb, offset, 1, refresh);
-                       }
+
+                       tff = proto_tree_add_item(req_tree, hf_mysql_refresh, tvb, offset, 1, ENC_NA);
+                       rfsh_tree = proto_item_add_subtree(tff, ett_refresh);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_grants, tvb, offset, 1, ENC_NA);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_log, tvb, offset, 1, ENC_NA);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_tables, tvb, offset, 1, ENC_NA);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_hosts, tvb, offset, 1, ENC_NA);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_status, tvb, offset, 1, ENC_NA);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_threads, tvb, offset, 1, ENC_NA);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_slave, tvb, offset, 1, ENC_NA);
+                       proto_tree_add_item(rfsh_tree, hf_mysql_rfsh_master, tvb, offset, 1, ENC_NA);
+
                }
-               offset+= 1;
+               offset += 1;
                conn_data->state= RESPONSE_OK;
                break;
 
        case MYSQL_SHUTDOWN:
-               opcode= tvb_get_guint8(tvb, offset);
-               proto_tree_add_uint_format(req_tree, hf_mysql_opcode, tvb, offset,
-                                          1, opcode, "Shutdown-Level: %s",
-                                          val_to_str(opcode, mysql_shutdown_vals, "Unknown (%u)"));
-               offset+= 1;
-               conn_data->state= RESPONSE_OK;
+               proto_tree_add_item(req_tree, hf_mysql_shutdown, tvb, offset, 1, ENC_NA);
+               offset += 1;
+               conn_data->state = RESPONSE_OK;
                break;
 
        case MYSQL_SET_OPTION:
-               option= tvb_get_letohs(tvb, offset);
-               proto_tree_add_uint_format(req_tree, hf_mysql_option, tvb, offset,
-                                          2, option, "Option: %s",
-                                          val_to_str(option, mysql_option_vals, "Unknown (%u)"));
-               offset+= 2;
-               conn_data->state= RESPONSE_OK;
+               proto_tree_add_item(req_tree, hf_mysql_option, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               offset += 2;
+               conn_data->state = RESPONSE_OK;
                break;
 
        case MYSQL_STMT_FETCH:
-               proto_tree_add_item(req_tree, hf_mysql_stmt_id,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
+               proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
 
-               proto_tree_add_item(req_tree, hf_mysql_num_rows,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
-               conn_data->state= RESPONSE_TABULAR;
+               proto_tree_add_item(req_tree, hf_mysql_num_rows, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
+               conn_data->state = RESPONSE_TABULAR;
                break;
 
        case MYSQL_STMT_SEND_LONG_DATA:
-               proto_tree_add_item(req_tree, hf_mysql_stmt_id,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
+               proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
 
-               proto_tree_add_item(req_tree, hf_mysql_param,
-                                   tvb, offset, 2, ENC_LITTLE_ENDIAN);
-               offset+= 2;
+               proto_tree_add_item(req_tree, hf_mysql_param, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               offset += 2;
 
                /* rest is data */
-               strlen= tvb_reported_length_remaining(tvb, offset);
+               strlen = tvb_reported_length_remaining(tvb, offset);
                if (tree &&  strlen > 0) {
-                       proto_tree_add_item(req_tree, hf_mysql_payload,
-                                           tvb, offset, strlen, ENC_NA);
+                       proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, strlen, ENC_NA);
                }
-               offset+= strlen;
-               conn_data->state= REQUEST;
+               offset += strlen;
+               conn_data->state = REQUEST;
                break;
 
        case MYSQL_STMT_EXECUTE:
-               proto_tree_add_item(req_tree, hf_mysql_stmt_id,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
+               proto_tree_add_item(req_tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
 
-               proto_tree_add_item(req_tree, hf_mysql_exec_flags,
-                                   tvb, offset, 1, ENC_NA);
-               offset+= 1;
+               if (conn_data->major_version >= 5) {
+                       proto_tree_add_item(req_tree, hf_mysql_exec_flags5, tvb, offset, 1, ENC_NA);
+               } else {
+                       proto_tree_add_item(req_tree, hf_mysql_exec_flags4, tvb, offset, 1, ENC_NA);
+               }
+               offset += 1;
 
-               proto_tree_add_item(req_tree, hf_mysql_exec_iter,
-                                   tvb, offset, 4, ENC_LITTLE_ENDIAN);
-               offset+= 4;
+               proto_tree_add_item(req_tree, hf_mysql_exec_iter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
 
 #if 0
 /* FIXME: rest needs metadata about statement */
 #else
-               strlen= tvb_reported_length_remaining(tvb, offset);
+               strlen = tvb_reported_length_remaining(tvb, offset);
                if (tree &&  strlen > 0) {
-                       proto_tree_add_string(req_tree, hf_mysql_payload, tvb, offset,
-                                             strlen, "FIXME: execute dissector incomplete");
+                       ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, strlen, ENC_NA);
+                       expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, "FIXME: execute dissector incomplete");
                }
-               offset+= strlen;
+               offset += strlen;
 #endif
                conn_data->state= RESPONSE_TABULAR;
                break;
 
-/* FIXME: implement replication packets */
        case MYSQL_BINLOG_DUMP:
+               proto_tree_add_item(req_tree, hf_mysql_binlog_position, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
+
+               proto_tree_add_item(req_tree, hf_mysql_binlog_flags, tvb, offset, 2, ENC_NA);
+               offset += 2;
+
+               proto_tree_add_item(req_tree, hf_mysql_binlog_server_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+               offset += 4;
+
+               /* binlog file name ? */
+               strlen = tvb_reported_length_remaining(tvb, offset);
+               if (tree &&  strlen > 0) {
+                       proto_tree_add_item(req_tree, hf_mysql_binlog_file_name, tvb, offset, strlen, ENC_NA);
+               }
+               offset += strlen;
+
+               conn_data->state = REQUEST;
+               break;
+/* FIXME: implement replication packets */
        case MYSQL_TABLE_DUMP:
        case MYSQL_CONNECT_OUT:
        case MYSQL_REGISTER_SLAVE:
-               proto_tree_add_string(req_tree, hf_mysql_payload, tvb, offset, -1,
-                                     "FIXME: implement replication packets");
-               offset+= tvb_reported_length_remaining(tvb, offset);
-               conn_data->state= REQUEST;
+               ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
+               expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, "FIXME: implement replication packets");
+               offset += tvb_reported_length_remaining(tvb, offset);
+               conn_data->state = REQUEST;
                break;
 
        default:
-               proto_tree_add_string(req_tree, hf_mysql_payload, tvb, offset, -1,
-                                     "unknown/invalid command code");
-               offset+= tvb_reported_length_remaining(tvb, offset);
-               conn_data->state= UNDEFINED;
+               ti = proto_tree_add_item(req_tree, hf_mysql_payload, tvb, offset, -1, ENC_NA);
+               expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Unknown/invalid command code");
+               offset += tvb_reported_length_remaining(tvb, offset);
+               conn_data->state = UNDEFINED;
        }
 
        return offset;
@@ -1127,84 +1159,94 @@ mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo, int offset,
 {
        gint response_code;
        gint strlen;
+    gint server_status = 0;
 
-       response_code= tvb_get_guint8(tvb, offset);
+       response_code = tvb_get_guint8(tvb, offset);
 
        if (response_code == 0xff ) {
-               offset= mysql_dissect_error_packet(tvb, pinfo, offset+1, tree);
+               offset = mysql_dissect_error_packet(tvb, pinfo, offset+1, tree);
                conn_data->state= REQUEST;
        }
 
        else if (response_code == 0xfe && tvb_reported_length_remaining(tvb, offset) < 9) {
 
-               proto_tree_add_uint_format(tree, hf_mysql_eof, tvb, offset, 1,
-                                          response_code, "EOF marker (%u)",
-                                          response_code);
-               offset+= 1;
+               proto_tree_add_item(tree, hf_mysql_eof, tvb, offset, 1, ENC_NA);
+
+               offset += 1;
 
                /* pre-4.1 packet ends here */
                if (tvb_reported_length_remaining(tvb, offset)) {
-                       proto_tree_add_item(tree, hf_mysql_num_warn,
-                                           tvb, offset, 2, ENC_LITTLE_ENDIAN);
-                       offset= mysql_dissect_server_status(tvb, offset+2, tree);
+                       proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+                       server_status = tvb_get_letohs(tvb, offset+2);
+                       offset = mysql_dissect_server_status(tvb, offset+2, tree);
                }
 
                if (conn_data->state == FIELD_PACKET) {
                        conn_data->state= ROW_PACKET;
+               } else if (conn_data->state == ROW_PACKET) {
+                       if (server_status & MYSQL_STAT_MU) {
+                               conn_data->state= RESPONSE_TABULAR;
+                       } else {
+                               conn_data->state= REQUEST;
+                       }
+               } else if (conn_data->state == PREPARED_PARAMETERS) {
+                       if (conn_data->stmt_num_fields > 0) {
+                               conn_data->state= PREPARED_FIELDS;
+                       } else {
+                               conn_data->state= REQUEST;
+                       }
+               } else if (conn_data->state == PREPARED_FIELDS) {
+                       conn_data->state= REQUEST;
                } else {
+                       /* This should be an unreachable case */
                        conn_data->state= REQUEST;
                }
        }
 
        else if (response_code == 0) {
-               if (tvb_reported_length_remaining(tvb, offset+1)
-                   > tvb_get_fle(tvb, offset+1, NULL, NULL)) {
-                       offset= mysql_dissect_ok_packet(tvb, pinfo, offset+1,
-                                                       tree, conn_data);
+               if (conn_data->state == RESPONSE_PREPARE) {
+                       offset = mysql_dissect_response_prepare(tvb, offset, tree, conn_data);
+               } else if (tvb_reported_length_remaining(tvb, offset+1)  > tvb_get_fle(tvb, offset+1, NULL, NULL)) {
+                       offset = mysql_dissect_ok_packet(tvb, pinfo, offset+1, tree, conn_data);
                } else {
-                       offset= mysql_dissect_result_header(tvb, pinfo, offset,
-                                                           tree, conn_data);
+                       offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
                }
        }
 
        else {
                switch (conn_data->state) {
                case RESPONSE_MESSAGE:
-                       if ((strlen= tvb_reported_length_remaining(tvb, offset))) {
-                               proto_tree_add_item(tree, hf_mysql_message, tvb,
-                                                   offset, strlen, ENC_NA);
-                               offset+= strlen;
+                       if ((strlen = tvb_reported_length_remaining(tvb, offset))) {
+                               proto_tree_add_item(tree, hf_mysql_message, tvb, offset, strlen, ENC_NA);
+                               offset += strlen;
                        }
-                       conn_data->state= REQUEST;
+                       conn_data->state = REQUEST;
                        break;
 
                case RESPONSE_TABULAR:
-                       offset= mysql_dissect_result_header(tvb, pinfo, offset,
-                                                           tree, conn_data);
+                       offset = mysql_dissect_result_header(tvb, pinfo, offset, tree, conn_data);
                        break;
 
                case FIELD_PACKET:
                case RESPONSE_SHOW_FIELDS:
-                       offset= mysql_dissect_field_packet(tvb, offset, tree, conn_data);
+               case RESPONSE_PREPARE:
+               case PREPARED_PARAMETERS:
+                       offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
                        break;
 
                case ROW_PACKET:
-                       offset= mysql_dissect_row_packet(tvb, offset, tree);
+                       offset = mysql_dissect_row_packet(tvb, offset, tree);
                        break;
 
-               case RESPONSE_PREPARE:
-                       offset= mysql_dissect_response_prepare(tvb, offset, tree);
-                       break;
-
-               case PARAM_PACKET:
-                       offset= mysql_dissect_param_packet(tvb, offset, tree);
+               case PREPARED_FIELDS:
+                       offset = mysql_dissect_field_packet(tvb, offset, tree, conn_data);
                        break;
 
                default:
                        proto_tree_add_string(tree, hf_mysql_payload, tvb, offset, -1,
                                              "unknown/invalid response");
-                       offset+= tvb_reported_length_remaining(tvb, offset);
-                       conn_data->state= UNDEFINED;
+                       offset += tvb_reported_length_remaining(tvb, offset);
+                       conn_data->state = UNDEFINED;
                }
        }
 
@@ -1216,25 +1258,21 @@ static int
 mysql_dissect_error_packet(tvbuff_t *tvb, packet_info *pinfo,
                           int offset, proto_tree *tree)
 {
-       gint error_code;
-       error_code= tvb_get_letohs(tvb, offset);
-
        if (check_col(pinfo->cinfo, COL_INFO)) {
-               col_append_fstr(pinfo->cinfo, COL_INFO, " Error %d", error_code);
+               col_append_fstr(pinfo->cinfo, COL_INFO, " Error %d", tvb_get_letohs(tvb, offset));
        }
-       proto_tree_add_uint(tree, hf_mysql_error_code, tvb,
-                           offset, 2, error_code);
-       offset+= 2;
+       proto_tree_add_item(tree, hf_mysql_error_code, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       offset += 2;
 
        if (tvb_get_guint8(tvb, offset) == '#')
        {
-               offset+= 1;
+               offset += 1;
                proto_tree_add_item(tree, hf_mysql_sqlstate, tvb, offset, 5, ENC_NA);
-               offset+= 5;
+               offset += 5;
        }
 
        proto_tree_add_item(tree, hf_mysql_error_string, tvb, offset, -1, ENC_NA);
-       offset+= tvb_reported_length_remaining(tvb, offset);
+       offset += tvb_reported_length_remaining(tvb, offset);
 
        return offset;
 }
@@ -1251,37 +1289,34 @@ mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset,
 
        col_append_str(pinfo->cinfo, COL_INFO, " OK" );
 
-       fle= tvb_get_fle(tvb, offset, &affected_rows, NULL);
-       proto_tree_add_uint64(tree, hf_mysql_affected_rows,
-                             tvb, offset, fle, affected_rows);
-       offset+= fle;
+       fle = tvb_get_fle(tvb, offset, &affected_rows, NULL);
+       proto_tree_add_uint64(tree, hf_mysql_affected_rows, tvb, offset, fle, affected_rows);
+       offset += fle;
 
        fle= tvb_get_fle(tvb, offset, &insert_id, NULL);
        if (tree && insert_id) {
-               proto_tree_add_uint64(tree, hf_mysql_insert_id,
-                                     tvb, offset, fle, insert_id);
+               proto_tree_add_uint64(tree, hf_mysql_insert_id, tvb, offset, fle, insert_id);
        }
-       offset+= fle;
+       offset += fle;
 
-       if ((strlen= tvb_reported_length_remaining(tvb, offset))) {
-               offset= mysql_dissect_server_status(tvb, offset, tree);
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               offset = mysql_dissect_server_status(tvb, offset, tree);
 
                /* 4.1+ protocol only: 2 bytes number of warnings */
                if (conn_data->clnt_caps & conn_data->srv_caps & MYSQL_CAPS_CU) {
-                       proto_tree_add_item(tree, hf_mysql_num_warn, tvb,
-                                           offset, 2, ENC_LITTLE_ENDIAN);
-               offset+= 2;
+                       proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               offset += 2;
                }
        }
 
        /* optional: message string */
-       if ((strlen= tvb_reported_length_remaining(tvb, offset))) {
-               proto_tree_add_item(tree, hf_mysql_message, tvb,
-                                   offset, strlen, ENC_NA);
-               offset+= strlen;
+       if (tvb_reported_length_remaining(tvb, offset) > 0) {
+               strlen = tvb_reported_length_remaining(tvb, offset);
+               proto_tree_add_item(tree, hf_mysql_message, tvb, offset, strlen, ENC_NA);
+               offset += strlen;
        }
 
-       conn_data->state= REQUEST;
+       conn_data->state = REQUEST;
        return offset;
 }
 
@@ -1289,91 +1324,108 @@ mysql_dissect_ok_packet(tvbuff_t *tvb, packet_info *pinfo, int offset,
 static int
 mysql_dissect_server_status(tvbuff_t *tvb, int offset, proto_tree *tree)
 {
-       guint16 status;
        proto_item *tf;
        proto_item *stat_tree;
 
-       status= tvb_get_letohs(tvb, offset);
        if (tree) {
-               tf= proto_tree_add_uint_format(tree, hf_mysql_status, tvb, offset, 2, status, "Server Status: 0x%04X ", status);
+               tf= proto_tree_add_item(tree, hf_mysql_server_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                stat_tree= proto_item_add_subtree(tf, ett_stat);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_it, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_ac, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_mr, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_mu, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_bi, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_ni, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_cr, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_lr, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_dr, tvb, offset, 2, status);
-               proto_tree_add_boolean(stat_tree, hf_mysql_stat_bs, tvb, offset, 2, status);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_it, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_ac, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_mr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_mu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_bi, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_ni, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_cr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_lr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_dr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(stat_tree, hf_mysql_stat_bs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        }
-       offset+= 2;
+       offset += 2;
 
        return offset;
 }
 
 
-static void
-mysql_dissect_collation(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 caps, gint charset, int field)
+static int
+mysql_dissect_caps_server(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps)
 {
-       proto_tree_add_uint_format(tree, field, tvb, offset, 1,
-                                  charset, "Charset: %s (%u)",
-                                  val_to_str(charset,
-                                             caps & MYSQL_CAPS_CU
-                                             ? mysql_collation_vals
-                                             : mysql_charset_vals,
-                                             "Unknown (%u)"), charset);
-}
+       proto_item *tf;
+       proto_item *cap_tree;
+
+       *caps= tvb_get_letohs(tvb, offset);
 
+       if (tree) {
+               tf = proto_tree_add_item(tree, hf_mysql_caps_server, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               cap_tree= proto_item_add_subtree(tf, ett_caps);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_secure_connect, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       }
+
+       offset += 2;
+       return offset;
+}
 
 static int
-mysql_dissect_caps(tvbuff_t *tvb, int offset, proto_tree *tree,
-                  guint16 *caps, const char* whom)
+mysql_dissect_caps_client(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *caps)
 {
+       proto_item *tf;
+       proto_item *cap_tree;
+
        *caps= tvb_get_letohs(tvb, offset);
+
        if (tree) {
-               proto_item *tf= proto_tree_add_uint_format(tree, hf_mysql_caps, tvb, offset, 2, *caps,
-                                                          "%s Capabilities: 0x%04X ", whom, *caps);
-               proto_item *cap_tree= proto_item_add_subtree(tf, ett_caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_reserved, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(cap_tree, hf_mysql_cap_secure_connect, tvb, offset, 2, *caps);
+               tf = proto_tree_add_item(tree, hf_mysql_caps_client, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               cap_tree= proto_item_add_subtree(tf, ett_caps);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(cap_tree, hf_mysql_cap_secure_connect, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        }
 
-       offset+= 2;
+       offset += 2;
        return offset;
 }
-
-
 static int
-mysql_dissect_ext_caps(tvbuff_t *tvb, int offset, proto_tree *tree,
-                      guint16 *caps, const char* whom)
+mysql_dissect_ext_caps_client(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *ext_caps)
 {
+       proto_item *tf;
        proto_item *extcap_tree;
-       *caps= tvb_get_letohs(tvb, offset);
+       *ext_caps= tvb_get_letohs(tvb, offset);
        if (tree) {
-               proto_item *tf= proto_tree_add_uint_format(tree, hf_mysql_extcaps, tvb, offset, 2, *caps,
-                                                          "Extended %s Capabilities: 0x%04X ", whom, *caps);
-               extcap_tree= proto_item_add_subtree(tf, ett_extcaps);
-               proto_tree_add_boolean(extcap_tree, hf_mysql_cap_multi_statements, tvb, offset, 2, *caps);
-               proto_tree_add_boolean(extcap_tree, hf_mysql_cap_multi_results, tvb, offset, 2, *caps);
+               tf = proto_tree_add_item(tree, hf_mysql_extcaps_client, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               extcap_tree = proto_item_add_subtree(tf, ett_extcaps);
+               proto_tree_add_item(extcap_tree, hf_mysql_cap_multi_statements, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(extcap_tree, hf_mysql_cap_multi_results, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        }
 
-       offset+= 2;
+       offset += 2;
        return offset;
 }
 
@@ -1387,22 +1439,20 @@ mysql_dissect_result_header(tvbuff_t *tvb, packet_info *pinfo, int offset,
 
        col_append_str(pinfo->cinfo, COL_INFO, " TABULAR" );
 
-       fle= tvb_get_fle(tvb, offset, &num_fields, NULL);
-       proto_tree_add_uint64(tree, hf_mysql_num_fields,
-                             tvb, offset, fle, num_fields);
-       offset+= fle;
+       fle = tvb_get_fle(tvb, offset, &num_fields, NULL);
+       proto_tree_add_uint64(tree, hf_mysql_num_fields, tvb, offset, fle, num_fields);
+       offset += fle;
 
        if (tvb_reported_length_remaining(tvb, offset)) {
-               fle= tvb_get_fle(tvb, offset, &extra, NULL);
-               proto_tree_add_uint64(tree, hf_mysql_extra,
-                                     tvb, offset, fle, extra);
-               offset+= fle;
+               fle = tvb_get_fle(tvb, offset, &extra, NULL);
+               proto_tree_add_uint64(tree, hf_mysql_extra, tvb, offset, fle, extra);
+               offset += fle;
        }
 
        if (num_fields) {
-               conn_data->state= FIELD_PACKET;
+               conn_data->state = FIELD_PACKET;
        } else {
-               conn_data->state= ROW_PACKET;
+               conn_data->state = ROW_PACKET;
        }
 
        return offset;
@@ -1423,8 +1473,7 @@ mysql_field_add_lestring(tvbuff_t *tvb, int offset, proto_tree *tree, int field)
                proto_tree_add_string(tree, field, tvb, offset, 4, "NULL");
        else
        {
-               proto_tree_add_item(tree, field, tvb, offset,
-                                   (int)lelen, ENC_NA);
+               proto_tree_add_item(tree, field, tvb, offset, (int)lelen, ENC_NA);
                offset += (int)lelen;
        }
        return offset;
@@ -1432,9 +1481,8 @@ mysql_field_add_lestring(tvbuff_t *tvb, int offset, proto_tree *tree, int field)
 
 
 static int
-mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data)
+mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data _U_)
 {
-       guint16 flags;
        proto_item *tf;
        proto_item *flags_tree;
 
@@ -1444,35 +1492,35 @@ mysql_dissect_field_packet(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_co
        offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_org_table);
        offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_name);
        offset = mysql_field_add_lestring(tvb, offset, tree, hf_mysql_fld_org_name);
-       offset++; /* filler */
-       mysql_dissect_collation(tvb, offset, tree, conn_data->srv_caps,
-                               tvb_get_letohs(tvb, offset), hf_mysql_fld_charsetnr);
+       offset +=1; /* filler */
+
+       proto_tree_add_item(tree, hf_mysql_fld_charsetnr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2; /* charset */
+
        proto_tree_add_item(tree, hf_mysql_fld_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        offset += 4; /* length */
+
        proto_tree_add_item(tree, hf_mysql_fld_type, tvb, offset, 1, ENC_NA);
-       offset++; /* type */
+       offset += 1; /* type */
 
-       flags = tvb_get_letohs(tvb, offset);
-       tf = proto_tree_add_uint_format(tree, hf_mysql_fld_flags, tvb, offset,
-                                       2, flags, "Field flags: 0x%04X", flags);
+       tf = proto_tree_add_item(tree, hf_mysql_fld_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        flags_tree = proto_item_add_subtree(tf, ett_field_flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_not_null, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_primary_key, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_unique_key, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_multiple_key, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_blob, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_unsigned, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_zero_fill, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_binary, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_enum, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_auto_increment, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_timestamp, tvb, offset, 2, flags);
-       proto_tree_add_boolean(flags_tree, hf_mysql_fld_set, tvb, offset, 2, flags);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_not_null, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_primary_key, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_unique_key, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_multiple_key, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_blob, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_unsigned, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_zero_fill, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_binary, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_enum, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_auto_increment, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_timestamp, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(flags_tree, hf_mysql_fld_set, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2; /* flags */
 
        proto_tree_add_item(tree, hf_mysql_fld_decimals, tvb, offset, 1, ENC_NA);
-       offset++; /* decimals */
+       offset += 1; /* decimals */
 
        offset += 2; /* filler */
 
@@ -1496,17 +1544,29 @@ mysql_dissect_row_packet(tvbuff_t *tvb, int offset, proto_tree *tree)
 
 
 static int
-mysql_dissect_response_prepare(tvbuff_t *tvb, int offset, proto_tree *tree)
+mysql_dissect_response_prepare(tvbuff_t *tvb, int offset, proto_tree *tree, mysql_conn_data_t *conn_data)
 {
-       proto_tree_add_text(tree, tvb, offset, -1, "FIXME: write mysql_dissect_response_prepare()");
-       return offset + tvb_reported_length_remaining(tvb, offset);
-}
-
+    /* 0, marker for OK packet */
+    offset += 1;
+    proto_tree_add_item(tree, hf_mysql_stmt_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+    offset += 4;
+    proto_tree_add_item(tree, hf_mysql_num_fields, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    conn_data->stmt_num_fields = tvb_get_letohs(tvb, offset);
+    offset += 2;
+    proto_tree_add_item(tree, hf_mysql_num_params, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+    conn_data->stmt_num_params = tvb_get_letohs(tvb, offset);
+    offset += 2;
+    /* Filler */
+    offset += 1;
+    proto_tree_add_item(tree, hf_mysql_num_warn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+
+    if (conn_data->stmt_num_params > 0)
+        conn_data->state = PREPARED_PARAMETERS;
+    else if (conn_data->stmt_num_fields > 0)
+        conn_data->state = PREPARED_FIELDS;
+    else
+        conn_data->state = REQUEST;
 
-static int
-mysql_dissect_param_packet(tvbuff_t *tvb, int offset, proto_tree *tree)
-{
-       proto_tree_add_text(tree, tvb, offset, -1, "FIXME: write mysql_dissect_param_packet()");
        return offset + tvb_reported_length_remaining(tvb, offset);
 }
 
@@ -1560,33 +1620,35 @@ my_tvb_strsize(tvbuff_t *tvb, int offset)
 static int
 tvb_get_fle(tvbuff_t *tvb, int offset, guint64 *res, guint8 *is_null)
 {
-       guint8 prefix= tvb_get_guint8(tvb, offset);
+       guint8 prefix;
+
+       prefix = tvb_get_guint8(tvb, offset);
 
        if (is_null)
-               *is_null= 0;
+               *is_null = 0;
 
        switch (prefix) {
        case 251:
                if (res)
-                       *res= 0;
+                       *res = 0;
                if (is_null)
-                       *is_null= 1;
+                       *is_null = 1;
                break;
        case 252:
                if (res)
-                       *res= tvb_get_letohs(tvb, offset+1);
+                       *res = tvb_get_letohs(tvb, offset+1);
                return 3;
        case 253:
                if (res)
-                       *res= tvb_get_letohl(tvb, offset+1);
+                       *res = tvb_get_letohl(tvb, offset+1);
                return 5;
        case 254:
                if (res)
-                       *res= tvb_get_letoh64(tvb, offset+1);
+                       *res = tvb_get_letoh64(tvb, offset+1);
                return 9;
        default:
                if (res)
-                       *res= prefix;
+                       *res = prefix;
        }
 
        return 1;
@@ -1607,9 +1669,14 @@ void proto_register_mysql(void)
                FT_UINT8, BASE_DEC, NULL, 0x0,
                NULL, HFILL }},
 
-               { &hf_mysql_opcode,
-               { "Command", "mysql.opcode",
-               FT_UINT8, BASE_DEC, NULL, 0x0,
+               { &hf_mysql_request,
+               { "Request Command", "mysql.request",
+               FT_NONE, BASE_NONE, NULL, 0x0,
+               NULL, HFILL }},
+
+               { &hf_mysql_command,
+               { "Command", "mysql.command",
+               FT_UINT8, BASE_DEC, VALS(mysql_command_vals), 0x0,
                NULL, HFILL }},
 
                { &hf_mysql_error_code,
@@ -1632,6 +1699,11 @@ void proto_register_mysql(void)
                FT_STRINGZ, BASE_NONE, NULL, 0x0,
                NULL, HFILL }},
 
+               { &hf_mysql_server_greeting,
+               { "Server Greeting", "mysql.server_greeting",
+               FT_NONE, BASE_NONE, NULL, 0x0,
+               NULL, HFILL }},
+
                { &hf_mysql_protocol,
                { "Protocol", "mysql.protocol",
                FT_UINT8, BASE_DEC, NULL, 0x0,
@@ -1642,9 +1714,14 @@ void proto_register_mysql(void)
                FT_STRINGZ, BASE_NONE, NULL, 0x0,
                "MySQL Version", HFILL }},
 
-               { &hf_mysql_caps,
-               { "Caps", "mysql.caps",
-               FT_UINT16, BASE_DEC, NULL, 0x0,
+               { &hf_mysql_caps_server,
+               { "Server Capabilities", "mysql.caps.server",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
+               "MySQL Capabilities", HFILL }},
+
+               { &hf_mysql_caps_client,
+               { "Client Capabilities", "mysql.caps.client",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
                "MySQL Capabilities", HFILL }},
 
                { &hf_mysql_cap_long_password,
@@ -1727,9 +1804,9 @@ void proto_register_mysql(void)
                FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_SC,
                NULL, HFILL }},
 
-               { &hf_mysql_extcaps,
-               { "Ext. Caps", "mysql.extcaps",
-               FT_UINT16, BASE_DEC, NULL, 0x0,
+               { &hf_mysql_extcaps_client,
+               { "Extended Client Capabilities", "mysql.extcaps.client",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
                "MySQL Extended Capabilities", HFILL }},
 
                { &hf_mysql_cap_multi_statements,
@@ -1742,11 +1819,26 @@ void proto_register_mysql(void)
                FT_BOOLEAN, 16, TFS(&tfs_set_notset), MYSQL_CAPS_MR,
                NULL, HFILL }},
 
+               { &hf_mysql_login_request,
+               { "Login Request", "mysql.login_request",
+               FT_NONE, BASE_NONE, NULL,  0x0,
+               NULL, HFILL }},
+
                { &hf_mysql_max_packet,
                { "MAX Packet", "mysql.max_packet",
                FT_UINT24, BASE_DEC, NULL,  0x0,
                "MySQL Max packet", HFILL }},
 
+               { &hf_mysql_charset,
+               { "Charset", "mysql.charset",
+               FT_UINT8, BASE_DEC, VALS(mysql_collation_vals),  0x0,
+               "MySQL Charset", HFILL }},
+
+               { &hf_mysql_table_name,
+               { "Table Name", "mysql.table_name",
+               FT_STRINGZ, BASE_NONE, NULL, 0x0,
+               NULL, HFILL }},
+
                { &hf_mysql_user,
                { "Username", "mysql.user",
                FT_STRINGZ, BASE_NONE, NULL, 0x0,
@@ -1772,14 +1864,14 @@ void proto_register_mysql(void)
                FT_UINT32, BASE_DEC, NULL,  0x0,
                "MySQL Thread ID", HFILL }},
 
-               { &hf_mysql_charset,
-               { "Charset", "mysql.charset",
-               FT_UINT8, BASE_DEC, NULL,  0x0,
+               { &hf_mysql_server_language,
+               { "Server Language", "mysql.server_language",
+               FT_UINT8, BASE_DEC, VALS(mysql_collation_vals),  0x0,
                "MySQL Charset", HFILL }},
 
-               { &hf_mysql_status,
-               { "Status", "mysql.status",
-               FT_UINT16, BASE_DEC, NULL,  0x0,
+               { &hf_mysql_server_status,
+               { "Server Status", "mysql.server_status",
+               FT_UINT16, BASE_HEX, NULL,  0x0,
                "MySQL Status", HFILL }},
 
                { &hf_mysql_stat_it,
@@ -1834,7 +1926,7 @@ void proto_register_mysql(void)
 
                { &hf_mysql_refresh,
                { "Refresh Option", "mysql.refresh",
-               FT_UINT8, BASE_DEC, NULL,  0x0,
+               FT_UINT8, BASE_HEX, NULL,  0x0,
                NULL, HFILL }},
 
                { &hf_mysql_rfsh_grants,
@@ -1884,12 +1976,12 @@ void proto_register_mysql(void)
 
                { &hf_mysql_passwd,
                { "Password", "mysql.passwd",
-               FT_STRING, BASE_NONE, NULL, 0x0,
+               FT_BYTES, BASE_NONE, NULL, 0x0,
                NULL, HFILL }},
 
                { &hf_mysql_payload,
                { "Payload", "mysql.payload",
-               FT_STRING, BASE_NONE, NULL, 0x0,
+               FT_BYTES, BASE_NONE, NULL, 0x0,
                "Additional Payload", HFILL }},
 
                { &hf_mysql_affected_rows,
@@ -1922,9 +2014,14 @@ void proto_register_mysql(void)
                FT_STRING, BASE_NONE, NULL, 0x0,
                NULL, HFILL }},
 
+               { &hf_mysql_shutdown,
+               { "Shutdown Level", "mysql.shutdown",
+               FT_UINT8, BASE_DEC, VALS(mysql_shutdown_vals), 0x0,
+               NULL, HFILL }},
+
                { &hf_mysql_option,
                { "Option", "mysql.option",
-               FT_UINT16, BASE_DEC, NULL, 0x0,
+               FT_UINT16, BASE_DEC, VALS(mysql_option_vals), 0x0,
                NULL, HFILL }},
 
                { &hf_mysql_param,
@@ -1932,23 +2029,53 @@ void proto_register_mysql(void)
                FT_UINT16, BASE_DEC, NULL, 0x0,
                NULL, HFILL }},
 
+               { &hf_mysql_num_params,
+               { "Number of parameter", "mysql.num_params",
+               FT_UINT16, BASE_DEC, NULL, 0x0,
+               NULL, HFILL }},
+
                { &hf_mysql_num_rows,
                { "Rows to fetch", "mysql.num_rows",
                FT_UINT32, BASE_DEC, NULL, 0x0,
                NULL, HFILL }},
 
-               { &hf_mysql_exec_flags,
+               { &hf_mysql_exec_flags4,
                { "Flags (unused)", "mysql.exec_flags",
                FT_UINT8, BASE_DEC, NULL, 0x0,
                NULL, HFILL }},
 
+               { &hf_mysql_exec_flags5,
+               { "Flags", "mysql.exec_flags",
+               FT_UINT8, BASE_DEC, VALS(mysql_exec_flags_vals), 0x0,
+               NULL, HFILL }},
+
                { &hf_mysql_exec_iter,
                { "Iterations (unused)", "mysql.exec_iter",
                FT_UINT32, BASE_DEC, NULL, 0x0,
                NULL, HFILL }},
 
+               { &hf_mysql_binlog_position,
+               { "Binlog Position", "mysql.binlog.position",
+               FT_UINT32, BASE_DEC, NULL, 0x0,
+               "Position to start at", HFILL }},
+
+               { &hf_mysql_binlog_flags,
+               { "Binlog Flags", "mysql.binlog.flags",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
+               "(currently not used; always 0)", HFILL }},
+
+               { &hf_mysql_binlog_server_id,
+               { "Binlog server id", "mysql.binlog.server_id",
+               FT_UINT16, BASE_HEX, NULL, 0x0,
+               "server_id of the slave", HFILL }},
+
+               { &hf_mysql_binlog_file_name,
+               { "Binlog file name", "mysql.binlog.file_name",
+               FT_STRINGZ, BASE_NONE, NULL, 0x0,
+               NULL, HFILL }},
+
                { &hf_mysql_eof,
-               { "EOF", "mysql.eof",
+               { "EOF marker", "mysql.eof",
                FT_UINT8, BASE_DEC, NULL,  0x0,
                NULL, HFILL }},
 
@@ -1994,7 +2121,7 @@ void proto_register_mysql(void)
 
                { &hf_mysql_fld_charsetnr,
                { "Charset number", "mysql.field.charsetnr",
-               FT_UINT16, BASE_DEC, NULL, 0x0,
+               FT_UINT16, BASE_DEC, VALS(mysql_collation_vals), 0x0,
                "Field: charset number", HFILL }},
 
                { &hf_mysql_fld_length,
@@ -2009,7 +2136,7 @@ void proto_register_mysql(void)
 
                { &hf_mysql_fld_flags,
                { "Flags", "mysql.field.flags",
-               FT_UINT16, BASE_DEC, NULL, 0x0,
+               FT_UINT16, BASE_HEX, NULL, 0x0,
                "Field: flags", HFILL }},
 
                { &hf_mysql_fld_not_null,
@@ -2092,6 +2219,7 @@ void proto_register_mysql(void)
        {
                &ett_mysql,
                &ett_server_greeting,
+               &ett_login_request,
                &ett_caps,
                &ett_extcaps,
                &ett_stat,
@@ -2102,11 +2230,11 @@ void proto_register_mysql(void)
 
        module_t *mysql_module;
 
-       proto_mysql= proto_register_protocol("MySQL Protocol", "MySQL", "mysql");
+       proto_mysql = proto_register_protocol("MySQL Protocol", "MySQL", "mysql");
        proto_register_field_array(proto_mysql, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
-       mysql_module= prefs_register_protocol(proto_mysql, NULL);
+       mysql_module = prefs_register_protocol(proto_mysql, NULL);
        prefs_register_bool_preference(mysql_module, "desegment_buffers",
                                       "Reassemble MySQL buffers spanning multiple TCP segments",
                                       "Whether the MySQL dissector should reassemble MySQL buffers spanning multiple TCP segments."