-
Notifications
You must be signed in to change notification settings - Fork 426
feat: support sql server #11214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: support sql server #11214
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,4 +15,5 @@ | |
| */ | ||
|
|
||
| pub mod some_ip; | ||
| pub mod sql_server; | ||
| pub mod tls; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /* | ||
| * Copyright (c) 2024 Yunshan Networks | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #[derive(Debug, Default)] | ||
| pub struct TdsParser { | ||
| pub sql: Option<String>, | ||
| pub status_code: Option<i32>, | ||
| pub error_message: Option<String>, | ||
| pub affected_row: Option<u64>, | ||
| } | ||
|
|
||
| impl TdsParser { | ||
| pub fn new(_: &[u8]) -> Self { | ||
| TdsParser::default() | ||
| } | ||
|
|
||
| pub fn parse(&mut self) -> Result<(), ParserError> { | ||
| Err(ParserError::InvalidData) | ||
| } | ||
| } | ||
|
|
||
| #[derive(Debug)] | ||
| pub enum ParserError { | ||
| IoError(std::io::Error), | ||
| UnknownToken(u8), | ||
| UnknownEnvType(u8), | ||
| InvalidData, | ||
| InsufficientData, | ||
| Utf8Error(std::string::FromUtf8Error), | ||
| Utf16Error(std::string::FromUtf16Error), | ||
| UnsupportedDataType, | ||
| } | ||
|
|
||
| impl From<std::io::Error> for ParserError { | ||
| fn from(err: std::io::Error) -> Self { | ||
| ParserError::IoError(err) | ||
| } | ||
| } | ||
|
|
||
| impl From<std::string::FromUtf8Error> for ParserError { | ||
| fn from(err: std::string::FromUtf8Error) -> Self { | ||
| ParserError::Utf8Error(err) | ||
| } | ||
| } | ||
|
|
||
| impl From<std::string::FromUtf16Error> for ParserError { | ||
| fn from(err: std::string::FromUtf16Error) -> Self { | ||
| ParserError::Utf16Error(err) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,7 +31,7 @@ use crate::{ | |
| fastcgi::FastCGIInfo, pb_adapter::L7ProtocolSendLog, AmqpInfo, BrpcInfo, DnsInfo, | ||
| DubboInfo, HttpInfo, KafkaInfo, MemcachedInfo, MongoDBInfo, MqttInfo, MysqlInfo, | ||
| NatsInfo, OpenWireInfo, PingInfo, PostgreInfo, PulsarInfo, RedisInfo, RocketmqInfo, | ||
| SofaRpcInfo, TarsInfo, ZmtpInfo, | ||
| SofaRpcInfo, SqlServerInfo, TarsInfo, ZmtpInfo, | ||
| }, | ||
| AppProtoHead, Result, | ||
| }, | ||
|
|
@@ -100,6 +100,7 @@ cfg_if::cfg_if! { | |
| SofaRpcInfo(SofaRpcInfo), | ||
| PingInfo(PingInfo), | ||
| CustomInfo(CustomInfo), | ||
| SqlServerInfo(SqlServerInfo), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这边不用加 |
||
| // add new protocol info below | ||
| ); | ||
| } else { | ||
|
|
@@ -131,6 +132,7 @@ cfg_if::cfg_if! { | |
| PingInfo(PingInfo), | ||
| CustomInfo(CustomInfo), | ||
| Iso8583Info(crate::flow_generator::protocol_logs::rpc::Iso8583Info), | ||
| SqlServerInfo(SqlServerInfo), | ||
| // add new protocol info below | ||
| ); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,7 +44,7 @@ use crate::flow_generator::protocol_logs::{ | |
| sql::ObfuscateCache, | ||
| AmqpLog, BrpcLog, DnsLog, DubboLog, HttpLog, KafkaLog, L7ResponseStatus, MemcachedLog, | ||
| MongoDBLog, MqttLog, MysqlLog, NatsLog, OpenWireLog, PingLog, PostgresqlLog, PulsarLog, | ||
| RedisLog, RocketmqLog, SofaRpcLog, TarsLog, ZmtpLog, | ||
| RedisLog, RocketmqLog, SofaRpcLog, SqlServerLog, TarsLog, ZmtpLog, | ||
| }; | ||
|
|
||
| use crate::flow_generator::Result; | ||
|
|
@@ -180,6 +180,7 @@ cfg_if::cfg_if! { | |
| RocketMQ(RocketmqLog), | ||
| OpenWire(OpenWireLog), | ||
| Ping(PingLog), | ||
| SqlServer(SqlServerLog), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里也不用 |
||
| // add protocol below | ||
| } | ||
| } | ||
|
|
@@ -213,6 +214,7 @@ cfg_if::cfg_if! { | |
| TLS(crate::flow_generator::protocol_logs::TlsLog), | ||
| SomeIp(crate::flow_generator::protocol_logs::SomeIpLog), | ||
| Ping(PingLog), | ||
| SqlServer(SqlServerLog), | ||
| // add protocol below | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -791,10 +791,10 @@ static __inline enum message_type infer_mysql_message(const char *buf, | |
| if (is_socket_info_valid(conn_info->socket_info_ptr)) { | ||
| /* | ||
| * Ensure the authentication response packet is captured | ||
| * and distinguish it based on the 5th byte (Payload start): | ||
| * and distinguish it based on the 5th byte (Payload start): | ||
| * | ||
| * - **Authentication Success (OK Packet):** `0x00` | ||
| * - **Authentication Failure (ERR Packet):** `0xFF` | ||
| * - **Authentication Success (OK Packet):** `0x00` | ||
| * - **Authentication Failure (ERR Packet):** `0xFF` | ||
| * - **Authentication Switch Request (Auth Switch Request):** `0xFE` | ||
| */ | ||
| if (seq <= 1 || (seq == 2 && (com == 0x0 || com == 0xFF || com == 0xFE))) | ||
|
|
@@ -835,14 +835,14 @@ static __inline enum message_type infer_mysql_message(const char *buf, | |
|
|
||
| /* | ||
| * After establishing a connection, the MySQL server sends a handshake packet. | ||
| * The process is as follows: | ||
| * - **Server > Client (Handshake Packet)** | ||
| * The process is as follows: | ||
| * - **Server > Client (Handshake Packet)** | ||
| * The server sends this handshake packet, which includes the MySQL version, | ||
| * thread ID, authentication method, and other information. | ||
| * - **Client > Server (Login Request Packet)** | ||
| * thread ID, authentication method, and other information. | ||
| * - **Client > Server (Login Request Packet)** | ||
| * The client computes the encrypted password based on `auth-plugin-data` and | ||
| * sends it back to the server for verification. | ||
| * - **Server > Client (Login Success or Failure)** | ||
| * sends it back to the server for verification. | ||
| * - **Server > Client (Login Success or Failure)** | ||
| * The server verifies the client's identity and returns either an **OK Packet** or an **ERR Packet**. | ||
| * | ||
| * The handshake packet sent by the server is used for identification. | ||
|
|
@@ -1228,6 +1228,48 @@ static __inline enum message_type infer_oracle_tns_message(const char *buf, | |
| } | ||
| } | ||
|
|
||
| static __inline enum message_type infer_sql_server_message(const char *buf, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 注释下sql_server推断的参考链接? |
||
| size_t count, | ||
| struct conn_info_s | ||
| *conn_info) | ||
| { | ||
| #define HEADER_SIZE 8 | ||
| #define MESSAGE_TYPE_OFFSET 0 | ||
| #define LENGTH_OFFSET 1 | ||
| #define WINDOWS_OFFSET 7 | ||
| #define MESSAGE_TYPE_SQL_BATCH 1 | ||
| #define MESSAGE_TYPE_RPC 3 | ||
| #define MESSAGE_TYPE_RESPONSE 4 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 上面这些宏在当前推断完之后undef了吧,确保这些宏定义不会污染到当前函数之外的代码中。 |
||
| if (!protocol_port_check_1(PROTO_SQL_SERVER, conn_info)) | ||
| return MSG_UNKNOWN; | ||
| if (conn_info->tuple.l4_protocol != IPPROTO_TCP || count < HEADER_SIZE) { | ||
| return MSG_UNKNOWN; | ||
| } | ||
|
|
||
| if (is_infer_socket_valid(conn_info->socket_info_ptr)) { | ||
| if (conn_info->socket_info_ptr->l7_proto != PROTO_SQL_SERVER) | ||
| return MSG_UNKNOWN; | ||
| } | ||
|
|
||
| __u8 pkt_type = buf[MESSAGE_TYPE_OFFSET]; | ||
| __u16 pkt_length = __bpf_ntohs(*(__u16 *) & buf[LENGTH_OFFSET]); | ||
| __u8 windows = buf[WINDOWS_OFFSET]; | ||
| if (pkt_length < HEADER_SIZE || windows != 0) { | ||
| return MSG_UNKNOWN; | ||
| } | ||
|
|
||
| if (pkt_type == MESSAGE_TYPE_RESPONSE) { | ||
| return MSG_RESPONSE; | ||
| } | ||
| if (pkt_type == MESSAGE_TYPE_SQL_BATCH) { | ||
| return MSG_REQUEST; | ||
| } | ||
| if (pkt_type == MESSAGE_TYPE_RPC) { | ||
| return MSG_REQUEST; | ||
| } | ||
| return MSG_UNKNOWN; | ||
| } | ||
|
|
||
| // https://en.wikipedia.org/wiki/ISO_8583 | ||
| static __inline enum message_type infer_iso8583_message(const char *buf, | ||
| size_t count, | ||
|
|
@@ -1581,11 +1623,11 @@ static __inline enum message_type infer_dns_message(const char *buf, | |
|
|
||
| bool update_tcp_dns_prev_count = false; | ||
| struct dns_header *dns = (struct dns_header *)buf; | ||
|
|
||
| /* | ||
| * Note that TCP DNS adds two length bytes at the beginning of the protocol, | ||
| * whereas UDP DNS does not. We need to handle this properly to ensure that | ||
| * these two length bytes are not sent to the upper layer. | ||
| * these two length bytes are not sent to the upper layer. | ||
| * | ||
| * When receiving data, the client does not first receive two bytes but instead | ||
| * receives everything at once; whereas the server receives two bytes (length) first | ||
|
|
@@ -4286,7 +4328,7 @@ infer_protocol_1(struct ctx_info_s *ctx, | |
| * encrypted data can be discarded to prevent it from being involved | ||
| * in subsequent protocol inference, thereby avoiding performance | ||
| * degradation. | ||
| */ | ||
| */ | ||
| if (is_socket_info_valid(conn_info->socket_info_ptr)) { | ||
| if (conn_info->socket_info_ptr->is_tls && | ||
| !skip_http2_kprobe()) | ||
|
|
@@ -4483,6 +4525,15 @@ infer_protocol_1(struct ctx_info_s *ctx, | |
| return inferred_message; | ||
| } | ||
| break; | ||
| case PROTO_SQL_SERVER: | ||
| if ((inferred_message.type = | ||
| infer_sql_server_message(infer_buf, count, | ||
| conn_info)) != | ||
| MSG_UNKNOWN) { | ||
| inferred_message.protocol = PROTO_SQL_SERVER; | ||
| return inferred_message; | ||
| } | ||
| break; | ||
| case PROTO_ISO8583: | ||
| if ((inferred_message.type = | ||
| infer_iso8583_message(infer_buf, count, | ||
|
|
@@ -4633,6 +4684,14 @@ infer_protocol_1(struct ctx_info_s *ctx, | |
| if (inferred_message.type == MSG_PRESTORE) | ||
| return inferred_message; | ||
| inferred_message.protocol = PROTO_MYSQL; | ||
| #if defined(LINUX_VER_KFUNC) || defined(LINUX_VER_5_2_PLUS) | ||
| } else if (skip_proto != PROTO_SQL_SERVER && (inferred_message.type = | ||
| #else | ||
| } else if ((inferred_message.type = | ||
| #endif | ||
| infer_sql_server_message(infer_buf, count, | ||
| conn_info)) != MSG_UNKNOWN) { | ||
| inferred_message.protocol = PROTO_SQL_SERVER; | ||
| #if defined(LINUX_VER_KFUNC) || defined(LINUX_VER_5_2_PLUS) | ||
| } else if (skip_proto != PROTO_FASTCGI && (inferred_message.type = | ||
| #else | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
把多个 crate 都在用的依赖放到 agent/Cargo.toml 的 workspace 依赖里