diff options
author | Guy Harris <guy@alum.mit.edu> | 2003-01-19 21:29:10 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2003-01-19 21:29:10 +0000 |
commit | 96b2d6076309f9a8f8c92cfef94c85e2be93d4ec (patch) | |
tree | d387f817830e46d06be82b1e028a96060d1198b7 /packet-mysql.c | |
parent | 3e393a11f03e3a6e74f80d476abd06753630606f (diff) | |
download | wireshark-96b2d6076309f9a8f8c92cfef94c85e2be93d4ec.tar.gz wireshark-96b2d6076309f9a8f8c92cfef94c85e2be93d4ec.tar.bz2 wireshark-96b2d6076309f9a8f8c92cfef94c85e2be93d4ec.zip |
From Huagang Xie: dissector for MySQL protocol.
svn path=/trunk/; revision=6939
Diffstat (limited to 'packet-mysql.c')
-rw-r--r-- | packet-mysql.c | 837 |
1 files changed, 837 insertions, 0 deletions
diff --git a/packet-mysql.c b/packet-mysql.c new file mode 100644 index 0000000000..6542d071d1 --- /dev/null +++ b/packet-mysql.c @@ -0,0 +1,837 @@ +/* packet-mysql.c + * Routines for mysql packet dissection + * + * Huagang XIE <huagang@intruvert.com> + * + * $Id: packet-mysql.c,v 1.1 2003/01/19 21:29:08 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * Copied from packet-tftp.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * the protocol spec at + * http://public.logicacmg.com/~redferni/mysql/MySQL-Protocol.html + * and MySQL source code + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glib.h> +#include <epan/packet.h> +#include <epan/conversation.h> + +#include "packet-smb-common.h" +#include "packet-frame.h" +#include "reassemble.h" +#include "prefs.h" + +/* Capabilities */ +#define MYSQL_CAPS_LP 0x0001 +#define MYSQL_CAPS_FR 0x0002 +#define MYSQL_CAPS_LF 0x0004 +#define MYSQL_CAPS_CD 0x0008 +#define MYSQL_CAPS_NS 0x0010 +#define MYSQL_CAPS_CP 0x0020 +#define MYSQL_CAPS_OB 0x0040 +#define MYSQL_CAPS_LI 0x0080 +#define MYSQL_CAPS_IS 0x0100 +#define MYSQL_CAPS_CU 0x0200 +#define MYSQL_CAPS_IA 0x0400 +#define MYSQL_CAPS_SL 0x0800 +#define MYSQL_CAPS_II 0x1000 +#define MYSQL_CAPS_TA 0x2000 + +static int proto_mysql = -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_response_code= -1; +static int hf_mysql_error_code= -1; +static int hf_mysql_payload= -1; +static int hf_mysql_protocol= -1; +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_version = -1; +static int hf_mysql_max_packet= -1; +static int hf_mysql_user= -1; +static int hf_mysql_password= -1; +static int hf_mysql_thread_id = -1; +static int hf_mysql_salt= -1; +static int hf_mysql_charset= -1; +static int hf_mysql_status= -1; +static int hf_mysql_unused= -1; +static int hf_mysql_parameter= -1; + +static gint ett_mysql = -1; +static gint ett_server_greeting = -1; +static gint ett_caps = -1; +static gint ett_request = -1; + + +static dissector_handle_t mysql_handle; + +static gboolean mysql_desegment = TRUE; + +#define TCP_PORT_MySQL 3306 + +#define MySQL_SLEEP 0 +#define MySQL_QUIT 1 +#define MySQL_INIT_DB 2 +#define MySQL_QUERY 3 +#define MySQL_FIELD_LIST 4 +#define MySQL_CREATE_DB 5 +#define MySQL_DROP_DB 6 +#define MySQL_REFRESH 7 +#define MySQL_SHUTDOWN 8 +#define MySQL_STATISTICS 9 +#define MySQL_PROCESS_INFO 10 +#define MySQL_CONNECT 11 +#define MySQL_PROCESS_KILL 12 +#define MySQL_DEBUG 13 +#define MySQL_PING 14 +#define MySQL_TIME 15 +#define MySQL_DELAY_INSERT 16 +#define MySQL_CHANGE_USER 17 +#define MySQL_BINLOG_DUMP 18 +#define MySQL_TABLE_DUMP 19 +#define MySQL_CONNECT_OUT 20 + + +static const value_string mysql_opcode_vals[] = { + { MySQL_SLEEP, "SLEEP" }, + { MySQL_QUIT, "Quit" }, + { MySQL_INIT_DB, "Init Database" }, + { MySQL_QUERY, "Query" }, + { MySQL_FIELD_LIST, "Field List" }, + { MySQL_CREATE_DB, "Create Database" }, + { MySQL_DROP_DB , "Drop Database" }, + { MySQL_REFRESH , "Refresh" }, + { MySQL_SHUTDOWN , "Shutdown" }, + { MySQL_STATISTICS , "Statistics" }, + { MySQL_PROCESS_INFO , "Process Info" }, + { MySQL_CONNECT , "Connect" }, + { MySQL_PROCESS_KILL , "Process Kill" }, + { MySQL_DEBUG , "Debug" }, + { MySQL_PING , "Ping" }, + { MySQL_TIME , "Time" }, + { MySQL_DELAY_INSERT , "Delay Insert" }, + { MySQL_CHANGE_USER , "Change User" }, + { MySQL_BINLOG_DUMP , "Binlog Dump" }, + { MySQL_TABLE_DUMP, "Table Dump" }, + { MySQL_CONNECT_OUT, "Table Connect Out" }, + { 0, NULL } +}; + +static const value_string mysql_status_vals[] = { + {1, "IN_TRANS" }, + {2, "AUTOCOMMIT"}, + { 0, NULL } +}; +static const value_string mysql_charset_vals[] = { + {1, "big5"}, + {2, "czech"}, + {3,"dec8"}, + {4, "dos" }, + {5,"german1"}, + {6,"hp8"}, + {7,"koi8_ru"}, + {8,"latin1"}, + {9,"latin2"}, + {9,"swe7 "}, + {10,"usa7"}, + {11,"ujis"}, + {12,"sjis"}, + {13,"cp1251"}, + {14,"danish"}, + {15,"hebrew"}, + {16,"win1251"}, + {17,"tis620"}, + {18,"euc_kr"}, + {19,"estonia"}, + {20,"hungarian"}, + {21,"koi8_ukr"}, + {22,"win1251ukr"}, + {23,"gb2312"}, + {24,"greek"}, + {25,"win1250"}, + {26,"croat"}, + {27,"gbk"}, + {28,"cp1257"}, + {29,"latin5"}, + {0,NULL} +}; +#if 0 +static const value_string mysql_error_code_vals[] = { + { 0, "Not defined" }, + { 1, "File not found" }, + { 2, "Access violation" }, + { 3, "Disk full or allocation exceeded" }, + { 4, "Illegal MySQL Operation" }, + { 5, "Unknown transfer ID" }, + { 6, "File already exists" }, + { 7, "No such user" }, + { 8, "Option negotiation failed" }, + { 0, NULL } +}; +#endif + +static int mysql_dissect_server_greeting(tvbuff_t *tvb, packet_info *pinfo, + int offset, proto_tree *tree); +static int mysql_dissect_authentication(tvbuff_t *tvb, packet_info *pinfo, + int offset, proto_tree *tree); +static int mysql_dissect_request(tvbuff_t *tvb, packet_info *pinfo, + int offset, proto_tree *tree); +static int mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo, + int offset, proto_tree *tree); + +static void +dissect_mysql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *mysql_tree = NULL; + proto_item *ti; + conversation_t *conversation; + + gint offset = 0; + gint this_offset = 0; + guint32 packet_length; + guint packet_number; + + guint i1=0; + + guint is_response=0; + guint32 length; + + conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype, + pinfo->srcport, pinfo->destport, 0); + + if (!conversation) { + /* create a new conversation */ + conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype, + pinfo->srcport, pinfo->destport, 0); + /* reset some counter */ + offset = this_offset = 0; + } + + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "MySQL"); + + if (pinfo->destport == TCP_PORT_MySQL) { + is_response=0; + }else { + is_response=1; + } + + while (tvb_reported_length_remaining(tvb, offset) != 0) { + /* + * We use "tvb_ensure_length_remaining()" to make sure + * there actually *is* data remaining. + */ + length = tvb_ensure_length_remaining(tvb, offset); + + this_offset = offset; + + packet_length = tvb_get_letoh24(tvb, offset); + /* check if reassembly is needed */ + if (mysql_desegment && pinfo->can_desegment) { + if(packet_length+4 > length) { + pinfo->desegment_offset = offset; + pinfo->desegment_len = packet_length + 4 - length; + return; + } + } + + if (tree) { + ti = proto_tree_add_item(tree, proto_mysql, tvb, offset, -1, FALSE); + mysql_tree = proto_item_add_subtree(ti, ett_mysql); + + proto_tree_add_uint(mysql_tree, hf_mysql_packet_length, tvb, + offset, 3, packet_length); + } + offset += 3; +/* packet number */ + packet_number= tvb_get_guint8(tvb, offset); + if (tree) { + proto_tree_add_uint(mysql_tree, hf_mysql_packet_number, tvb, + offset, 1, packet_number); + } + offset += 1; + + /* + * packet == 0 && response --> server greeting + * packet == 1 && request --> login request + */ + if(is_response ) { + if( packet_number == 0 ) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, "Server Greeting" ) ; + } + offset = mysql_dissect_server_greeting(tvb,pinfo,offset,mysql_tree); + }else { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, "Response" ) ; + } + offset = mysql_dissect_response(tvb,pinfo,offset,mysql_tree); + } + } else { + if( packet_number == 1 ) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, "Login Request") ; + } + offset = mysql_dissect_authentication(tvb,pinfo,offset,mysql_tree); + }else { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, "Request") ; + } + offset = mysql_dissect_request(tvb,pinfo,offset,mysql_tree); + } + } + + +/* paylod */ + if(packet_length+4 > length) { + if (mysql_desegment && pinfo->can_desegment) { + i1 = packet_length-offset+this_offset+4; + } else { + /* increase by 1 to make the display or unassembly packet */ + i1 = length-offset+this_offset+4; + } + } else { + i1 = packet_length-offset+this_offset+4; + } + if (tree && i1 > 0) { + proto_tree_add_item(mysql_tree, hf_mysql_payload, + tvb, offset, i1, FALSE); + } + offset += i1; + } + pinfo->desegment_offset = 0; + pinfo->desegment_len = 0; +} +static int +mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo, + int offset, proto_tree *tree) +{ + gint response_code; + gint error_code; + + /* response code */ + response_code= tvb_get_guint8(tvb, offset); + if (tree) { + proto_tree_add_uint(tree, hf_mysql_response_code, tvb, + offset, 1, response_code); + } + offset +=1; + + if(response_code== 0xff ) { + /* error code */ + error_code = tvb_get_letohs(tvb, offset); + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Error Code: %x", error_code ); + } + if (tree) { + proto_tree_add_uint(tree, hf_mysql_error_code, tvb, + offset, 2, error_code); + } + offset +=2; + + } else { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_str(pinfo->cinfo, COL_INFO, " OK" ); + } + } + return offset; +} + +static int +mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo, + int offset, proto_tree *tree) +{ + gint opcode; + gint strlen; + proto_item *tf; + 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); + } + + opcode = tvb_get_guint8(tvb, offset); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Command: %s", + val_to_str(opcode, mysql_opcode_vals, "Unknown (%u)")); + } + + if (req_tree) { + 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); + } + /* command parameter */ + + offset += 1; + if ( (strlen = tvb_length_remaining(tvb,offset)) > 0 ) { + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " : %s", + tvb_memdup(tvb,offset,strlen)); + } + + if (tree) { + proto_tree_add_item(req_tree, hf_mysql_parameter, tvb, + offset, strlen, FALSE ); + } + offset +=strlen; + } + + return offset; +} + + +static int +mysql_dissect_authentication(tvbuff_t *tvb, packet_info *pinfo, + int offset, proto_tree *tree) +{ + gint16 client_caps; + gint32 max_packet; + gint strlen; + + proto_item *tf; + proto_item *cap_tree; + proto_item *login_tree=NULL; + + if(tree) { + tf=proto_tree_add_text(tree,tvb,offset,-1,"Login Packet"); + login_tree = proto_item_add_subtree(tf ,ett_server_greeting); + } + + client_caps= tvb_get_letohs(tvb, offset); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Caps: 0x%x",client_caps) ; + } + if(tree) { + tf = proto_tree_add_uint_format(login_tree, hf_mysql_caps, tvb, offset , 1, client_caps, "Caps: 0x%04x ", client_caps ); + cap_tree = proto_item_add_subtree(tf, ett_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, client_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, client_caps); + } + +/* proto_tree_add_uint(tree, hf_mysql_client_caps, tvb, + offset, 2, client_caps); +*/ + offset +=2; + /* 3 bytes max packet, 16777216 - x */ + max_packet = 0xffffff - tvb_get_letoh24(tvb, offset); + if(tree) { + proto_tree_add_uint(login_tree, hf_mysql_max_packet, tvb, + offset, 3, max_packet); + } + offset +=3; + /* User name */ + strlen = tvb_strsize(tvb,offset); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " ,user: %s", + tvb_get_ptr(tvb,offset,strlen)); + } + if (tree) { + proto_tree_add_item(login_tree, hf_mysql_user, tvb, + offset, strlen, FALSE ); + } + offset +=strlen; + + /* Password */ + strlen = tvb_length_remaining(tvb,offset); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " ,password: %s", + tvb_get_ptr(tvb,offset,strlen)); + } + if (tree) { + proto_tree_add_item(login_tree, hf_mysql_password, tvb, + offset, strlen, FALSE ); + } + offset +=strlen; + + + return offset; +} + + +static int +mysql_dissect_server_greeting(tvbuff_t *tvb, packet_info *pinfo, + int offset, proto_tree *tree) +{ + gint protocol; + gint strlen; + gint32 thread_id; + gint16 server_caps; + gint charset; + gint16 status; + + proto_item *tf; + proto_item *greeting_tree=NULL; + proto_item *cap_tree; + + protocol= tvb_get_guint8(tvb, offset); + + if(tree) { + tf = proto_tree_add_text(tree,tvb,offset,-1,"Server Greeting"); + greeting_tree = proto_item_add_subtree(tf ,ett_server_greeting); + } + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Protocol : %d",protocol) ; + } + if (tree) { + proto_tree_add_uint(greeting_tree, hf_mysql_protocol, tvb, + offset, 1, protocol); + } + offset +=1; + /* version string */ + + strlen = tvb_strsize(tvb,offset); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " ,version: %s", + tvb_get_ptr(tvb,offset,strlen)); + } + if (tree) { + proto_tree_add_item(greeting_tree, hf_mysql_version, tvb, + offset, strlen, FALSE ); + } + offset +=strlen; + + /* 4 bytes little endian thread_id */ + thread_id = tvb_get_letohl(tvb, offset); + if(tree) { + proto_tree_add_uint(greeting_tree, hf_mysql_thread_id, tvb, + offset, 4, thread_id); + } + offset +=4; + /* salt string */ + strlen = tvb_strsize(tvb,offset); + if (tree) { + proto_tree_add_item(greeting_tree, hf_mysql_salt, tvb, + offset, strlen, FALSE ); + } + offset +=strlen; + /* 2 bytes CAPS */ + server_caps= tvb_get_letohs(tvb, offset); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Caps: 0x%x",server_caps) ; + } + if(tree) { + tf = proto_tree_add_uint_format(greeting_tree, hf_mysql_caps, tvb, offset , 1, server_caps, "Caps: 0x%04x ", server_caps ); + cap_tree = proto_item_add_subtree(tf, ett_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, server_caps); + proto_tree_add_boolean(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, server_caps); + } + offset+=2; + /* 1 byte charset */ + charset = tvb_get_guint8(tvb, offset); + if (tree) { + proto_tree_add_uint_format(greeting_tree, hf_mysql_charset, tvb, + offset, 1, charset, "Charset: %s (%u)", + val_to_str(charset, mysql_charset_vals, "Unknown (%u)"), charset); + } + offset +=1; + /* 2 byte status */ + status = tvb_get_letohs(tvb, offset); + if (tree) { + proto_tree_add_uint_format(greeting_tree, hf_mysql_status, tvb, + offset, 2, status, "Status: %s (%u)", + val_to_str(status, mysql_status_vals, "Unknown (%u)"), status); + } + offset +=2; + /* other unused */ + strlen = tvb_length_remaining(tvb,offset); + + if (tree) { + proto_tree_add_item(greeting_tree, hf_mysql_unused, tvb, + offset, strlen, FALSE ); + } + offset +=strlen; + + return offset; +} + +void +proto_register_mysql(void) +{ + static hf_register_info hf[] = { + { &hf_mysql_packet_length, + { "Packet Length", "mysql.packet_length", + FT_UINT24, BASE_DEC, NULL, 0x0, + "MySQL packet length", HFILL }}, + + { &hf_mysql_packet_number, + { "Packet Number", "mysql.packet_number", + FT_UINT8, BASE_DEC, NULL, 0x0, + "MySQL Packet Number", HFILL }}, + + { &hf_mysql_opcode, + { "Command", "mysql.opcode", + FT_UINT8, BASE_DEC, NULL, 0x0, + "MySQL OPCODE", HFILL }}, + + { &hf_mysql_response_code, + { "Response Code", "mysql.response_code", + FT_UINT8, BASE_DEC, NULL, 0x0, + "MySQL Respone Code", HFILL }}, + + { &hf_mysql_error_code, + { "Error Code", "mysql.error_code", + FT_UINT16, BASE_DEC, NULL, 0x0, + "MySQL Error CODE", HFILL }}, + + { &hf_mysql_protocol, + { "Protocol", "mysql.protocol", + FT_UINT8, BASE_DEC, NULL, 0x0, + "MySQL Protocol", HFILL }}, + + { &hf_mysql_version, + { "Version", "mysql.version", + FT_STRINGZ, BASE_DEC, NULL, 0x0, + "MySQL Version", HFILL }}, + + { &hf_mysql_caps, + { "Caps", "mysql.caps", + FT_UINT16, BASE_DEC, NULL, 0x0, + "MySQL Capabilities", HFILL }}, + + { &hf_mysql_cap_long_password, + { "Long Password","tcp.caps.lp", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LP, + "", HFILL }}, + + { &hf_mysql_cap_found_rows, + { "Found Rows","tcp.caps.fr", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_FR, + "", HFILL }}, + + + { &hf_mysql_cap_long_flag, + { "Long Flag","tcp.caps.lf", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LF, + "", HFILL }}, + + { &hf_mysql_cap_connect_with_db, + { "Connect With Database","tcp.caps.cd", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CD, + "", HFILL }}, + + + { &hf_mysql_cap_no_schema, + { "Dont Allow database.table.column","tcp.caps.ns", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_NS, + "", HFILL }}, + + { &hf_mysql_cap_compress, + { "Can use compression protocol","tcp.caps.CP", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CP, + "", HFILL }}, + + { &hf_mysql_cap_odbc, + { "ODBC Client","tcp.caps.ob", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_OB, + "", HFILL }}, + + + { &hf_mysql_cap_local_files, + { "Can Use LOAD DATA LOCAL","tcp.caps.li", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LI, + "", HFILL }}, + + { &hf_mysql_cap_ignore_space, + { "Ignore Spaces before (","tcp.caps.is", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_IS, + "", HFILL }}, + + + { &hf_mysql_cap_change_user, + { "Support the mysql_change_user()","tcp.caps.cu", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CU, + "", HFILL }}, + + + { &hf_mysql_cap_interactive, + { "an Interactive Client","tcp.caps.ia", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_IA, + "", HFILL }}, + + + { &hf_mysql_cap_ssl, + { "Switch to SSL after handshake","tcp.caps.sl", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_SL, + "", HFILL }}, + + { &hf_mysql_cap_ignore_sigpipe, + { "Ignore sigpipes","tcp.caps.ii", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_II, + "", HFILL }}, + + { &hf_mysql_cap_transactions, + { "Client knows about transactions","tcp.caps.ta", + FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_TA, + "", HFILL }}, + + { &hf_mysql_max_packet, + { "MAX Packet", "mysql.max_packet", + FT_UINT24, BASE_DEC, NULL, 0x0, + "MySQL Max packet", HFILL }}, + + { &hf_mysql_user, + { "Username", "mysql.user", + FT_STRINGZ, BASE_DEC, NULL, 0x0, + "Login Username", HFILL }}, + + { &hf_mysql_password, + { "Password", "mysql.password", + FT_STRING, BASE_DEC, NULL, 0x0, + "Login Password", HFILL }}, + + { &hf_mysql_salt, + { "Salt", "mysql.salt", + FT_STRINGZ, BASE_DEC, NULL, 0x0, + "Salt", HFILL }}, + + { &hf_mysql_thread_id, + { "Thread ID", "mysql.thread_id", + FT_UINT32, BASE_DEC, NULL, 0x0, + "MySQL Thread ID", HFILL }}, + + { &hf_mysql_charset, + { "Charset", "mysql.charset", + FT_UINT8, BASE_DEC, NULL, 0x0, + "MySQL Charset", HFILL }}, + + { &hf_mysql_status, + { "Status", "mysql.status", + FT_UINT16, BASE_DEC, NULL, 0x0, + "MySQL Status", HFILL }}, + + { &hf_mysql_unused, + { "Unused", "mysql.unused", + FT_STRING, BASE_DEC, NULL, 0x0, + "Unused", HFILL }}, + + { &hf_mysql_parameter, + { "Parameter", "mysql.parameter", + FT_STRING, BASE_DEC, NULL, 0x0, + "Parameter", HFILL }}, + { &hf_mysql_payload, + { "Payload", "mysql.payload", + FT_STRING, BASE_DEC, NULL, 0x0, + "MySQL Payload", HFILL }}, + + + }; +#if 0 + { &hf_mysql_destination_file, + { "DESTINATION File", "mysql.destination_file", + FT_STRINGZ, BASE_DEC, NULL, 0x0, + "MySQL source file name", HFILL }}, + + { &hf_mysql_blocknum, + { "Block", "mysql.block", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Block number", HFILL }}, + + { &hf_mysql_error_code, + { "Error code", "mysql.error.code", + FT_UINT16, BASE_DEC, VALS(mysql_error_code_vals), 0x0, + "Error code in case of MySQL error message", HFILL }}, + + { &hf_mysql_error_string, + { "Error message", "mysql.error.message", + FT_STRINGZ, BASE_DEC, NULL, 0x0, + "Error string in case of MySQL error message", HFILL }} +#endif + static gint *ett[] = { + &ett_mysql, + &ett_server_greeting, + &ett_caps, + &ett_request, + }; + module_t *mysql_module; + + 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_handle = create_dissector_handle(dissect_mysql, proto_mysql); + + mysql_module = prefs_register_protocol(proto_mysql, NULL); + prefs_register_bool_preference(mysql_module, "desegment_buffers", + "Desegment all MySQL buffers spanning multiple TCP segments", + "Whether the MySQL dissector should desegment all MySQL buffers spanning multiple TCP segments", + &mysql_desegment); +} + +void +proto_reg_handoff_mysql(void) +{ + dissector_add("tcp.port", TCP_PORT_MySQL, mysql_handle); +} |