diff --git a/doc/userguide/output/eve/eve-json-format.rst b/doc/userguide/output/eve/eve-json-format.rst index 952945dffc98..a7667e2bbbcf 100644 --- a/doc/userguide/output/eve/eve-json-format.rst +++ b/doc/userguide/output/eve/eve-json-format.rst @@ -3057,3 +3057,32 @@ Example of ARP logging: request and response "dest_mac": "00:1d:09:f0:92:ab", "dest_ip": "10.10.10.1" } + +Event type: MySQL +----------------- + +Fields +~~~~~~ + +* "version": the MySQL protocol version offered by the server. +* "tls": protocol need to be upgrade to tls. +* "command": sql query statement or utility command like ping. +* "rows": zero or multi results from executing sql query statement, one row is splited by comma. + +Examples +~~~~~~~~ + +Example of MySQL logging: + +:: + +{ + "mysql": { + "version": "8.0.32", + "tls": false, + "command": "SELECT VERSION()", + "rows": [ + "8.0.32" + ] + } +} diff --git a/doc/userguide/rules/index.rst b/doc/userguide/rules/index.rst index c8b586fecaa7..a3b8108bdcf4 100644 --- a/doc/userguide/rules/index.rst +++ b/doc/userguide/rules/index.rst @@ -37,6 +37,7 @@ Suricata Rules nfs-keywords smtp-keywords websocket-keywords + mysql-keywords app-layer xbits noalert diff --git a/doc/userguide/rules/mysql-keywords.rst b/doc/userguide/rules/mysql-keywords.rst new file mode 100644 index 000000000000..39ed949c3db9 --- /dev/null +++ b/doc/userguide/rules/mysql-keywords.rst @@ -0,0 +1,50 @@ +MySQL Keywords +============ + +The MySQL keywords are implemented and can be used to match on fields in MySQL messages. + +============================== ================== +Keyword Direction +============================== ================== +mysql.command Request +mysql.rows Response +============================== ================== + +mysql.command +---------- + +This keyword matches on the query statement like `select * from xxx where yyy = zzz` found in a MySQL request. + +Syntax +~~~~~~ + +:: + + mysql.command; content:; + +Examples +~~~~~~~~ + +:: + + mysql.commands; content:"select"; + +mysql.rows +------- + +This keyword matches on the rows which come from query statement result found in a Mysql response. +row format: 1,foo,bar + +Syntax +~~~~~~ + +:: + + mysql.rows; content:; + +Examples +~~~~~~~~ + +:: + + mysql.rows; content:"foo,bar"; diff --git a/doc/userguide/upgrade.rst b/doc/userguide/upgrade.rst index 63e2146280ab..5b2cdf1bf732 100644 --- a/doc/userguide/upgrade.rst +++ b/doc/userguide/upgrade.rst @@ -79,6 +79,8 @@ Major changes - sip.content_length - Napatech support has been moved to a capture plugin. See :doc:`Napatech plugin `. +- MySQL parser and logger have been introduced. +- The MySQL keywords ``mysql.command`` and ``mysql.command`` have been introduced. Removals ~~~~~~~~ diff --git a/etc/schema.json b/etc/schema.json index 388387652018..3837a3a941f3 100644 --- a/etc/schema.json +++ b/etc/schema.json @@ -2390,23 +2390,30 @@ "type": "object", "optional": true, "properties": { - "tx_id": { - "type": "integer" - }, "version": { - "type": "string" + "type": "string", + "description": "Mysql server version" }, "tls": { "type": "boolean" }, "command": { - "type": "string" + "type": "string", + "description": "sql query statement or some utility commands like ping." }, "affected_rows": { "type": "integer" }, - }, - "additionalProperties": false + "rows": { + "type": "array", + "optional": true, + "minItems": 1, + "items": { + "type": "string" + }, + "description": "Comma separated result from sql statement" + } + } }, "ldap": { "type": "object", @@ -4688,6 +4695,10 @@ "description": "Errors encountered parsing MQTT protocol", "$ref": "#/$defs/stats_applayer_error" }, + "mysql": { + "description": "Errors encountered parsing MySQL protocol", + "$ref": "#/$defs/stats_applayer_error" + }, "nfs_tcp": { "description": "Errors encountered parsing NFS/TCP protocol", "$ref": "#/$defs/stats_applayer_error" @@ -4863,6 +4874,10 @@ "description": "Number of flows for MQTT protocol", "type": "integer" }, + "mysql": { + "description": "Number of flows for MySQL protocol", + "type": "integer" + }, "nfs_tcp": { "description": "Number of flows for NFS/TCP protocol", "type": "integer" @@ -5033,6 +5048,10 @@ "description": "Number of transactions for MQTT protocol", "type": "integer" }, + "mysql": { + "description": "Number of flows for MySQL protocol", + "type": "integer" + }, "nfs_tcp": { "description": "Number of transactions for NFS/TCP protocol", "type": "integer" diff --git a/rust/src/mysql/detect.rs b/rust/src/mysql/detect.rs new file mode 100644 index 000000000000..1f42b0f84bc6 --- /dev/null +++ b/rust/src/mysql/detect.rs @@ -0,0 +1,166 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +// Author: QianKaiLin + +/// Detect +/// Get the mysql query +use super::mysql::{MysqlTransaction, ALPROTO_MYSQL}; +use crate::detect::{ + DetectBufferSetActiveList, DetectHelperBufferMpmRegister, DetectHelperGetData, + DetectHelperGetMultiData, DetectHelperKeywordRegister, DetectHelperMultiBufferMpmRegister, + DetectSignatureSetAppProto, SCSigTableElmt, SIGMATCH_NOOPT, +}; +use std::os::raw::{c_int, c_void}; + +static mut G_MYSQL_COMMAND_BUFFER_ID: c_int = 0; +static mut G_MYSQL_ROWS_BUFFER_ID: c_int = 0; + +#[no_mangle] +unsafe extern "C" fn SCMysqlCommandSetup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_MYSQL) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_MYSQL_COMMAND_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +#[no_mangle] +unsafe extern "C" fn SCMysqlGetCommand( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, +) -> *mut c_void { + return DetectHelperGetData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + SCMysqlGetCommandData, + ); +} + +#[no_mangle] +unsafe extern "C" fn SCMysqlGetCommandData( + tx: *const c_void, _flags: u8, buf: *mut *const u8, len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, MysqlTransaction); + if let Some(command) = &tx.command { + if !command.is_empty() { + *buf = command.as_ptr(); + *len = command.len() as u32; + return true; + } + } + + false +} + +#[no_mangle] +unsafe extern "C" fn SCMysqlRowsSetup( + de: *mut c_void, s: *mut c_void, _raw: *const std::os::raw::c_char, +) -> c_int { + if DetectSignatureSetAppProto(s, ALPROTO_MYSQL) != 0 { + return -1; + } + if DetectBufferSetActiveList(de, s, G_MYSQL_ROWS_BUFFER_ID) < 0 { + return -1; + } + return 0; +} + +#[no_mangle] +unsafe extern "C" fn SCMysqlGetRows( + de: *mut c_void, transforms: *const c_void, flow: *const c_void, flow_flags: u8, + tx: *const c_void, list_id: c_int, local_id: u32, +) -> *mut c_void { + return DetectHelperGetMultiData( + de, + transforms, + flow, + flow_flags, + tx, + list_id, + local_id, + SCMysqlGetRowsData, + ); +} + +/// Get the mysql rows at index i +#[no_mangle] +pub unsafe extern "C" fn SCMysqlGetRowsData( + tx: *const c_void, _flow_flags: u8, local_id: u32, buf: *mut *const u8, len: *mut u32, +) -> bool { + let tx = cast_pointer!(tx, MysqlTransaction); + if let Some(rows) = &tx.rows { + if !rows.is_empty() { + let index = local_id as usize; + if let Some(row) = rows.get(index) { + *buf = row.as_ptr(); + *len = row.len() as u32; + return true; + } + } + } + + false +} + +#[no_mangle] +pub unsafe extern "C" fn ScDetectMysqlRegister() { + let kw = SCSigTableElmt { + name: b"mysql.command\0".as_ptr() as *const libc::c_char, + desc: b"sticky buffer to match on the MySQL command\0".as_ptr() as *const libc::c_char, + url: b"/rules/mysql-keywords.html#mysql-command\0".as_ptr() as *const libc::c_char, + Setup: SCMysqlCommandSetup, + flags: SIGMATCH_NOOPT, + AppLayerTxMatch: None, + Free: None, + }; + let _g_mysql_command_kw_id = DetectHelperKeywordRegister(&kw); + G_MYSQL_COMMAND_BUFFER_ID = DetectHelperBufferMpmRegister( + b"mysql.command\0".as_ptr() as *const libc::c_char, + b"mysql.command\0".as_ptr() as *const libc::c_char, + ALPROTO_MYSQL, + false, + true, + SCMysqlGetCommand, + ); + let kw = SCSigTableElmt { + name: b"mysql.rows\0".as_ptr() as *const libc::c_char, + desc: b"sticky buffer to match on the MySQL Rows\0".as_ptr() as *const libc::c_char, + url: b"/rules/mysql-keywords.html#mysql-rows\0".as_ptr() as *const libc::c_char, + Setup: SCMysqlRowsSetup, + flags: SIGMATCH_NOOPT, + AppLayerTxMatch: None, + Free: None, + }; + let _g_mysql_rows_kw_id = DetectHelperKeywordRegister(&kw); + G_MYSQL_ROWS_BUFFER_ID = DetectHelperMultiBufferMpmRegister( + b"mysql.rows\0".as_ptr() as *const libc::c_char, + b"mysql select statement resultset\0".as_ptr() as *const libc::c_char, + ALPROTO_MYSQL, + true, + false, + SCMysqlGetRows, + ); +} diff --git a/rust/src/mysql/logger.rs b/rust/src/mysql/logger.rs index 6bc68c180581..38cd85ebb461 100644 --- a/rust/src/mysql/logger.rs +++ b/rust/src/mysql/logger.rs @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Open Information Security Foundation +/* Copyright (C) 2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -15,21 +15,15 @@ * 02110-1301, USA. */ -// written by linqiankai -// +// Author: QianKaiLin + use crate::jsonbuilder::{JsonBuilder, JsonError}; use crate::mysql::mysql::*; -fn log_mysql(tx: &MysqlTransaction, _flags: u32, js: &mut JsonBuilder) -> Result<(), JsonError> { +fn log_mysql(tx: &MysqlTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { js.open_object("mysql")?; - if let Some(version) = &tx.version { - js.set_string("version", version)?; - } - if let Some(tls) = &tx.tls { - js.set_bool("tls", *tls)?; - } else { - js.set_bool("tls", false)?; - } + js.set_string("version", tx.version.as_str())?; + js.set_bool("tls", tx.tls)?; if let Some(command) = &tx.command { js.set_string("command", command)?; @@ -54,16 +48,12 @@ fn log_mysql(tx: &MysqlTransaction, _flags: u32, js: &mut JsonBuilder) -> Result #[no_mangle] pub unsafe extern "C" fn SCMysqlLogger( - tx: *mut std::os::raw::c_void, flags: u32, js: &mut JsonBuilder, + tx: *mut std::os::raw::c_void, js: &mut JsonBuilder, ) -> bool { let tx_mysql = cast_pointer!(tx, MysqlTransaction); - SCLogDebug!( - "----------- MySQL rs_mysql_logger call. Tx is {:?}", - tx_mysql - ); - let result = log_mysql(tx_mysql, flags, js); - if let Err(ref err) = result { - SCLogError!("----------- MySQL rs_mysql_logger failed. err is {:?}", err); + let result = log_mysql(tx_mysql, js); + if let Err(ref _err) = result { + return false; } return result.is_ok(); } diff --git a/rust/src/mysql/mod.rs b/rust/src/mysql/mod.rs index 96be7aa8c41c..4bc3005880c4 100644 --- a/rust/src/mysql/mod.rs +++ b/rust/src/mysql/mod.rs @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Open Information Security Foundation +/* Copyright (C) 2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -15,9 +15,9 @@ * 02110-1301, USA. */ -//! MySQL parser, logger and application layer module. -//! -//! written by Kotodian +// Author: QianKaiLin + +pub mod detect; pub mod logger; pub mod mysql; pub mod parser; diff --git a/rust/src/mysql/mysql.rs b/rust/src/mysql/mysql.rs index 0a3796274a14..35636ab32c9e 100644 --- a/rust/src/mysql/mysql.rs +++ b/rust/src/mysql/mysql.rs @@ -1,3 +1,22 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +// Author: QianKaiLin +// use std::collections::VecDeque; use std::ffi::CString; @@ -13,7 +32,7 @@ pub const MYSQL_CONFIG_DEFAULT_STREAM_DEPTH: u32 = 0; static mut MYSQL_MAX_TX: usize = 1024; -static mut ALPROTO_MYSQL: AppProto = ALPROTO_UNKNOWN; +pub static mut ALPROTO_MYSQL: AppProto = ALPROTO_UNKNOWN; #[derive(FromPrimitive, Debug, AppLayerEvent)] pub enum MysqlEvent { @@ -24,12 +43,15 @@ pub enum MysqlEvent { pub struct MysqlTransaction { pub tx_id: u64, - pub version: Option, - pub command_code: Option, + /// Required + pub version: String, + /// Optional when tls is true pub command: Option, + /// Optional when tls is true pub affected_rows: Option, + /// Optional when tls is true pub rows: Option>, - pub tls: Option, + pub tls: bool, pub complete: bool, pub tx_data: AppLayerTxData, @@ -41,21 +63,14 @@ impl Transaction for MysqlTransaction { } } -impl Default for MysqlTransaction { - fn default() -> Self { - Self::new() - } -} - impl MysqlTransaction { - pub fn new() -> Self { + pub fn new(version: String) -> Self { Self { tx_id: 0, - version: None, - command_code: None, + version, command: None, affected_rows: None, - tls: None, + tls: false, tx_data: AppLayerTxData::new(), complete: false, rows: None, @@ -133,6 +148,81 @@ pub enum MysqlStateProgress { Finished, } +#[derive(Debug)] +struct MysqlStatement { + statement_id: Option, + prepare_stmt: String, + param_cnt: Option, + param_types: Option>, + stmt_long_datas: Option>, + rows: Option>, +} + +impl MysqlStatement { + fn new(prepare_stmt: String) -> Self { + MysqlStatement { + statement_id: None, + prepare_stmt, + param_cnt: None, + param_types: None, + stmt_long_datas: None, + rows: None, + } + } + + fn set_statement_id(&mut self, statement_id: u32) { + self.statement_id = Some(statement_id); + } + + fn set_param_cnt(&mut self, param_cnt: u16) { + self.param_cnt = Some(param_cnt); + } + + fn set_param_types(&mut self, cols: Vec) { + self.param_types = Some(cols); + } + + fn add_stmt_long_datas(&mut self, long_data: StmtLongData) { + if let Some(stmt_long_datas) = &mut self.stmt_long_datas { + stmt_long_datas.push(long_data); + } else { + self.stmt_long_datas = Some(vec![long_data]); + } + } + + fn reset_stmt_long_datas(&mut self) { + self.stmt_long_datas.take(); + } + + fn add_rows(&mut self, rows: Vec) { + if let Some(old_rows) = &mut self.rows { + old_rows.extend(rows); + } else { + self.rows = Some(rows); + } + } + + fn execute(&self, params: Vec) -> Option { + let prepare_stmt = self.prepare_stmt.clone(); + let mut query = String::new(); + if !params.is_empty() + && self.param_cnt.is_some() + && self.param_cnt.unwrap() as usize == params.len() + { + let mut params = params.iter(); + for part in prepare_stmt.split('?') { + query.push_str(part); + if let Some(param) = params.next() { + query.push_str(param); + } + } + Some(query) + } else { + None + } + } +} + #[derive(Debug)] pub struct MysqlState { pub state_data: AppLayerStateData, @@ -146,20 +236,8 @@ pub struct MysqlState { client_flags: u32, version: Option, tls: bool, - command_code: Option, - command: Option, - affected_rows: Option, - rows: Option>, /// stmt prepare - prepare_stmt: Option, - /// stmt prepare response statement id - statement_id: Option, - /// stmt prepare param count - param_cnt: Option, - /// stmt prepare params definition - param_types: Option>, - /// stmt execute long data - stmt_long_datas: Vec, + prepare_stmt: Option, } impl State for MysqlState { @@ -192,15 +270,7 @@ impl MysqlState { client_flags: 0, version: None, tls: false, - command_code: None, - command: None, - affected_rows: None, - rows: None, prepare_stmt: None, - statement_id: None, - param_cnt: None, - param_types: None, - stmt_long_datas: Vec::new(), }; state } @@ -227,23 +297,25 @@ impl MysqlState { self.transactions.iter().find(|tx| tx.tx_id == tx_id + 1) } + fn get_tx_mut(&mut self, tx_id: u64) -> Option<&mut MysqlTransaction> { + self.transactions + .iter_mut() + .find(|tx| tx.tx_id == tx_id + 1) + } + fn set_event(tx: &mut MysqlTransaction, event: MysqlEvent) { tx.tx_data.set_event(event as u8); } - fn new_tx( - &mut self, command_code: Option, command: Option, version: Option, - affected_rows: Option, rows: Option>, tls: bool, - ) -> MysqlTransaction { - let mut tx = MysqlTransaction::new(); + fn new_tx(&mut self, command: String) -> MysqlTransaction { + let mut tx = MysqlTransaction::new(self.version.clone().unwrap_or_default()); self.tx_id += 1; tx.tx_id = self.tx_id; - tx.version = version; - tx.tls = Some(tls); - tx.command_code = command_code; - tx.command = command; - tx.affected_rows = affected_rows; - tx.rows = rows; + tx.tls = self.tls; + if tx.tls { + tx.complete = true; + } + tx.command = Some(command); SCLogDebug!("Creating new transaction.tx_id: {}", tx.tx_id); if self.transactions.len() > unsafe { MYSQL_MAX_TX } + self.tx_index_completed { let mut index = self.tx_index_completed; @@ -259,54 +331,19 @@ impl MysqlState { } tx } + /// Find or create a new transaction /// /// If a new transaction is created, push that into state.transactions before returning &mut to last tx /// If we can't find a transaction and we should not create one, we return None /// The moment when this is called will may impact the logic of transaction tracking (e.g. when a tx is considered completed) - fn find_or_create_tx(&mut self) -> Option<&mut MysqlTransaction> { - match self.state_progress { - MysqlStateProgress::CommandResponseReceived - | MysqlStateProgress::Finished - | MysqlStateProgress::StmtExecResponseReceived => { - let command = self.command.take().map(|cmd| match cmd { - MysqlCommand::Quit => "quit".to_string(), - MysqlCommand::Query { query } => query, - MysqlCommand::Ping => "ping".to_string(), - _ => String::new(), - }); - let rows = self.rows.take(); - let version = self.version.clone(); - let command_code = self.command_code.take(); - let affected_rows = self.affected_rows.take(); - let tls = self.tls; - - let tx = self.new_tx(command_code, command, version, affected_rows, rows, tls); - self.transactions.push_back(tx); - } - MysqlStateProgress::StmtCloseReceived => { - let _ = self.prepare_stmt.take(); - let _ = self.statement_id.take(); - let _ = self.param_types.take(); - } - _ => {} - } - // If we don't need a new transaction, just return the current one - SCLogDebug!("find_or_create state is {:?}", &self.state_progress); + fn create_tx(&mut self, command: String) -> Option<&mut MysqlTransaction> { + let tx = self.new_tx(command); + SCLogDebug!("create state is {:?}", &self.state_progress); + self.transactions.push_back(tx); self.transactions.back_mut() } - fn is_tx_completed(&self) -> bool { - if let MysqlStateProgress::CommandResponseReceived - | MysqlStateProgress::StmtExecResponseReceived - | MysqlStateProgress::Finished = self.state_progress - { - true - } else { - false - } - } - fn request_next_state( &mut self, request: MysqlFEMessage, f: *const Flow, ) -> Option { @@ -329,55 +366,39 @@ impl MysqlState { AppLayerRequestProtocolTLSUpgrade(f); } self.tls = true; + self.create_tx("".to_string()); Some(MysqlStateProgress::Finished) } MysqlFEMessage::AuthRequest => None, MysqlFEMessage::LocalFileData(length) => { if length == 0 { + let tx = self.get_tx_mut(self.tx_id - 1); + if let Some(tx) = tx { + tx.complete = true; + } return Some(MysqlStateProgress::LocalFileContentFinished); } None } - MysqlFEMessage::Request(req) => { - self.command_code = Some(req.command_code); - match req.command { - MysqlCommand::Query { query: _ } => { - self.command = Some(req.command); - return Some(MysqlStateProgress::CommandReceived); - } - MysqlCommand::StmtPrepare { query } => { - self.prepare_stmt = Some(query); - return Some(MysqlStateProgress::StmtPrepareReceived); - } + MysqlFEMessage::Request(req) => match req.command { + MysqlCommand::Query { query: _ } => { + self.create_tx(req.command.to_string()); + return Some(MysqlStateProgress::CommandReceived); + } + MysqlCommand::StmtPrepare { query } => { + self.prepare_stmt = Some(MysqlStatement::new(query)); + return Some(MysqlStateProgress::StmtPrepareReceived); + } - MysqlCommand::StmtExecute { - statement_id, - params, - } => { - if let Some(expected_statement_id) = self.statement_id { + MysqlCommand::StmtExecute { + statement_id: expected_statement_id, + params, + } => { + if let Some(prepare_stmt) = &self.prepare_stmt { + if let Some(statement_id) = prepare_stmt.statement_id { if statement_id == expected_statement_id { - if let Some(params) = params { - if !params.is_empty() - && self.param_cnt.is_some() - && self.param_cnt.unwrap() as usize == params.len() - { - let mut params = params.iter(); - if let Some(prepare_stmt) = &self.prepare_stmt { - // replace `?` to params - let mut query = String::new(); - for part in prepare_stmt.split('?') { - query.push_str(part); - if let Some(param) = params.next() { - query.push_str(param); - } - } - self.command = Some(MysqlCommand::Query { query }); - } else { - SCLogWarning!("Receive stmt exec without stmt prepare or without stmt prepare response"); - return Some(MysqlStateProgress::Finished); - } - } - } + let command = prepare_stmt.execute(params.unwrap_or_default()); + self.create_tx(command.unwrap_or_default()); } else { SCLogWarning!( "Receive stmt exec statement_id {} not equal we need {}", @@ -386,44 +407,43 @@ impl MysqlState { ); return Some(MysqlStateProgress::Finished); } - } else { - self.param_cnt = None; - SCLogWarning!( - "Receive stmt exec without stmt prepare response, should end" - ); - return Some(MysqlStateProgress::Finished); } - return Some(MysqlStateProgress::StmtExecReceived); - } - MysqlCommand::StmtFetch { - statement_id: _, - number_rows: _, - } => { - return Some(MysqlStateProgress::StmtFetchReceived); + } else { + return Some(MysqlStateProgress::Finished); } - MysqlCommand::StmtSendLongData(stmt_long_data) => { - if let Some(statement_id) = self.statement_id { + return Some(MysqlStateProgress::StmtExecReceived); + } + MysqlCommand::StmtFetch { + statement_id: _, + number_rows: _, + } => { + return Some(MysqlStateProgress::StmtFetchReceived); + } + MysqlCommand::StmtSendLongData(stmt_long_data) => { + if let Some(prepare_stmt) = &mut self.prepare_stmt { + if let Some(statement_id) = prepare_stmt.statement_id { if statement_id == stmt_long_data.statement_id { - self.stmt_long_datas.push(stmt_long_data); + prepare_stmt.add_stmt_long_datas(stmt_long_data); } } - None } - MysqlCommand::StmtReset { statement_id } => { - if let Some(expected_statement_id) = self.statement_id { + None + } + MysqlCommand::StmtReset { statement_id } => { + if let Some(prepare_stmt) = &mut self.prepare_stmt { + if let Some(expected_statement_id) = prepare_stmt.statement_id { if statement_id == expected_statement_id { - self.stmt_long_datas.clear(); + prepare_stmt.reset_stmt_long_datas(); } } - return Some(MysqlStateProgress::StmtResetReceived); } - MysqlCommand::StmtClose { statement_id } => { - if let Some(expected_statement_id) = self.statement_id { + return Some(MysqlStateProgress::StmtResetReceived); + } + MysqlCommand::StmtClose { statement_id } => { + if let Some(prepare_stmt) = &self.prepare_stmt { + if let Some(expected_statement_id) = prepare_stmt.statement_id { if statement_id == expected_statement_id { - self.statement_id = None; - self.prepare_stmt = None; - self.stmt_long_datas.clear(); - self.param_types = None; + self.prepare_stmt.take(); } else { SCLogWarning!( "Receive stmt close statement_id {} not equal we need {}", @@ -434,35 +454,37 @@ impl MysqlState { } else { SCLogWarning!("Receive stmt close without stmt prepare response"); } - - return Some(MysqlStateProgress::StmtCloseReceived); - } - MysqlCommand::Quit => { - self.command = Some(req.command); - return Some(MysqlStateProgress::Finished); - } - MysqlCommand::Ping - | MysqlCommand::Debug - | MysqlCommand::ResetConnection - | MysqlCommand::SetOption => { - self.command = Some(req.command); - Some(MysqlStateProgress::CommandReceived) - } - MysqlCommand::Statistics => Some(MysqlStateProgress::StatisticsReceived), - MysqlCommand::FieldList { table: _ } => { - self.command = Some(req.command); - return Some(MysqlStateProgress::FieldListReceived); - } - MysqlCommand::ChangeUser => { - self.command = Some(req.command); - return Some(MysqlStateProgress::ChangeUserReceived); - } - _ => { - SCLogWarning!("Unknown command {}", req.command_code); - return Some(MysqlStateProgress::UnknownCommandReceived); + } else { + SCLogWarning!("Receive stmt close without stmt prepare response"); } + + return Some(MysqlStateProgress::StmtCloseReceived); } - } + MysqlCommand::Quit => { + self.create_tx(req.command.to_string()); + return Some(MysqlStateProgress::Finished); + } + MysqlCommand::Ping + | MysqlCommand::Debug + | MysqlCommand::ResetConnection + | MysqlCommand::SetOption => { + self.create_tx(req.command.to_string()); + Some(MysqlStateProgress::CommandReceived) + } + MysqlCommand::Statistics => Some(MysqlStateProgress::StatisticsReceived), + MysqlCommand::FieldList { table: _ } => { + self.create_tx(req.command.to_string()); + return Some(MysqlStateProgress::FieldListReceived); + } + MysqlCommand::ChangeUser => { + self.create_tx(req.command.to_string()); + return Some(MysqlStateProgress::ChangeUserReceived); + } + _ => { + SCLogWarning!("Unknown command {}", req.command_code); + return Some(MysqlStateProgress::UnknownCommandReceived); + } + }, } } @@ -504,11 +526,9 @@ impl MysqlState { return AppLayerResult::ok(); } - // SCLogDebug!("input length: {}", i.len()); - // If there was gap, check we can sync up again. if self.request_gap { - if !probe(i).is_ok() { + if probe(i).is_err() { SCLogDebug!("Suricata interprets there's a gap in the request"); return AppLayerResult::ok(); } @@ -528,31 +548,28 @@ impl MysqlState { &self.state_progress ); let mut stmt_long_datas = None; - if !self.stmt_long_datas.is_empty() { - stmt_long_datas = Some(self.stmt_long_datas.clone()); + let mut param_cnt = None; + let mut param_types = None; + if let Some(prepare_stmt) = &self.prepare_stmt { + stmt_long_datas = prepare_stmt.stmt_long_datas.clone(); + param_cnt = prepare_stmt.param_cnt; + param_types = prepare_stmt.param_types.clone(); } match MysqlState::state_based_req_parsing( self.state_progress, start, - self.param_cnt, - self.param_types.clone(), + param_cnt, + param_types.clone(), stmt_long_datas, self.client_flags, ) { Ok((rem, request)) => { SCLogDebug!("Request is {:?}", &request); - // SCLogDebug!("remain length: {}", rem.len()); start = rem; if let Some(state) = self.request_next_state(request, flow) { self.state_progress = state; } - let tx_completed = self.is_tx_completed(); - if let Some(tx) = self.find_or_create_tx() { - if tx_completed { - tx.complete = true; - } - } } Err(nom7::Err::Incomplete(_needed)) => { let consumed = i.len() - start.len(); @@ -583,9 +600,7 @@ impl MysqlState { /// /// If there is data from the backend message that Suri should store separately in the State or /// Transaction, that is also done here - fn response_next_state( - &mut self, response: MysqlBEMessage, _f: *const Flow, - ) -> Option { + fn response_next_state(&mut self, response: MysqlBEMessage) -> Option { match response { MysqlBEMessage::HandshakeRequest(req) => { self.version = Some(req.version.clone()); @@ -597,9 +612,25 @@ impl MysqlState { Some(MysqlStateProgress::LocalFileRequestReceived) } MysqlResponsePacket::FieldsList { columns: _ } => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } Some(MysqlStateProgress::FieldListResponseReceived) } MysqlResponsePacket::Statistics => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } Some(MysqlStateProgress::StatisticsResponseReceived) } MysqlResponsePacket::AuthSwithRequest => Some(MysqlStateProgress::Auth), @@ -607,21 +638,63 @@ impl MysqlState { MysqlResponsePacket::Err { .. } => match self.state_progress { MysqlStateProgress::CommandReceived | MysqlStateProgress::TextResulsetContinue => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } Some(MysqlStateProgress::CommandResponseReceived) } MysqlStateProgress::FieldListReceived => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } Some(MysqlStateProgress::FieldListResponseReceived) } MysqlStateProgress::StmtExecReceived | MysqlStateProgress::StmtExecResponseContinue => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } Some(MysqlStateProgress::StmtExecResponseReceived) } MysqlStateProgress::StmtResetReceived => { Some(MysqlStateProgress::StmtResetResponseReceived) } - MysqlStateProgress::ChangeUserReceived => Some(MysqlStateProgress::Finished), + MysqlStateProgress::ChangeUserReceived => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } + Some(MysqlStateProgress::Finished) + } MysqlStateProgress::StmtFetchReceived | MysqlStateProgress::StmtFetchResponseContinue => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } Some(MysqlStateProgress::StmtFetchResponseReceived) } _ => None, @@ -633,11 +706,27 @@ impl MysqlState { } => match self.state_progress { MysqlStateProgress::Auth => Some(MysqlStateProgress::AuthFinished), MysqlStateProgress::CommandReceived => { - self.affected_rows = Some(rows); + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.affected_rows = Some(rows); + tx.complete = true; + } Some(MysqlStateProgress::CommandResponseReceived) } MysqlStateProgress::StmtExecReceived => { - self.affected_rows = Some(rows); + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.affected_rows = Some(rows); + tx.complete = true; + } Some(MysqlStateProgress::StmtExecResponseReceived) } MysqlStateProgress::ChangeUserReceived => { @@ -647,9 +736,38 @@ impl MysqlState { Some(MysqlStateProgress::StmtResetResponseReceived) } MysqlStateProgress::TextResulsetContinue => { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.complete = true; + } Some(MysqlStateProgress::CommandResponseReceived) } MysqlStateProgress::StmtExecResponseContinue => { + let prepare_stmt = self.prepare_stmt.take(); + if self.tx_id > 0 { + let tx = self.get_tx_mut(self.tx_id - 1); + if let Some(tx) = tx { + if let Some(mut prepare_stmt) = prepare_stmt { + let rows = prepare_stmt.rows.take(); + if let Some(rows) = rows { + tx.rows = Some( + rows.into_iter() + .map(|row| match row { + MysqlResultBinarySetRow::Err => String::new(), + MysqlResultBinarySetRow::Text(text) => text, + }) + .collect::>(), + ); + } + + tx.complete = true; + } + } + } Some(MysqlStateProgress::StmtExecResponseReceived) } MysqlStateProgress::StmtFetchResponseContinue => { @@ -663,19 +781,32 @@ impl MysqlState { eof, rows, } => { - let mut rows = rows.into_iter().map(|row| row.texts.join(",")).collect(); - if eof.status_flags != 0x0A { - self.rows = Some(rows); - Some(MysqlStateProgress::CommandResponseReceived) + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) } else { - // MultiStatement - if let Some(state_rows) = self.rows.as_mut() { - state_rows.append(&mut rows); + None + }; + if !rows.is_empty() { + let mut rows = rows.into_iter().map(|row| row.texts.join(",")).collect(); + if let Some(tx) = tx { + if eof.status_flags != 0x0A { + tx.rows = Some(rows); + Some(MysqlStateProgress::CommandResponseReceived) + } else { + // MultiStatement + if let Some(state_rows) = tx.rows.as_mut() { + state_rows.append(&mut rows); + } else { + tx.rows = Some(rows); + } + + Some(MysqlStateProgress::TextResulsetContinue) + } } else { - self.rows = Some(rows); + Some(MysqlStateProgress::Finished) } - - Some(MysqlStateProgress::TextResulsetContinue) + } else { + Some(MysqlStateProgress::CommandResponseReceived) } } MysqlResponsePacket::StmtPrepare { @@ -684,9 +815,14 @@ impl MysqlState { params, .. } => { - self.statement_id = Some(statement_id); - self.param_cnt = Some(num_params); - self.param_types = params; + if let Some(prepare_stmt) = &mut self.prepare_stmt { + prepare_stmt.set_statement_id(statement_id); + prepare_stmt.set_param_cnt(num_params); + if let Some(params) = params { + prepare_stmt.set_param_types(params); + } + } + Some(MysqlStateProgress::StmtPrepareResponseReceived) } MysqlResponsePacket::StmtFetch => { @@ -702,25 +838,37 @@ impl MysqlState { { return Some(MysqlStateProgress::StmtFetchResponseContinue); } - let mut rows = rows - .into_iter() - .map(|row| match row { - MysqlResultBinarySetRow::Err => String::new(), - MysqlResultBinarySetRow::Text(text) => text, - }) - .collect::>(); - if eof.status_flags != 0x0A { - self.rows = Some(rows); - Some(MysqlStateProgress::StmtExecResponseReceived) - } else { - // MultiResulset - if let Some(state_rows) = self.rows.as_mut() { - state_rows.append(&mut rows); + + if !rows.is_empty() { + if eof.status_flags != 0x0A { + let tx = if self.tx_id > 0 { + self.get_tx_mut(self.tx_id - 1) + } else { + None + }; + if let Some(tx) = tx { + tx.rows = Some( + rows.into_iter() + .map(|row| match row { + MysqlResultBinarySetRow::Err => String::new(), + MysqlResultBinarySetRow::Text(text) => text, + }) + .collect::>(), + ); + tx.complete = true; + } + + Some(MysqlStateProgress::StmtExecResponseReceived) } else { - self.rows = Some(rows); - } + // MultiResulset + if let Some(prepare_stmt) = &mut self.prepare_stmt { + prepare_stmt.add_rows(rows); + } - Some(MysqlStateProgress::StmtExecResponseContinue) + Some(MysqlStateProgress::StmtExecResponseContinue) + } + } else { + Some(MysqlStateProgress::StmtExecResponseReceived) } } _ => None, @@ -786,14 +934,14 @@ impl MysqlState { || self.state_progress == StmtExecResponseReceived } - pub fn parse_response(&mut self, flow: *const Flow, i: &[u8]) -> AppLayerResult { + pub fn parse_response(&mut self, i: &[u8]) -> AppLayerResult { // We're not interested in empty responses. if i.is_empty() { return AppLayerResult::ok(); } if self.response_gap { - if !probe(i).is_ok() { + if probe(i).is_err() { SCLogDebug!("Suricata interprets there's a gap in the response"); return AppLayerResult::ok(); } @@ -817,15 +965,9 @@ impl MysqlState { start = rem; SCLogDebug!("Response is {:?}", &response); - if let Some(state) = self.response_next_state(response, flow) { + if let Some(state) = self.response_next_state(response) { self.state_progress = state; } - let tx_completed = self.is_tx_completed(); - if let Some(tx) = self.find_or_create_tx() { - if tx_completed { - tx.complete = true; - } - } } Err(nom7::Err::Incomplete(_needed)) => { let consumed = i.len() - start.len(); @@ -838,11 +980,11 @@ impl MysqlState { ); return AppLayerResult::incomplete(consumed as u32, needed_estimation as u32); } - Err(err) => { - SCLogError!( + Err(_err) => { + SCLogDebug!( "Error while parsing MySQL response, state: {:?} err: {:?}", self.state_progress, - err, + _err, ); return AppLayerResult::err(); } @@ -863,7 +1005,7 @@ impl MysqlState { } /// Probe for a valid mysql message -pub fn probe(i: &[u8]) -> IResult<&[u8], ()> { +fn probe(i: &[u8]) -> IResult<&[u8], ()> { let (i, _) = parse_packet_header(i)?; Ok((i, ())) } @@ -880,8 +1022,8 @@ pub unsafe extern "C" fn rs_mysql_probing_ts( match parse_handshake_response(slice) { Ok(_) => return ALPROTO_MYSQL, Err(nom7::Err::Incomplete(_)) => return ALPROTO_UNKNOWN, - Err(err) => { - SCLogError!("failed to probe request {:?}", err); + Err(_err) => { + SCLogDebug!("failed to probe request {:?}", _err); return ALPROTO_FAILED; } } @@ -899,8 +1041,8 @@ pub unsafe extern "C" fn rs_mysql_probing_tc( match parse_handshake_request(slice) { Ok(_) => return ALPROTO_MYSQL, Err(nom7::Err::Incomplete(_)) => return ALPROTO_UNKNOWN, - Err(err) => { - SCLogError!("failed to probe response {:?}", err); + Err(_err) => { + SCLogDebug!("failed to probe response {:?}", _err); return ALPROTO_FAILED; } } @@ -950,7 +1092,7 @@ pub unsafe extern "C" fn rs_mysql_parse_request( if stream_slice.is_gap() { state_safe.on_request_gap(stream_slice.gap_size()); - } else if !stream_slice.is_empty() { + } else { return state_safe.parse_request(flow, stream_slice.as_slice()); } AppLayerResult::ok() @@ -958,7 +1100,7 @@ pub unsafe extern "C" fn rs_mysql_parse_request( #[no_mangle] pub unsafe extern "C" fn rs_mysql_parse_response( - flow: *const Flow, state: *mut std::os::raw::c_void, pstate: *mut std::os::raw::c_void, + _flow: *const Flow, state: *mut std::os::raw::c_void, pstate: *mut std::os::raw::c_void, stream_slice: StreamSlice, _data: *const std::os::raw::c_void, ) -> AppLayerResult { if stream_slice.is_empty() { @@ -973,8 +1115,8 @@ pub unsafe extern "C" fn rs_mysql_parse_response( if stream_slice.is_gap() { state_safe.on_response_gap(stream_slice.gap_size()); - } else if !stream_slice.is_empty() { - return state_safe.parse_response(flow, stream_slice.as_slice()); + } else { + return state_safe.parse_response(stream_slice.as_slice()); } AppLayerResult::ok() } @@ -1017,44 +1159,6 @@ pub unsafe extern "C" fn rs_mysql_tx_get_alstate_progress( export_tx_data_get!(rs_mysql_get_tx_data, MysqlTransaction); export_state_data_get!(rs_mysql_get_state_data, MysqlState); -/// Detect -/// Get the mysql query -#[no_mangle] -pub unsafe extern "C" fn SCMysqlTxGetCommand( - tx: &mut MysqlTransaction, buf: *mut *const u8, len: *mut u32, -) -> bool { - if let Some(command) = &tx.command { - if !command.is_empty() { - *buf = command.as_ptr(); - *len = command.len() as u32; - return true; - } - } - - false -} - -/// Get the mysql rows at index i -#[no_mangle] -pub unsafe extern "C" fn SCMysqlGetRowsData( - tx: &mut MysqlTransaction, i: u32, buf: *mut *const u8, len: *mut u32, -) -> bool { - if let Some(rows) = &tx.rows { - if !rows.is_empty() { - let index = i as usize; - if let Some(row) = rows.get(index) { - if !row.is_empty() { - *buf = row.as_ptr(); - *len = row.len() as u32; - return true; - } - } - } - } - - false -} - // Parser name as a C style string. const PARSER_NAME: &[u8] = b"mysql\0"; @@ -1124,6 +1228,7 @@ pub unsafe extern "C" fn rs_mysql_register_parser() { SCLogError!("Invalid value for mysql.max-tx"); } } + AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_MYSQL); } else { SCLogDebug!("Protocol detector and parser disabled for MYSQL."); } diff --git a/rust/src/mysql/parser.rs b/rust/src/mysql/parser.rs index 23d07b96c52e..d74bbcaed5eb 100644 --- a/rust/src/mysql/parser.rs +++ b/rust/src/mysql/parser.rs @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Open Information Security Foundation +/* Copyright (C) 2024 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -15,7 +15,7 @@ * 02110-1301, USA. */ -// Author: Kotodian +// Author: QianKaiLin //! MySQL nom parsers @@ -29,7 +29,8 @@ use nom7::{ }, IResult, }; -use num::ToPrimitive; +use num::{FromPrimitive, ToPrimitive}; +use suricata_derive::EnumStringU8; #[allow(dead_code)] pub const CLIENT_LONG_PASSWORD: u32 = BIT_U32!(0); @@ -37,7 +38,6 @@ pub const CLIENT_LONG_PASSWORD: u32 = BIT_U32!(0); pub const CLIENT_FOUND_ROWS: u32 = BIT_U32!(1); #[allow(dead_code)] pub const CLIENT_LONG_FLAG: u32 = BIT_U32!(2); -#[allow(dead_code)] const CLIENT_CONNECT_WITH_DB: u32 = BIT_U32!(3); #[allow(dead_code)] const CLIENT_NO_SCHEMA: u32 = BIT_U32!(4); @@ -49,11 +49,9 @@ const CLIENT_ODBC: u32 = BIT_U32!(6); const CLIENT_LOCAL_FILES: u32 = BIT_U32!(7); #[allow(dead_code)] const CLIENT_IGNORE_SPACE: u32 = BIT_U32!(8); -#[allow(dead_code)] const CLIENT_PROTOCOL_41: u32 = BIT_U32!(9); #[allow(dead_code)] const CLIENT_INTERACTIVE: u32 = BIT_U32!(10); -#[allow(dead_code)] pub const CLIENT_SSL: u32 = BIT_U32!(11); #[allow(dead_code)] pub const CLIENT_IGNORE_SIGPIPE: u32 = BIT_U32!(12); @@ -79,7 +77,6 @@ pub const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: u32 = BIT_U32!(21); pub const CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: u32 = BIT_U32!(22); #[allow(dead_code)] pub const CLIENT_SESSION_TRACK: u32 = BIT_U32!(23); -#[allow(dead_code)] pub const CLIENT_DEPRECATE_EOF: u32 = BIT_U32!(24); #[allow(dead_code)] pub const CLIENT_OPTIONAL_RESULTSET_METADATA: u32 = BIT_U32!(25); @@ -101,8 +98,8 @@ pub const FIELD_FLAGS_UNSIGNED: u32 = BIT_U32!(5); const PAYLOAD_MAX_LEN: u32 = 0xffffff; -#[derive(Debug, Clone, Copy)] #[repr(u8)] +#[derive(Debug, Clone, Copy, EnumStringU8, FromPrimitive)] pub enum FieldType { Decimal = 0, Tiny = 1, @@ -142,45 +139,12 @@ pub enum FieldType { Geometry = 255, } -impl From for FieldType { - fn from(value: u8) -> Self { - match value { - 0 => Self::Decimal, - 1 => Self::Tiny, - 2 => Self::Short, - 3 => Self::Long, - 4 => Self::Float, - 5 => Self::Double, - 6 => Self::NULL, - 7 => Self::Timestamp, - 8 => Self::LongLong, - 9 => Self::Int24, - 10 => Self::Date, - 11 => Self::Time, - 12 => Self::Datetime, - 13 => Self::Year, - 15 => Self::Varchar, - 16 => Self::Bit, - 17 => Self::Timestamp2, - 18 => Self::Datetime2, - 19 => Self::Time2, - 20 => Self::Array, - 242 => Self::Vector, - 243 => Self::Invalid, - 244 => Self::Bool, - 245 => Self::Json, - 246 => Self::NewDecimal, - 247 => Self::Enum, - 248 => Self::Set, - 249 => Self::TinyBlob, - 250 => Self::MediumBlob, - 251 => Self::LongBlob, - 252 => Self::Blob, - 253 => Self::VarString, - 254 => Self::String, - 255 => Self::Geometry, - _ => Self::Unknown, - } +#[inline] +fn parse_field_type(field_type: u8) -> FieldType { + if let Some(f) = FromPrimitive::from_u8(field_type) { + f + } else { + FieldType::Invalid } } @@ -252,6 +216,17 @@ pub enum MysqlCommand { }, } +impl std::fmt::Display for MysqlCommand { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + MysqlCommand::Quit => write!(f, "quit"), + MysqlCommand::Query { query } => write!(f, "{}", query), + MysqlCommand::Ping => write!(f, "ping"), + _ => write!(f, ""), + } + } +} + #[derive(Debug, Clone)] pub struct MysqlColumnDefinition { pub catalog: String, @@ -316,10 +291,6 @@ pub struct MysqlHandshakeResponse { pub zstd_compression_level: Option, } -pub const SHA2_PASSWORD_REQUEST_PUBLIC_KEY: u8 = 2; -pub const SHA2_PASSWORD_FAST_AUTH_SUCCESS: u8 = 3; -pub const SHA2_PASSWORD_PERFORM_FULL_AUTH: u8 = 3; - #[derive(Debug)] pub struct MysqlAuthSwtichRequest { pub plugin_name: String, @@ -449,6 +420,8 @@ pub fn parse_packet_header(i: &[u8]) -> IResult<&[u8], MysqlPacket> { let mut payload_len: usize = 0; let mut rem = i; let mut pkt_num = None; + // Loop until payload length is less than 0xffffff + // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_packets.html#sect_protocol_basic_packets_sending_mt_16mb loop { let (i, pkt_len) = verify(le_u24, |&pkt_len| -> bool { pkt_len <= PAYLOAD_MAX_LEN })(rem)?; payload_len += pkt_len as usize; @@ -460,6 +433,7 @@ pub fn parse_packet_header(i: &[u8]) -> IResult<&[u8], MysqlPacket> { rem = i; // payload extend rem_payload payload.extend_from_slice(rem_payload); + if pkt_len < PAYLOAD_MAX_LEN { break; } @@ -531,7 +505,7 @@ fn parse_query_cmd(i: &[u8], client_flags: u32) -> IResult<&[u8], MysqlCommand> String::from_utf8_lossy(s).to_string() })(i)?; - Ok((i, (field_type.into(), flags != 0))) + Ok((i, (parse_field_type(field_type), flags != 0))) }, ), )(i)?; @@ -763,22 +737,19 @@ fn parse_stmt_execute_cmd( Ok((ch, name)) })(ch)?; - Ok((ch, (field_type.into(), flags != 0))) + Ok((ch, (parse_field_type(field_type), flags != 0))) }, ), )(i)?; let param_types = if let Some(new_param_types) = new_param_types { Some(new_param_types) } else { - match param_types { - Some(param_types) => Some( - param_types - .iter() - .map(|param_type| (param_type.field_type, param_type.flags != 0)) - .collect(), - ), - None => None, - } + param_types.map(|param_types| { + param_types + .iter() + .map(|param_type| (param_type.field_type, param_type.flags != 0)) + .collect() + }) }; let consumed = old.len() - i.len(); @@ -1080,7 +1051,7 @@ fn parse_column_definition(i: &[u8]) -> IResult<&[u8], MysqlColumnDefinition> { let (i, decimals) = be_u8(i)?; let (_, _filter) = take(2_u32)(i)?; - let field_type = field_type.into(); + let field_type = parse_field_type(field_type); Ok(( rem, @@ -1122,7 +1093,7 @@ fn parse_resultset_row_texts(i: &[u8]) -> IResult<&[u8], Vec> { length -= consumed; } - Ok((rem, texts)) + Ok((&[], texts)) } fn parse_resultset_row(i: &[u8]) -> IResult<&[u8], MysqlResultSetRow> { @@ -2002,9 +1973,9 @@ pub fn parse_field_list_response(i: &[u8]) -> IResult<&[u8], MysqlResponse> { let n_cols = response_code; let (i, columns) = many_m_n(n_cols as usize, n_cols as usize, parse_column_definition)(rem)?; - let (i, _) = parse_eof_packet(i)?; + let (_, _) = parse_eof_packet(i)?; Ok(( - i, + rem, MysqlResponse { item: MysqlResponsePacket::FieldsList { columns: Some(columns), @@ -2042,7 +2013,7 @@ pub fn parse_stmt_prepare_response(i: &[u8], _client_flags: u32) -> IResult<&[u8 } })?; // should use remain - let (i, fields) = cond( + let (_, fields) = cond( num_columns > 0, many_till(parse_column_definition, parse_eof_packet), )(i) @@ -2151,16 +2122,6 @@ mod test { use super::*; - #[test] - fn test_parse_packet_header() { - let pkt: &[u8] = &[0x07, 0x00, 0x00, 0x03]; - let (rem, packet_header) = parse_packet_header(pkt).unwrap(); - - assert!(rem.is_empty()); - assert_eq!(packet_header.pkt_len, 7); - assert_eq!(packet_header.pkt_num, 3); - } - #[test] fn test_parse_handshake_request() { let pkt: &[u8] = &[ @@ -2244,25 +2205,6 @@ mod test { assert!(rem.is_empty()); } - #[test] - fn test_parse_auth_response() { - let pkt: &[u8] = &[0x02, 0x00, 0x00, 0x02, 0x01, 0x03]; - - let (rem, auth_response) = parse_auth_response(pkt).unwrap(); - - assert!(rem.is_empty()); - let item = auth_response.item; - if let MysqlResponsePacket::AuthMoreData { data } = item { - assert_eq!(data, SHA2_PASSWORD_FAST_AUTH_SUCCESS); - } else { - unreachable!(); - } - } - - //TODO: test auth switch - #[test] - fn test_parse_auth_switch_request() {} - #[test] fn test_parse_query_request() { let pkt: &[u8] = &[ @@ -2305,46 +2247,18 @@ mod test { } else { unreachable!(); } - let pkt: &[u8] = &[ - 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x52, 0x6f, - 0x77, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x3a, 0x20, 0x31, 0x20, - 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x3a, 0x20, 0x31, 0x20, 0x20, 0x57, - 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x20, 0x30, - ]; - - let (rem, _) = parse_response(pkt).unwrap(); - assert!(rem.is_empty()); - - let pkt: &[u8] = &[ - 0x30, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x52, 0x6f, - 0x77, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x3a, 0x20, 0x31, 0x20, - 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x3a, 0x20, 0x31, 0x20, 0x20, 0x57, - 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x20, 0x30, - ]; - let (rem, _) = parse_response(pkt).unwrap(); - assert!(rem.is_empty()); } - //TODO: test response error #[test] - fn test_parse_err_response() { + fn test_parse_text_resultset_response() { let pkt: &[u8] = &[ - 51, 0, 0, 0, 255, 134, 4, 35, 48, 56, 83, 48, 49, 71, 111, 116, 32, 97, 110, 32, 101, - 114, 114, 111, 114, 32, 114, 101, 97, 100, 105, 110, 103, 32, 99, 111, 109, 109, 117, - 110, 105, 99, 97, 116, 105, 111, 110, 32, 112, 97, 99, 107, 101, 116, 115, - ]; - let (rem, _) = parse_response(pkt).unwrap(); - assert!(rem.is_empty()); - } - - #[test] - fn test_parse_resultset_response() { - let pkt: &[u8] = &[ - 0x01, 0x00, 0x00, 0x01, 0x01, 0x1f, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, - 0x00, 0x00, 0x09, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x28, 0x29, 0x00, 0x0c, - 0xff, 0x00, 0x14, 0x00, 0x00, 0x00, 0xfd, 0x01, 0x00, 0x1f, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x04, 0x05, 0x39, 0x2e, - 0x30, 0x2e, 0x31, 0x05, 0x00, 0x00, 0x05, 0xfe, 0x00, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x01, // Column count + 0x1f, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x09, 0x56, 0x45, + 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x28, 0x29, 0x00, 0x0c, 0xff, 0x00, 0x14, 0x00, 0x00, + 0x00, 0xfd, 0x01, 0x00, 0x1f, 0x00, 0x00, // Field packet + 0x05, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x02, 0x00, // EOF + 0x06, 0x00, 0x00, 0x04, 0x05, 0x39, 0x2e, 0x30, 0x2e, 0x31, // Row packet + 0x05, 0x00, 0x00, 0x05, 0xfe, 0x00, 0x00, 0x02, 0x00, // EOF ]; let (rem, response) = parse_response(pkt).unwrap(); @@ -2359,64 +2273,7 @@ mod test { } = item { assert_eq!(n_cols, 1); - } else { - unreachable!(); } - - let pkt: &[u8] = &[ - 0x01, 0x00, 0x00, 0x01, 0x01, 0x4d, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x09, 0x73, 0x79, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x73, 0x09, 0x73, 0x79, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x09, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x0c, 0xff, 0x00, 0xfc, 0x02, 0x00, 0x00, 0xfd, 0x0c, 0x40, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, - 0x04, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x07, 0x00, 0x00, 0x05, 0x06, 0x73, 0x75, - 0x6e, 0x6a, 0x69, 0x65, 0x04, 0x00, 0x00, 0x06, 0x03, 0x6c, 0x77, 0x77, 0x08, 0x00, - 0x00, 0x07, 0x07, 0x6b, 0x61, 0x72, 0x65, 0x6b, 0x69, 0x69, 0x03, 0x00, 0x00, 0x08, - 0x02, 0x6d, 0x75, 0x04, 0x00, 0x00, 0x09, 0x03, 0x6c, 0x64, 0x62, 0x07, 0x00, 0x00, - 0x0a, 0x06, 0x71, 0x69, 0x75, 0x71, 0x69, 0x75, 0x0c, 0x00, 0x00, 0x0b, 0x0b, 0x44, - 0x6f, 0x6e, 0x67, 0x77, 0x65, 0x6e, 0x74, 0x6f, 0x6e, 0x67, 0x08, 0x00, 0x00, 0x0c, - 0x07, 0x4b, 0x65, 0x79, 0x75, 0x72, 0x75, 0x69, 0x0b, 0x00, 0x00, 0x0d, 0x0a, 0x31, - 0x32, 0x40, 0x20, 0xe8, 0x90, 0xa8, 0xe8, 0xbe, 0xbe, 0x16, 0x00, 0x00, 0x0e, 0x15, - 0xe8, 0xbf, 0x99, 0xe6, 0x98, 0xaf, 0xe4, 0xb8, 0x80, 0xe4, 0xb8, 0xaa, 0xe7, 0x94, - 0xa8, 0xe6, 0x88, 0xb7, 0xe5, 0x90, 0x8d, 0x05, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, - 0x02, 0x00, - ]; - - let (rem, _) = parse_response(pkt).unwrap(); - assert!(rem.is_empty()); - - let pkt: &[u8] = &[ - 0x0c, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, - 0x3f, 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x03, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, - 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x04, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x6f, 0x00, 0x00, 0x05, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x13, 0x73, 0x79, 0x73, 0x5f, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x65, 0x6e, 0x75, - 0x73, 0x13, 0x73, 0x79, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x73, 0x10, 0x73, 0x79, 0x73, 0x5f, 0x62, 0x61, - 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x5f, 0x69, 0x64, 0x10, 0x73, 0x79, 0x73, - 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x5f, 0x69, 0x64, 0x0c, - 0x3f, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x23, 0x50, 0x00, 0x00, 0x00, 0x83, 0x00, - 0x00, 0x06, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x13, 0x73, - 0x79, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6d, - 0x65, 0x6e, 0x75, 0x73, 0x13, 0x73, 0x79, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x73, 0x1a, 0x73, 0x79, 0x73, - 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x1a, 0x73, 0x79, 0x73, 0x5f, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x08, 0x23, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, - 0x02, 0x00, - ]; - - let (rem, _response) = parse_stmt_prepare_response(pkt, 0).unwrap(); - assert!(rem.is_empty()); } #[test] @@ -2468,953 +2325,6 @@ mod test { assert_eq!(request.command_code, 0x16); } - #[test] - fn test_parse_prepare_stmt_response() { - let pkt: &[u8] = &[ - 0x0c, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, - 0x3f, 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x26, 0x00, 0x00, 0x04, - 0x03, 0x64, 0x65, 0x66, 0x04, 0x74, 0x65, 0x73, 0x74, 0x04, 0x74, 0x65, 0x73, 0x74, - 0x04, 0x74, 0x65, 0x73, 0x74, 0x02, 0x69, 0x64, 0x02, 0x69, 0x64, 0x0c, 0x3f, 0x00, - 0x0a, 0x00, 0x00, 0x00, 0x03, 0x23, 0x42, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x05, - 0x03, 0x64, 0x65, 0x66, 0x04, 0x74, 0x65, 0x73, 0x74, 0x04, 0x74, 0x65, 0x73, 0x74, - 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, - 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x0c, 0xff, 0x00, 0xfc, 0x03, - 0x00, 0x00, 0xfd, 0x01, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0xfe, 0x00, - 0x00, 0x02, 0x00, - ]; - - let (rem, response) = parse_stmt_prepare_response(pkt, 0).unwrap(); - assert!(rem.is_empty()); - - let item = response.item; - if let MysqlResponsePacket::StmtPrepare { - statement_id, - num_params, - .. - } = item - { - assert_eq!(statement_id, 1); - assert_eq!(num_params, 1); - } else { - unreachable!(); - } - let pkt: &[u8] = &[ - 0x0c, 0x00, 0x00, 0x01, 0x00, 0x6e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, - 0x3f, 0x00, 0x0c, 0xff, 0x00, 0x68, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x03, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, - 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x00, 0x04, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, - 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00, 0x17, - 0x00, 0x00, 0x05, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x0c, - 0xff, 0x00, 0xfc, 0xff, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x06, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x0c, 0xff, - 0x00, 0xfc, 0xff, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x17, 0x00, 0x00, - 0x07, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x0c, 0xff, 0x00, - 0xfc, 0xff, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x17, 0x00, 0x00, 0x08, - 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x0c, 0xff, 0x00, 0xfc, - 0xff, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x17, 0x00, 0x00, 0x09, 0x03, - 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, - 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x0a, 0x03, 0x64, - 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, - 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x0b, 0xfe, 0x00, 0x00, - 0x03, 0x00, - ]; - - let (rem, _response) = parse_stmt_prepare_response(pkt, 0).unwrap(); - assert!(rem.is_empty()); - - let pkt: &[u8] = &[ - 0x0c, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, - 0x3f, 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x03, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, 0x3f, - 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x04, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x6f, 0x00, 0x00, 0x05, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x13, 0x73, 0x79, 0x73, 0x5f, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x65, 0x6e, 0x75, - 0x73, 0x13, 0x73, 0x79, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x73, 0x10, 0x73, 0x79, 0x73, 0x5f, 0x62, 0x61, - 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x5f, 0x69, 0x64, 0x10, 0x73, 0x79, 0x73, - 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x5f, 0x69, 0x64, 0x0c, - 0x3f, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x23, 0x50, 0x00, 0x00, 0x00, 0x83, 0x00, - 0x00, 0x06, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x13, 0x73, - 0x79, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6d, - 0x65, 0x6e, 0x75, 0x73, 0x13, 0x73, 0x79, 0x73, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x65, 0x6e, 0x75, 0x73, 0x1a, 0x73, 0x79, 0x73, - 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x1a, 0x73, 0x79, 0x73, 0x5f, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x08, 0x23, 0x50, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, - 0x02, 0x00, - ]; - - let (rem, _response) = parse_stmt_prepare_response(pkt, 0).unwrap(); - assert!(rem.is_empty()); - - let pkt: &[u8] = &[ - 0x0c, 0x00, 0x00, 0x01, 0x00, 0xf3, 0x01, 0x00, 0x00, 0x29, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x01, - 0x3f, 0x00, 0x0c, 0x3f, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x4f, 0x00, 0x00, 0x04, - 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, - 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x02, 0x69, 0x64, 0x02, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x08, 0x07, 0x42, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x05, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x0c, 0x3f, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x06, - 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, - 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x0c, 0x3f, - 0x00, 0x13, 0x00, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, - 0x07, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, - 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x0c, - 0x3f, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0c, 0x88, 0x40, 0x00, 0x00, 0x00, 0x53, 0x00, - 0x00, 0x08, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x04, 0x75, 0x75, 0x69, 0x64, 0x04, 0x75, 0x75, - 0x69, 0x64, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x09, 0x50, 0x00, 0x00, - 0x00, 0x53, 0x00, 0x00, 0x09, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, - 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x01, - 0x10, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x0a, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x08, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x69, 0x64, 0x08, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, - 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x21, 0x10, 0x00, 0x00, - 0x00, 0x61, 0x00, 0x00, 0x0b, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, - 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0b, 0x70, 0x72, 0x6f, 0x64, - 0x75, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x21, - 0x10, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x0c, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x74, - 0x61, 0x67, 0x03, 0x74, 0x61, 0x67, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, - 0x01, 0x10, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x0d, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x08, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x0c, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x91, 0x10, 0x00, - 0x00, 0x00, 0x55, 0x00, 0x00, 0x0e, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, - 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, - 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x05, 0x73, 0x63, 0x6f, - 0x72, 0x65, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x0c, 0x3f, 0x00, 0x0a, 0x00, 0x00, - 0x00, 0x03, 0x21, 0x10, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0f, 0x03, 0x64, 0x65, - 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, - 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, - 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x0c, - 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x21, 0x10, 0x00, 0x00, 0x00, 0x53, 0x00, - 0x00, 0x10, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x04, 0x70, 0x6f, - 0x72, 0x74, 0x0c, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x21, 0x10, 0x00, 0x00, - 0x00, 0x4f, 0x00, 0x00, 0x11, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, - 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x02, 0x69, 0x70, 0x02, 0x69, - 0x70, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x01, 0x10, 0x00, 0x00, 0x00, - 0x5d, 0x00, 0x00, 0x12, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, - 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, - 0x0c, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x91, 0x10, 0x00, 0x00, 0x00, 0x5d, - 0x00, 0x00, 0x13, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, - 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x5f, 0x69, 0x64, 0x09, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x0c, - 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, - 0x00, 0x14, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x01, 0x10, 0x00, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x15, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, - 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x08, 0x6f, 0x72, 0x67, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x08, 0x6f, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x0c, - 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x01, 0x10, 0x00, 0x00, 0x00, 0x5d, 0x00, - 0x00, 0x16, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x6f, 0x72, 0x67, 0x5f, 0x73, 0x74, 0x61, - 0x66, 0x66, 0x09, 0x6f, 0x72, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x66, 0x66, 0x0c, 0xff, - 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, - 0x17, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, - 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0b, 0x73, 0x74, 0x61, 0x66, 0x66, 0x5f, 0x70, 0x68, - 0x6f, 0x6e, 0x65, 0x0b, 0x73, 0x74, 0x61, 0x66, 0x66, 0x5f, 0x70, 0x68, 0x6f, 0x6e, - 0x65, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x01, 0x10, 0x00, 0x00, 0x00, - 0x57, 0x00, 0x00, 0x18, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, - 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, - 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x19, 0x03, 0x64, 0x65, - 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, - 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, - 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x0b, 0x6f, 0x72, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0b, - 0x6f, 0x72, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0c, 0xff, 0x00, - 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x1a, - 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, - 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x08, - 0x70, 0x6f, 0x73, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, - 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x1b, 0x03, 0x64, 0x65, - 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, - 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, - 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x0a, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x67, - 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0c, 0xff, 0x00, 0xfc, 0x03, - 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x1c, 0x03, 0x64, - 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x08, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x1d, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, - 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x64, 0x65, 0x70, - 0x61, 0x72, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, - 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x1e, 0x03, 0x64, 0x65, 0x66, - 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, - 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, - 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x0c, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x0c, - 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x0c, 0xff, - 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, - 0x1f, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, - 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x05, 0x65, 0x6d, - 0x61, 0x69, 0x6c, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x57, 0x00, 0x00, 0x20, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, - 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, - 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x06, 0x63, 0x68, 0x61, - 0x72, 0x67, 0x65, 0x06, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x0c, 0xff, 0x00, 0xfc, - 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x21, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x04, 0x70, 0x61, 0x72, 0x74, 0x04, 0x70, 0x61, 0x72, 0x74, 0x0c, - 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, - 0x00, 0x22, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x06, - 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x23, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0c, 0xff, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x24, 0x03, 0x64, - 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x03, 0x75, 0x72, 0x6c, 0x03, 0x75, 0x72, 0x6c, 0x0c, 0xff, 0x00, 0xfc, - 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x25, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x03, 0x6e, 0x65, 0x74, 0x03, 0x6e, 0x65, 0x74, 0x0c, 0x3f, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xf5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x26, - 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, - 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x09, 0x70, 0x61, 0x73, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x09, 0x70, 0x61, 0x73, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x0c, 0x3f, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x08, 0x21, 0x10, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x27, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x07, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x07, 0x61, 0x70, - 0x70, 0x72, 0x6f, 0x76, 0x65, 0x0c, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x21, - 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x28, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x07, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x0c, 0x3f, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x21, 0x10, 0x00, 0x00, 0x00, 0x59, - 0x00, 0x00, 0x29, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, - 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x0c, 0xff, 0x00, 0xfc, 0x03, - 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x2a, 0x03, 0x64, - 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x0c, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x57, 0x00, 0x00, 0x2b, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, - 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, - 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x06, 0x61, 0x70, 0x70, 0x5f, - 0x69, 0x64, 0x06, 0x61, 0x70, 0x70, 0x5f, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x0a, 0x00, - 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x2c, 0x03, 0x64, - 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x11, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x11, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x0c, 0x3f, - 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x2d, 0xfe, 0x00, 0x00, 0x02, 0x00, - ]; - - let (rem, _response) = parse_stmt_prepare_response(pkt, 0).unwrap(); - assert!(rem.is_empty()); - } - - // #[test] - // let pkt: &[u8] = &[ - // 22, 0, 0, 0, 23, 42, 2, 0, 0, 0, 1, 0, 0, 0, 0, 1, 8, 128, 16, 39, 0, 0, 0, 0, 0, 0, 5, - // 0, 0, 0, 25, 42, 2, 0, 0, 194, 0, 0, 0, 22, 83, 69, 76, 69, 67, 84, 32, 96, 117, 117, - // 105, 100, 96, 44, 96, 112, 97, 114, 101, 110, 116, 95, 105, 100, 96, 44, 96, 112, 97, - // 116, 104, 96, 44, 96, 110, 97, 109, 101, 96, 44, 96, 109, 101, 110, 117, 95, 108, 101, - // 118, 101, 108, 96, 44, 96, 104, 105, 100, 100, 101, 110, 96, 44, 96, 115, 111, 114, - // 116, 96, 32, 70, 82, 79, 77, 32, 96, 115, 121, 115, 95, 98, 97, 115, 101, 95, 109, 101, - // 110, 117, 115, 96, 32, 87, 72, 69, 82, 69, 32, 96, 115, 121, 115, 95, 98, 97, 115, 101, - // 95, 109, 101, 110, 117, 115, 96, 46, 96, 117, 117, 105, 100, 96, 32, 73, 78, 32, 40, - // 63, 44, 63, 44, 63, 44, 63, 41, 32, 65, 78, 68, 32, 96, 115, 121, 115, 95, 98, 97, 115, - // 101, 95, 109, 101, 110, 117, 115, 96, 46, 96, 100, 101, 108, 101, 116, 101, 100, 95, - // 97, 116, 96, 32, 73, 83, 32, 78, 85, 76, 76, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, - // 115, 111, 114, 116, 32, 97, 115, 99, - // - // - // let (rem, _request) = parse_request(pkt, Some(9), None, None, 1811085).unwrap(); - // assert!(rem.is_empty()); - // } - - // #[test] - // fn test_parse_execute_stmt_request() { - // let pkt: &[u8] = &[ - // 0x16, 0x00, 0x00, 0x00, 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - // 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // ]; - - // let (rem, request) = parse_request(pkt, Some(1), None, 0).unwrap(); - - // assert!(rem.is_empty()); - // assert_eq!(request.command_code, 0x17); - - // let command = request.command; - - // if let MysqlCommand::StmtExecute { - // statement_id, - // params, - // } = command - // { - // assert_eq!(statement_id, 1); - // assert_ne!(params, None); - - // let params = params.unwrap(); - // assert_eq!(params.len(), 1); - - // let mut params = params.iter(); - // assert_eq!(params.next(), Some(&"0".to_string())); - // } else { - // unreachable!(); - // } - - // let pkt: &[u8] = &[ - // 0x7c, 0x00, 0x00, 0x00, 0x17, 0x71, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - // 0x00, 0x00, 0x01, 0xfe, 0x00, 0x08, 0x00, 0x08, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, - // 0x00, 0xfe, 0x00, 0x08, 0x80, 0x08, 0x80, 0x17, 0x32, 0x30, 0x32, 0x34, 0x2d, 0x30, - // 0x39, 0x2d, 0x30, 0x34, 0x20, 0x31, 0x30, 0x3a, 0x31, 0x30, 0x3a, 0x31, 0x35, 0x2e, - // 0x38, 0x34, 0x35, 0x87, 0xc1, 0xd7, 0x66, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, - // 0x38, 0x2e, 0x32, 0x37, 0x07, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x0a, 0x57, - // 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x31, 0x30, 0x04, 0x45, 0x64, 0x67, 0x65, - // 0x69, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x75, 0x00, 0x00, 0x00, 0x00, - // 0x00, 0x00, - // ]; - - // let (rem, request) = parse_request(pkt, Some(9), None, 0).unwrap(); - - // assert!(rem.is_empty()); - // assert_eq!(request.command_code, 0x17); - - // let pkt: &[u8] = &[ - // 0x20, 0x00, 0x00, 0x00, 0x17, 0x70, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - // 0x00, 0x01, 0x08, 0x80, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // ]; - - // let (rem, request) = parse_request(pkt, Some(2), None, 0).unwrap(); - - // assert!(rem.is_empty()); - // assert_eq!(request.command_code, 0x17); - - // // let pkt: &[u8] = &[ - // // 32, 0, 0, 0, 23, 110, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 8, 128, 8, 0, 2, 145, 1, 0, 0, 0, - // // 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 25, 110, 0, 0, 0, 18, 0, 0, 0, 3, 83, 84, 65, - // // 82, 84, 32, 84, 82, 65, 78, 83, 65, 67, 84, 73, 79, 78, - // // ]; - // // let (rem, request) = parse_request(pkt, Some(23), None, CLIENT_QUERY_ATTRIBUTES).unwrap(); - - // // assert!(rem.is_empty()); - // } - - #[test] - fn test_parse_execute_stmt_response() { - let pkt: &[u8] = &[ - 1, 0, 0, 1, 30, 65, 0, 0, 2, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, - 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, - 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 2, 105, 100, - 2, 105, 100, 12, 63, 0, 20, 0, 0, 0, 8, 35, 66, 0, 0, 0, 69, 0, 0, 3, 3, 100, 101, 102, - 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, - 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, - 101, 114, 95, 97, 112, 112, 4, 110, 97, 109, 101, 4, 110, 97, 109, 101, 12, 255, 0, - 252, 3, 0, 0, 253, 9, 80, 0, 0, 0, 69, 0, 0, 4, 3, 100, 101, 102, 19, 115, 101, 110, - 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, - 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, - 112, 112, 4, 108, 111, 103, 111, 4, 108, 111, 103, 111, 12, 255, 0, 252, 3, 0, 0, 253, - 1, 16, 0, 0, 0, 81, 0, 0, 5, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, - 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, - 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 115, 104, - 111, 114, 116, 95, 110, 97, 109, 101, 10, 115, 104, 111, 114, 116, 95, 110, 97, 109, - 101, 12, 255, 0, 0, 1, 0, 0, 253, 8, 64, 0, 0, 0, 91, 0, 0, 6, 3, 100, 101, 102, 19, - 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, - 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, - 114, 95, 97, 112, 112, 15, 115, 121, 115, 95, 112, 114, 111, 100, 117, 99, 101, 114, - 95, 105, 100, 15, 115, 121, 115, 95, 112, 114, 111, 100, 117, 99, 101, 114, 95, 105, - 100, 12, 63, 0, 20, 0, 0, 0, 8, 8, 64, 0, 0, 0, 71, 0, 0, 7, 3, 100, 101, 102, 19, 115, - 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, - 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, - 97, 112, 112, 5, 97, 114, 101, 97, 115, 5, 97, 114, 101, 97, 115, 12, 255, 0, 0, 16, 0, - 0, 253, 0, 0, 0, 0, 0, 75, 0, 0, 8, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, - 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, - 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 7, 116, - 97, 114, 103, 101, 116, 115, 7, 116, 97, 114, 103, 101, 116, 115, 12, 255, 0, 252, 3, - 0, 0, 253, 0, 0, 0, 0, 0, 77, 0, 0, 9, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, - 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, - 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 8, - 110, 116, 100, 95, 105, 109, 103, 115, 8, 110, 116, 100, 95, 105, 109, 103, 115, 12, - 255, 0, 252, 255, 3, 0, 252, 16, 0, 0, 0, 0, 85, 0, 0, 10, 3, 100, 101, 102, 19, 115, - 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, - 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, - 97, 112, 112, 12, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 115, 12, 97, 112, - 112, 108, 105, 99, 97, 116, 105, 111, 110, 115, 12, 255, 0, 252, 255, 3, 0, 252, 16, 0, - 0, 0, 0, 85, 0, 0, 11, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, - 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, - 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 12, 115, 121, 115, - 95, 99, 108, 111, 117, 100, 95, 105, 100, 12, 115, 121, 115, 95, 99, 108, 111, 117, - 100, 95, 105, 100, 12, 63, 0, 20, 0, 0, 0, 8, 1, 16, 0, 0, 0, 83, 0, 0, 12, 3, 100, - 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, - 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, - 112, 104, 101, 114, 95, 97, 112, 112, 11, 116, 101, 110, 97, 110, 116, 95, 110, 97, - 109, 101, 11, 116, 101, 110, 97, 110, 116, 95, 110, 97, 109, 101, 12, 255, 0, 252, 3, - 0, 0, 253, 1, 16, 0, 0, 0, 65, 0, 0, 13, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, - 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, - 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 2, - 105, 112, 2, 105, 112, 12, 255, 0, 80, 0, 0, 0, 253, 0, 0, 0, 0, 0, 69, 0, 0, 14, 3, - 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, - 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, - 112, 104, 101, 114, 95, 97, 112, 112, 4, 112, 111, 114, 116, 4, 112, 111, 114, 116, 12, - 63, 0, 11, 0, 0, 0, 3, 0, 0, 0, 0, 0, 83, 0, 0, 15, 3, 100, 101, 102, 19, 115, 101, - 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, - 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, - 112, 112, 11, 100, 111, 109, 97, 105, 110, 95, 110, 97, 109, 101, 11, 100, 111, 109, - 97, 105, 110, 95, 110, 97, 109, 101, 12, 255, 0, 0, 8, 0, 0, 253, 0, 0, 0, 0, 0, 79, 0, - 0, 16, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, - 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, - 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 9, 108, 111, 103, 105, 110, 95, 117, - 114, 108, 9, 108, 111, 103, 105, 110, 95, 117, 114, 108, 12, 255, 0, 0, 8, 0, 0, 253, - 0, 0, 0, 0, 0, 73, 0, 0, 17, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, - 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, - 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 6, 105, 115, - 95, 115, 115, 108, 6, 105, 115, 95, 115, 115, 108, 12, 63, 0, 1, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 87, 0, 0, 18, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, - 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, - 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 13, 105, 110, 116, - 114, 97, 110, 101, 116, 95, 105, 110, 102, 111, 13, 105, 110, 116, 114, 97, 110, 101, - 116, 95, 105, 110, 102, 111, 12, 255, 0, 252, 255, 3, 0, 252, 16, 0, 0, 0, 0, 81, 0, 0, - 19, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, - 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, - 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 114, 101, 97, 116, 101, 100, 95, - 97, 116, 10, 99, 114, 101, 97, 116, 101, 100, 95, 97, 116, 12, 63, 0, 23, 0, 0, 0, 12, - 128, 0, 3, 0, 0, 81, 0, 0, 20, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, - 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, - 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 117, 112, - 100, 97, 116, 101, 100, 95, 97, 116, 10, 117, 112, 100, 97, 116, 101, 100, 95, 97, 116, - 12, 63, 0, 23, 0, 0, 0, 12, 128, 0, 3, 0, 0, 81, 0, 0, 21, 3, 100, 101, 102, 19, 115, - 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, - 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, - 97, 112, 112, 10, 100, 101, 108, 101, 116, 101, 100, 95, 97, 116, 10, 100, 101, 108, - 101, 116, 101, 100, 95, 97, 116, 12, 63, 0, 23, 0, 0, 0, 12, 128, 0, 3, 0, 0, 75, 0, 0, - 22, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, - 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, - 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 7, 97, 112, 112, 114, 111, 118, 101, 7, - 97, 112, 112, 114, 111, 118, 101, 12, 63, 0, 10, 0, 0, 0, 3, 33, 0, 0, 0, 0, 75, 0, 0, - 23, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, - 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, - 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 7, 117, 115, 101, 114, 95, 105, 100, 7, - 117, 115, 101, 114, 95, 105, 100, 12, 63, 0, 20, 0, 0, 0, 8, 33, 16, 0, 0, 0, 69, 0, 0, - 24, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, - 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, - 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 4, 117, 117, 105, 100, 4, 117, 117, 105, - 100, 12, 255, 0, 252, 3, 0, 0, 253, 9, 80, 0, 0, 0, 75, 0, 0, 25, 3, 100, 101, 102, 19, - 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, - 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, - 114, 95, 97, 112, 112, 7, 112, 114, 111, 99, 101, 115, 115, 7, 112, 114, 111, 99, 101, - 115, 115, 12, 255, 0, 252, 3, 0, 0, 253, 0, 0, 0, 0, 0, 73, 0, 0, 26, 3, 100, 101, 102, - 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, - 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, - 101, 114, 95, 97, 112, 112, 6, 114, 101, 115, 117, 108, 116, 6, 114, 101, 115, 117, - 108, 116, 12, 63, 0, 10, 0, 0, 0, 3, 32, 0, 0, 0, 0, 75, 0, 0, 27, 3, 100, 101, 102, - 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, - 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, - 101, 114, 95, 97, 112, 112, 7, 111, 115, 95, 110, 97, 109, 101, 7, 111, 115, 95, 110, - 97, 109, 101, 12, 255, 0, 252, 3, 0, 0, 253, 0, 0, 0, 0, 0, 81, 0, 0, 28, 3, 100, 101, - 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, - 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, - 104, 101, 114, 95, 97, 112, 112, 10, 111, 115, 95, 118, 101, 114, 115, 105, 111, 110, - 10, 111, 115, 95, 118, 101, 114, 115, 105, 111, 110, 12, 255, 0, 252, 3, 0, 0, 253, 0, - 0, 0, 0, 0, 73, 0, 0, 29, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, - 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, - 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 6, 107, 101, 114, - 110, 101, 108, 6, 107, 101, 114, 110, 101, 108, 12, 255, 0, 252, 3, 0, 0, 253, 0, 0, 0, - 0, 0, 77, 0, 0, 30, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, 110, 101, 108, 95, - 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, 104, 101, 114, 95, - 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 8, 112, 114, 111, 116, - 111, 99, 111, 108, 8, 112, 114, 111, 116, 111, 99, 111, 108, 12, 63, 0, 255, 255, 255, - 255, 245, 144, 0, 0, 0, 0, 69, 0, 0, 31, 3, 100, 101, 102, 19, 115, 101, 110, 116, 105, - 110, 101, 108, 95, 102, 108, 111, 119, 95, 97, 100, 109, 105, 110, 10, 99, 105, 112, - 104, 101, 114, 95, 97, 112, 112, 10, 99, 105, 112, 104, 101, 114, 95, 97, 112, 112, 4, - 109, 97, 114, 107, 4, 109, 97, 114, 107, 12, 63, 0, 20, 0, 0, 0, 8, 1, 0, 0, 0, 0, 5, - 0, 0, 32, 254, 0, 0, 2, 0, 224, 0, 0, 33, 0, 0, 0, 34, 0, 1, 0, 0, 0, 0, 0, 0, 0, 24, - 233, 163, 142, 233, 153, 169, 230, 188, 143, 230, 180, 158, 230, 131, 133, 230, 138, - 165, 229, 185, 179, 229, 143, 176, 4, 83, 65, 86, 83, 12, 233, 163, 142, 233, 153, 169, - 229, 185, 179, 229, 143, 176, 9, 0, 0, 0, 0, 0, 0, 0, 4, 91, 51, 52, 93, 3, 91, 51, 93, - 2, 91, 93, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, 48, - 48, 46, 50, 49, 53, 80, 0, 0, 0, 0, 0, 4, 110, 117, 108, 108, 11, 232, 7, 7, 2, 11, 11, - 0, 232, 253, 0, 0, 11, 232, 7, 8, 26, 15, 27, 59, 112, 225, 8, 0, 1, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 36, 48, 49, 57, 49, 56, 100, 57, 53, 45, 97, 50, 53, 56, 45, 55, 100, - 98, 52, 45, 98, 52, 50, 101, 45, 101, 51, 52, 98, 98, 99, 57, 49, 97, 53, 102, 52, 0, - 1, 0, 0, 0, 6, 67, 101, 110, 116, 111, 115, 3, 55, 46, 54, 4, 53, 46, 49, 53, 8, 91, - 34, 72, 84, 84, 80, 34, 93, 1, 0, 0, 0, 0, 0, 0, 0, 201, 0, 0, 34, 0, 0, 0, 34, 0, 2, - 0, 0, 0, 0, 0, 0, 0, 14, 79, 65, 231, 174, 161, 231, 144, 134, 231, 179, 187, 231, 187, - 159, 5, 71, 69, 79, 65, 32, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 91, 51, 53, 93, 3, 91, 49, - 93, 2, 91, 93, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, - 48, 48, 46, 49, 51, 53, 138, 19, 0, 0, 0, 0, 4, 110, 117, 108, 108, 11, 232, 7, 8, 2, - 11, 12, 23, 136, 66, 13, 0, 11, 232, 7, 8, 10, 14, 37, 55, 232, 50, 13, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 36, 48, 49, 57, 49, 51, 98, 48, 50, 45, 48, 100, 49, 53, 45, - 55, 99, 101, 50, 45, 57, 54, 101, 57, 45, 99, 100, 56, 101, 57, 51, 55, 57, 101, 97, - 50, 98, 0, 1, 0, 0, 0, 5, 113, 105, 108, 105, 110, 3, 86, 49, 48, 0, 11, 91, 34, 84, - 76, 83, 124, 49, 46, 50, 34, 93, 2, 0, 0, 0, 0, 0, 0, 0, 13, 1, 0, 35, 0, 0, 0, 34, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 18, 232, 175, 129, 230, 141, 174, 231, 174, 161, 231, 144, 134, - 231, 179, 187, 231, 187, 159, 9, 90, 74, 71, 76, 45, 52, 48, 48, 48, 0, 20, 0, 0, 0, 0, - 0, 0, 0, 4, 110, 117, 108, 108, 4, 110, 117, 108, 108, 2, 91, 93, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, 48, 48, 46, 49, 48, 52, 187, 1, 0, 0, - 0, 0, 4, 110, 117, 108, 108, 11, 232, 7, 6, 19, 11, 13, 27, 128, 175, 2, 0, 11, 232, 7, - 8, 20, 10, 15, 25, 208, 102, 5, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 36, 48, 49, 57, - 49, 54, 100, 57, 49, 45, 52, 102, 97, 52, 45, 55, 49, 102, 55, 45, 56, 50, 52, 99, 45, - 97, 97, 51, 56, 49, 54, 54, 48, 52, 101, 51, 98, 0, 1, 0, 0, 0, 5, 75, 121, 108, 105, - 110, 7, 86, 49, 48, 45, 83, 80, 49, 0, 66, 91, 34, 84, 76, 83, 124, 49, 46, 48, 34, 44, - 32, 34, 84, 76, 83, 124, 49, 46, 49, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 50, 34, - 44, 32, 34, 84, 76, 83, 124, 49, 46, 51, 34, 44, 32, 34, 84, 76, 83, 124, 103, 109, 45, - 49, 46, 48, 34, 44, 32, 34, 72, 84, 84, 80, 34, 93, 3, 0, 0, 0, 0, 0, 0, 0, 26, 1, 0, - 36, 0, 0, 0, 34, 0, 4, 0, 0, 0, 0, 0, 0, 0, 18, 230, 150, 135, 228, 187, 182, 229, 173, - 152, 229, 130, 168, 231, 179, 187, 231, 187, 159, 4, 70, 87, 83, 68, 18, 230, 150, 135, - 228, 187, 182, 229, 173, 152, 229, 130, 168, 231, 179, 187, 231, 187, 159, 46, 0, 0, 0, - 0, 0, 0, 0, 4, 110, 117, 108, 108, 4, 110, 117, 108, 108, 2, 91, 93, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, 48, 48, 46, 49, 48, 53, 187, 1, 0, - 0, 0, 0, 4, 110, 117, 108, 108, 11, 232, 7, 8, 19, 11, 15, 41, 80, 171, 4, 0, 11, 232, - 7, 8, 20, 10, 13, 45, 8, 153, 9, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 36, 48, 49, 57, - 49, 54, 100, 56, 102, 45, 99, 97, 49, 55, 45, 55, 49, 102, 55, 45, 57, 56, 48, 101, 45, - 100, 51, 50, 99, 52, 54, 54, 102, 53, 98, 100, 49, 0, 1, 0, 0, 0, 5, 75, 121, 108, 105, - 110, 7, 86, 49, 48, 45, 83, 80, 49, 0, 66, 91, 34, 84, 76, 83, 124, 49, 46, 48, 34, 44, - 32, 34, 84, 76, 83, 124, 49, 46, 49, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 50, 34, - 44, 32, 34, 84, 76, 83, 124, 49, 46, 51, 34, 44, 32, 34, 84, 76, 83, 124, 103, 109, 45, - 49, 46, 48, 34, 44, 32, 34, 72, 84, 84, 80, 34, 93, 4, 0, 0, 0, 0, 0, 0, 0, 29, 1, 0, - 37, 0, 0, 0, 34, 0, 5, 0, 0, 0, 0, 0, 0, 0, 18, 231, 148, 181, 229, 173, 144, 230, 138, - 165, 232, 161, 168, 231, 179, 187, 231, 187, 159, 7, 69, 84, 83, 49, 48, 50, 48, 18, - 231, 148, 181, 229, 173, 144, 230, 138, 165, 232, 161, 168, 231, 179, 187, 231, 187, - 159, 48, 0, 0, 0, 0, 0, 0, 0, 4, 110, 117, 108, 108, 4, 110, 117, 108, 108, 2, 91, 93, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, 48, 48, 46, 50, - 51, 51, 187, 1, 0, 0, 0, 0, 4, 110, 117, 108, 108, 11, 232, 7, 5, 19, 11, 17, 17, 8, - 183, 4, 0, 11, 232, 7, 8, 20, 10, 13, 7, 160, 15, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 36, 48, 49, 57, 49, 54, 100, 56, 102, 45, 51, 51, 51, 54, 45, 55, 49, 102, 55, - 45, 98, 55, 99, 100, 45, 57, 99, 54, 102, 98, 56, 54, 48, 48, 48, 102, 100, 0, 1, 0, 0, - 0, 5, 75, 121, 108, 105, 110, 7, 86, 49, 48, 45, 83, 80, 49, 0, 66, 91, 34, 84, 76, 83, - 124, 49, 46, 48, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 49, 34, 44, 32, 34, 84, 76, - 83, 124, 49, 46, 50, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 51, 34, 44, 32, 34, 84, - 76, 83, 124, 103, 109, 45, 49, 46, 48, 34, 44, 32, 34, 72, 84, 84, 80, 34, 93, 5, 0, 0, - 0, 0, 0, 0, 0, 33, 1, 0, 38, 0, 0, 0, 34, 0, 6, 0, 0, 0, 0, 0, 0, 0, 15, 71, 73, 83, - 232, 129, 148, 233, 152, 178, 231, 179, 187, 231, 187, 159, 8, 71, 73, 83, 83, 71, 73, - 83, 83, 15, 71, 73, 83, 232, 129, 148, 233, 152, 178, 231, 179, 187, 231, 187, 159, 40, - 0, 0, 0, 0, 0, 0, 0, 4, 110, 117, 108, 108, 4, 110, 117, 108, 108, 2, 91, 93, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 50, 48, 48, 46, 50, 49, 51, - 187, 1, 0, 0, 0, 0, 4, 110, 117, 108, 108, 11, 232, 7, 8, 19, 11, 19, 23, 112, 148, 0, - 0, 11, 232, 7, 8, 20, 10, 12, 27, 0, 83, 7, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 36, - 48, 49, 57, 49, 54, 100, 56, 101, 45, 57, 56, 100, 50, 45, 55, 49, 102, 55, 45, 98, 53, - 100, 97, 45, 51, 98, 97, 55, 57, 49, 51, 97, 100, 98, 55, 55, 0, 1, 0, 0, 0, 5, 75, - 121, 108, 105, 110, 7, 86, 49, 48, 45, 83, 80, 49, 0, 75, 91, 34, 84, 76, 83, 124, 49, - 46, 48, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 49, 34, 44, 32, 34, 84, 76, 83, 124, - 49, 46, 50, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 51, 34, 44, 32, 34, 84, 76, 83, - 124, 103, 109, 45, 49, 46, 48, 34, 44, 32, 34, 73, 80, 83, 101, 99, 34, 44, 32, 34, 72, - 84, 84, 80, 34, 93, 6, 0, 0, 0, 0, 0, 0, 0, 10, 1, 0, 39, 0, 0, 0, 34, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 12, 231, 165, 158, 231, 155, 190, 233, 152, 178, 230, 138, 164, 6, 78, 83, - 71, 51, 56, 48, 12, 78, 83, 71, 51, 56, 48, 48, 45, 84, 71, 50, 53, 33, 0, 0, 0, 0, 0, - 0, 0, 4, 110, 117, 108, 108, 4, 110, 117, 108, 108, 2, 91, 93, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, 48, 48, 46, 50, 49, 53, 187, 1, 0, 0, 0, - 0, 4, 110, 117, 108, 108, 11, 231, 7, 8, 19, 11, 21, 54, 64, 72, 14, 0, 11, 232, 7, 8, - 20, 10, 14, 47, 88, 229, 8, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 36, 48, 49, 57, 49, - 54, 100, 57, 48, 45, 98, 99, 49, 57, 45, 55, 49, 102, 55, 45, 56, 99, 54, 51, 45, 99, - 55, 52, 101, 53, 49, 100, 102, 51, 100, 98, 52, 0, 1, 0, 0, 0, 7, 117, 110, 107, 110, - 111, 119, 110, 7, 117, 110, 107, 110, 111, 119, 110, 0, 58, 91, 34, 84, 76, 83, 124, - 49, 46, 48, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 49, 34, 44, 32, 34, 84, 76, 83, - 124, 49, 46, 50, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 51, 34, 44, 32, 34, 84, 76, - 83, 124, 103, 109, 45, 49, 46, 48, 34, 93, 7, 0, 0, 0, 0, 0, 0, 0, 53, 1, 0, 40, 0, 0, - 0, 34, 0, 8, 0, 0, 0, 0, 0, 0, 0, 24, 230, 153, 186, 230, 133, 167, 232, 176, 131, 229, - 186, 166, 230, 142, 167, 229, 136, 182, 231, 179, 187, 231, 187, 159, 8, 73, 68, 67, - 83, 45, 50, 48, 48, 24, 230, 153, 186, 230, 133, 167, 232, 176, 131, 229, 186, 166, - 230, 142, 167, 229, 136, 182, 231, 179, 187, 231, 187, 159, 49, 0, 0, 0, 0, 0, 0, 0, 4, - 110, 117, 108, 108, 4, 110, 117, 108, 108, 2, 91, 93, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 15, - 49, 57, 50, 46, 49, 54, 56, 46, 49, 48, 48, 46, 50, 50, 49, 187, 1, 0, 0, 0, 0, 4, 110, - 117, 108, 108, 11, 232, 7, 8, 19, 11, 24, 18, 48, 27, 15, 0, 11, 232, 7, 8, 20, 10, 11, - 30, 88, 92, 10, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 36, 48, 49, 57, 49, 54, 100, 56, - 100, 45, 98, 97, 102, 48, 45, 55, 49, 102, 55, 45, 97, 98, 52, 100, 45, 54, 101, 97, - 48, 100, 51, 50, 102, 55, 48, 102, 56, 0, 1, 0, 0, 0, 7, 117, 110, 107, 110, 111, 119, - 110, 7, 117, 110, 107, 110, 111, 119, 110, 0, 75, 91, 34, 84, 76, 83, 124, 49, 46, 48, - 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 49, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, - 50, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 51, 34, 44, 32, 34, 84, 76, 83, 124, 103, - 109, 45, 49, 46, 48, 34, 44, 32, 34, 73, 80, 83, 101, 99, 34, 44, 32, 34, 72, 84, 84, - 80, 34, 93, 8, 0, 0, 0, 0, 0, 0, 0, 35, 1, 0, 41, 0, 0, 0, 34, 0, 9, 0, 0, 0, 0, 0, 0, - 0, 24, 231, 187, 136, 231, 171, 175, 229, 174, 137, 229, 133, 168, 231, 174, 161, 231, - 144, 134, 231, 179, 187, 231, 187, 159, 8, 77, 83, 77, 83, 45, 51, 57, 48, 6, 229, 164, - 169, 230, 147, 142, 47, 0, 0, 0, 0, 0, 0, 0, 4, 110, 117, 108, 108, 4, 110, 117, 108, - 108, 2, 91, 93, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, - 48, 48, 46, 50, 50, 50, 187, 1, 0, 0, 0, 0, 4, 110, 117, 108, 108, 11, 232, 7, 8, 19, - 11, 27, 30, 88, 122, 5, 0, 11, 232, 7, 8, 20, 15, 37, 20, 32, 179, 4, 0, 1, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 36, 48, 49, 57, 49, 54, 101, 98, 56, 45, 48, 56, 97, 101, 45, 55, - 52, 99, 99, 45, 56, 98, 54, 56, 45, 49, 52, 52, 100, 54, 51, 48, 99, 53, 56, 98, 50, 0, - 1, 0, 0, 0, 7, 117, 110, 107, 110, 111, 119, 110, 7, 117, 110, 107, 110, 111, 119, 110, - 0, 75, 91, 34, 84, 76, 83, 124, 49, 46, 48, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, - 49, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 50, 34, 44, 32, 34, 84, 76, 83, 124, 49, - 46, 51, 34, 44, 32, 34, 73, 80, 83, 101, 99, 34, 44, 32, 34, 84, 76, 83, 124, 103, 109, - 45, 49, 46, 48, 34, 44, 32, 34, 72, 84, 84, 80, 34, 93, 9, 0, 0, 0, 0, 0, 0, 0, 54, 1, - 0, 42, 0, 0, 0, 34, 0, 10, 0, 0, 0, 0, 0, 0, 0, 24, 230, 153, 186, 230, 133, 167, 232, - 129, 148, 229, 138, 168, 232, 129, 148, 229, 139, 164, 231, 179, 187, 231, 187, 159, 9, - 73, 76, 76, 83, 45, 49, 50, 48, 48, 24, 230, 153, 186, 230, 133, 167, 232, 129, 148, - 229, 138, 168, 232, 129, 148, 229, 139, 164, 231, 179, 187, 231, 187, 159, 46, 0, 0, 0, - 0, 0, 0, 0, 4, 110, 117, 108, 108, 4, 110, 117, 108, 108, 2, 91, 93, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 49, 57, 50, 46, 49, 54, 56, 46, 49, 48, 48, 46, 49, 51, 51, 187, 1, 0, - 0, 0, 0, 4, 110, 117, 108, 108, 11, 231, 7, 9, 19, 11, 29, 46, 224, 105, 11, 0, 11, - 232, 7, 8, 20, 10, 6, 40, 208, 179, 13, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 36, 48, - 49, 57, 49, 54, 100, 56, 57, 45, 52, 101, 102, 99, 45, 55, 49, 102, 55, 45, 56, 97, - 102, 49, 45, 54, 54, 57, 49, 97, 98, 99, 48, 102, 101, 52, 101, 0, 1, 0, 0, 0, 7, 117, - 110, 107, 110, 111, 119, 110, 7, 117, 110, 107, 110, 111, 119, 110, 0, 75, 91, 34, 84, - 76, 83, 124, 49, 46, 48, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 49, 34, 44, 32, 34, - 84, 76, 83, 124, 49, 46, 50, 34, 44, 32, 34, 84, 76, 83, 124, 49, 46, 51, 34, 44, 32, - 34, 84, 76, 83, 124, 103, 109, 45, 49, 46, 48, 34, 44, 32, 34, 73, 80, 83, 101, 99, 34, - 44, 32, 34, 72, 84, 84, 80, 34, 93, 10, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 43, 254, 0, 0, 2, - 0, - ]; - - let (rem, _) = parse_stmt_execute_response(pkt).unwrap(); - assert!(rem.is_empty()); - - let pkt: &[u8] = &[ - 0x01, 0x00, 0x00, 0x01, 0x20, 0x47, 0x00, 0x00, 0x02, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x02, 0x69, 0x64, 0x02, 0x69, 0x64, 0x0c, 0x3f, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x08, 0x23, 0x42, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x03, - 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, - 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x73, 0x79, 0x73, - 0x5f, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x69, 0x64, 0x0d, 0x73, 0x79, 0x73, - 0x5f, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x5f, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x08, 0x01, 0x10, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x04, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0c, 0x73, 0x79, 0x73, 0x5f, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x69, 0x64, 0x0c, 0x73, 0x79, 0x73, 0x5f, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x08, 0x01, 0x10, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x05, 0x03, 0x64, 0x65, 0x66, - 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, - 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x03, 0x69, 0x70, 0x73, 0x03, 0x69, 0x70, 0x73, - 0x0c, 0xff, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x51, - 0x00, 0x00, 0x06, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, - 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, - 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x07, - 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, - 0x6e, 0x0c, 0x3f, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x01, 0x10, 0x00, 0x00, 0x00, - 0x67, 0x00, 0x00, 0x07, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, - 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, - 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x6e, 0x67, - 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x0c, 0xff, 0x00, 0xfc, - 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x08, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x16, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, - 0x5f, 0x73, 0x74, 0x72, 0x16, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x6e, 0x67, 0x5f, - 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x0c, - 0xff, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, - 0x00, 0x09, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, - 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, - 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x14, 0x61, - 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x61, 0x6c, 0x67, 0x6f, - 0x72, 0x69, 0x74, 0x68, 0x6d, 0x14, 0x61, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x0c, 0xff, - 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, - 0x0a, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, - 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x61, 0x73, - 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x61, 0x73, 0x79, 0x6d, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, - 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x0c, 0xff, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfd, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x0b, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x0e, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6c, 0x67, 0x6f, - 0x72, 0x69, 0x74, 0x68, 0x6d, 0x0e, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x0c, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x12, 0x68, 0x61, 0x73, - 0x68, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x73, 0x74, - 0x72, 0x0c, 0xff, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6b, 0x00, 0x00, 0x0d, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, - 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x14, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, - 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x14, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, - 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, - 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, - 0x00, 0x00, 0x0e, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, - 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, - 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, - 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x73, 0x65, 0x71, - 0x75, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, - 0x74, 0x68, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x0c, 0xff, 0x00, 0x78, 0x00, 0x00, 0x00, - 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x0f, 0x03, 0x64, 0x65, 0x66, - 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, - 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0f, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x61, - 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x0f, 0x6f, 0x74, 0x68, 0x65, 0x72, - 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x0c, 0xff, 0x00, 0xfc, - 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x10, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x69, 0x73, 0x5f, 0x6b, - 0x65, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x0d, 0x69, 0x73, 0x5f, 0x6b, - 0x65, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x0c, 0x3f, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x11, 0x03, 0x64, - 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, - 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, - 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0c, 0xff, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfc, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x12, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x06, 0x72, - 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x0c, 0xff, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfc, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x13, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x0c, 0x3f, - 0x00, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x00, 0x00, 0x57, 0x00, 0x00, - 0x14, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, - 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0a, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x0c, 0x3f, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x80, - 0x00, 0x03, 0x00, 0x00, 0x57, 0x00, 0x00, 0x15, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, - 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x0c, 0x3f, - 0x00, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x03, 0x00, 0x00, 0x61, 0x00, 0x00, - 0x16, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, - 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0f, 0x67, 0x6d, - 0x74, 0x5f, 0x30, 0x30, 0x35, 0x33, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x0f, - 0x67, 0x6d, 0x74, 0x5f, 0x30, 0x30, 0x35, 0x33, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x0c, 0xff, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfc, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x59, 0x00, 0x00, 0x17, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, - 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x0b, 0x67, 0x6d, 0x74, 0x5f, 0x30, 0x30, 0x35, 0x33, 0x5f, 0x69, 0x70, 0x0b, 0x67, - 0x6d, 0x74, 0x5f, 0x30, 0x30, 0x35, 0x33, 0x5f, 0x69, 0x70, 0x0c, 0xff, 0x00, 0xfc, - 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x18, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x67, 0x6d, 0x74, 0x5f, - 0x30, 0x30, 0x35, 0x33, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x0d, 0x67, 0x6d, 0x74, 0x5f, - 0x30, 0x30, 0x35, 0x33, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x0c, 0x3f, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x19, 0x03, 0x64, - 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, - 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, - 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x07, 0x61, 0x70, 0x70, 0x72, 0x6f, - 0x76, 0x65, 0x07, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x0c, 0x3f, 0x00, 0x0a, - 0x00, 0x00, 0x00, 0x03, 0x21, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x1a, 0x03, - 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x07, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x0c, 0x3f, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x08, 0x21, 0x10, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x1b, - 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, - 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x04, 0x75, 0x75, 0x69, 0x64, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, - 0x09, 0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x1c, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x07, - 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, - 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x1d, 0x03, 0x64, 0x65, 0x66, - 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, - 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x06, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x0c, 0x3f, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x1e, 0x03, 0x64, 0x65, 0x66, 0x13, - 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x07, 0x6f, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x07, - 0x6f, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, - 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x1f, 0x03, 0x64, 0x65, 0x66, - 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, - 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x0c, 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, - 0x00, 0x00, 0x20, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, - 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, - 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x06, - 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x0c, - 0xff, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00, - 0x00, 0x21, 0x03, 0x64, 0x65, 0x66, 0x13, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, - 0x6c, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x0d, 0x63, - 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x0d, 0x63, - 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x04, 0x6d, - 0x61, 0x72, 0x6b, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x0c, 0x3f, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x22, 0xfe, 0x00, 0x00, - 0x22, 0x00, 0x05, 0x00, 0x00, 0x23, 0xfe, 0x00, 0x00, 0x22, 0x00, - ]; - - let (rem, _) = parse_stmt_execute_response(pkt).unwrap(); - assert!(rem.is_empty()); - } - #[test] fn test_parse_close_stmt_request() { let pkt: &[u8] = &[0x05, 0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x00, 0x00]; @@ -3441,7 +2351,4 @@ mod test { assert!(rem.is_empty()); assert_eq!(request.command, MysqlCommand::Ping); } - - #[test] - fn test_parse_unknown_request() {} } diff --git a/src/Makefile.am b/src/Makefile.am index f53a90cba865..6970d709f35c 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -242,8 +242,6 @@ noinst_HEADERS = \ detect-quic-cyu-hash.h \ detect-quic-cyu-string.h \ detect-msg.h \ - detect-mysql-command.h \ - detect-mysql-rows.h \ detect-nfs-procedure.h \ detect-nfs-version.h \ detect-noalert.h \ @@ -813,8 +811,6 @@ libsuricata_c_a_SOURCES = \ detect-quic-cyu-hash.c \ detect-quic-cyu-string.c \ detect-msg.c \ - detect-mysql-command.c \ - detect-mysql-rows.c \ detect-nfs-procedure.c \ detect-nfs-version.c \ detect-noalert.c \ diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 48a6e47c2d9e..123f441c431d 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -1732,6 +1732,7 @@ void AppLayerParserRegisterProtocolParsers(void) RegisterHTTP2Parsers(); rs_telnet_register_parser(); RegisterIMAPParsers(); + rs_mysql_register_parser(); /** POP3 */ AppLayerProtoDetectRegisterProtocol(ALPROTO_POP3, "pop3"); diff --git a/src/app-layer-protos.h b/src/app-layer-protos.h index 0ba973a2edb3..c43c1bc9de7b 100644 --- a/src/app-layer-protos.h +++ b/src/app-layer-protos.h @@ -64,11 +64,11 @@ enum AppProtoEnum { ALPROTO_HTTP2, ALPROTO_BITTORRENT_DHT, ALPROTO_POP3, - ALPROTO_MYSQL, // signature-only (ie not seen in flow) // HTTP for any version (ALPROTO_HTTP1 (version 1) or ALPROTO_HTTP2) ALPROTO_HTTP, + ALPROTO_MYSQL, /* used by the probing parser when alproto detection fails * permanently for that particular stream */ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index fcfc8a27b4c7..63ad3e9a505f 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -260,8 +260,6 @@ #include "detect-ike-nonce-payload-length.h" #include "detect-ike-nonce-payload.h" #include "detect-ike-key-exchange-payload.h" -#include "detect-mysql-command.h" -#include "detect-mysql-rows.h" #include "action-globals.h" #include "tm-threads.h" @@ -696,6 +694,7 @@ void SigTableSetup(void) ScDetectRfbRegister(); ScDetectSipRegister(); ScDetectTemplateRegister(); + ScDetectMysqlRegister(); /* close keyword registration */ DetectBufferTypeCloseRegistration(); diff --git a/src/detect-mysql-command.c b/src/detect-mysql-command.c deleted file mode 100644 index 3968e6b1df22..000000000000 --- a/src/detect-mysql-command.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * 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 - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * Detect keyword for Mysql command: mysql.command - */ - -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-prefilter.h" -#include "detect-engine-content-inspection.h" -#include "detect-mysql-command.h" -#include "util-profiling.h" -#include "rust.h" - -static int detect_buffer_id = 0; - -static int DetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) -{ - if (DetectBufferSetActiveList(de_ctx, s, detect_buffer_id) < 0) { - return -1; - } - if (DetectSignatureSetAppProto(s, ALPROTO_MYSQL) < 0) { - return -1; - } - - return 0; -} - -static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flags, void *txv, - const int list_id) -{ - InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); - if (!buffer->initialized) { - uint32_t data_len = 0; - const uint8_t *data = NULL; - SCMysqlTxGetCommand(txv, &data, &data_len); - InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len); - InspectionBufferApplyTransforms(buffer, transforms); - } - return buffer; -} - -void DetectMysqlCommandRegister(void) -{ - static const char *keyword = "mysql.command"; - sigmatch_table[DETECT_AL_MYSQL_COMMAND].name = keyword; - sigmatch_table[DETECT_AL_MYSQL_COMMAND].desc = "Mysql command"; - sigmatch_table[DETECT_AL_MYSQL_COMMAND].url = "todo"; - sigmatch_table[DETECT_AL_MYSQL_COMMAND].Setup = DetectSetup; - sigmatch_table[DETECT_AL_MYSQL_COMMAND].flags |= SIGMATCH_NOOPT; - - DetectAppLayerInspectEngineRegister(keyword, ALPROTO_MYSQL, SIG_FLAG_TOSERVER, 0, - DetectEngineInspectBufferGeneric, GetBuffer); - - DetectBufferTypeSetDescriptionByName(keyword, "mysql command"); - DetectBufferTypeSupportsMultiInstance(keyword); - - detect_buffer_id = DetectBufferTypeGetByName(keyword); -} diff --git a/src/detect-mysql-command.h b/src/detect-mysql-command.h deleted file mode 100644 index ec36e6bfc1f9..000000000000 --- a/src/detect-mysql-command.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * 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 - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#ifndef SURICATA_DETECT_MYSQL_COMMAND_NAME_H -#define SURICATA_DETECT_MYSQL_COMMAND_NAME_H - -void DetectMysqlCommandRegister(void); - -#endif /* SURICATA_DETECT_MYSQL_COMMAND_NAME_H */ diff --git a/src/detect-mysql-rows.c b/src/detect-mysql-rows.c deleted file mode 100644 index 61a0a7921083..000000000000 --- a/src/detect-mysql-rows.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * 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 - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * Detect keyword for Mysql rows: mysql.rows - */ - -#include "detect.h" -#include "detect-parse.h" -#include "detect-engine.h" -#include "detect-engine-prefilter.h" -#include "detect-engine-content-inspection.h" -#include "detect-mysql-rows.h" -#include "util-profiling.h" -#include "rust.h" - -static int detect_buffer_id = 0; - -static int DetectSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) -{ - if (DetectBufferSetActiveList(de_ctx, s, detect_buffer_id) < 0) { - return -1; - } - if (DetectSignatureSetAppProto(s, ALPROTO_MYSQL) < 0) { - return -1; - } - - return 0; -} - -static InspectionBuffer *GetBuffer(DetectEngineThreadCtx *det_ctx, - const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flags, void *txv, - const int list_id, uint32_t local_id) -{ - SCEnter(); - - InspectionBuffer *buffer = InspectionBufferMultipleForListGet(det_ctx, list_id, local_id); - if (buffer == NULL) - return NULL; - if (buffer->initialized) - return buffer; - - const uint8_t *data; - uint32_t data_len; - if (SCMysqlGetRowsData(txv, local_id, &data, &data_len) == 0) { - InspectionBufferSetupMultiEmpty(buffer); - return NULL; - } - InspectionBufferSetupMulti(buffer, transforms, data, data_len); - buffer->flags = DETECT_CI_FLAGS_SINGLE; - - SCReturnPtr(buffer, "InspectionBuffer"); - return buffer; -} - -void DetectMysqlRowsRegister(void) -{ - static const char *keyword = "mysql.rows"; - sigmatch_table[DETECT_AL_MYSQL_ROWS].name = keyword; - sigmatch_table[DETECT_AL_MYSQL_ROWS].desc = "Mysql rows"; - sigmatch_table[DETECT_AL_MYSQL_ROWS].url = "todo"; - sigmatch_table[DETECT_AL_MYSQL_ROWS].Setup = DetectSetup; - sigmatch_table[DETECT_AL_MYSQL_ROWS].flags |= SIGMATCH_NOOPT; - - DetectAppLayerMultiRegister(keyword, ALPROTO_MYSQL, SIG_FLAG_TOCLIENT, 0, - GetBuffer, 2, 1); - - DetectBufferTypeSetDescriptionByName(keyword, "mysql rows"); - DetectBufferTypeSupportsMultiInstance(keyword); - - detect_buffer_id = DetectBufferTypeGetByName(keyword); -} diff --git a/src/detect-mysql-rows.h b/src/detect-mysql-rows.h deleted file mode 100644 index b8302a2290f4..000000000000 --- a/src/detect-mysql-rows.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2023 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * 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 - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#ifndef SURICATA_DETECT_MYSQL_ROWS_H -#define SURICATA_DETECT_MYSQL_ROWS_H - -void DetectMysqlRowsRegister(void); - -#endif /* SURICATA_DETECT_MYSQL_ROWS_H */ diff --git a/src/output.c b/src/output.c index cca55baf0c34..cc20406eef9c 100644 --- a/src/output.c +++ b/src/output.c @@ -901,8 +901,7 @@ void OutputRegisterRootLoggers(void) // underscore instead of dash for bittorrent_dht RegisterSimpleJsonApplayerLogger( ALPROTO_BITTORRENT_DHT, rs_bittorrent_dht_logger_log, "bittorrent_dht"); - RegisterSimpleJsonApplayerLogger( - ALPROTO_MYSQL, (EveJsonSimpleTxLogFunc)SCMysqlLogger, "mysql"); + RegisterSimpleJsonApplayerLogger(ALPROTO_MYSQL, SCMysqlLogger, "mysql"); OutputPacketLoggerRegister(); OutputFiledataLoggerRegister(); @@ -1083,6 +1082,10 @@ void OutputRegisterLoggers(void) OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonLdapLog", "eve-log.ldap", OutputJsonLogInitSub, ALPROTO_LDAP, JsonGenericDirFlowLogger, JsonLogThreadInit, JsonLogThreadDeinit); + /* MySQL JSON logger. */ + OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonMySQLLog", "eve-log.mysql", + OutputJsonLogInitSub, ALPROTO_MYSQL, JsonGenericDirFlowLogger, JsonLogThreadInit, + JsonLogThreadDeinit); /* DoH2 JSON logger. */ JsonDoh2LogRegister(); /* Template JSON logger. */