/src/suricata7/rust/src/modbus/log.rs
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2021 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | use super::modbus::ModbusTransaction; |
19 | | use crate::jsonbuilder::{JsonBuilder, JsonError}; |
20 | | |
21 | | use sawp_modbus::{Data, Message, Read, Write}; |
22 | | |
23 | | #[no_mangle] |
24 | 10.8k | pub extern "C" fn rs_modbus_to_json(tx: &mut ModbusTransaction, js: &mut JsonBuilder) -> bool { |
25 | 10.8k | log(tx, js).is_ok() |
26 | 10.8k | } |
27 | | |
28 | | /// populate a json object with transactional information, for logging |
29 | 10.8k | fn log(tx: &ModbusTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { |
30 | 10.8k | js.open_object("modbus")?; |
31 | 10.8k | js.set_uint("id", tx.id)?; |
32 | | |
33 | 10.8k | if let Some(req) = &tx.request { |
34 | 6.73k | js.open_object("request")?; |
35 | 6.73k | log_message(req, js)?; |
36 | 6.73k | js.close()?; |
37 | 4.14k | } |
38 | | |
39 | 10.8k | if let Some(resp) = &tx.response { |
40 | 5.24k | js.open_object("response")?; |
41 | 5.24k | log_message(resp, js)?; |
42 | 5.24k | js.close()?; |
43 | 5.64k | } |
44 | | |
45 | 10.8k | js.close()?; |
46 | 10.8k | Ok(()) |
47 | 10.8k | } |
48 | | |
49 | 11.9k | fn log_message(msg: &Message, js: &mut JsonBuilder) -> Result<(), JsonError> { |
50 | 11.9k | js.set_uint("transaction_id", msg.transaction_id.into())?; |
51 | 11.9k | js.set_uint("protocol_id", msg.protocol_id.into())?; |
52 | 11.9k | js.set_uint("unit_id", msg.unit_id.into())?; |
53 | 11.9k | js.set_uint("function_raw", msg.function.raw.into())?; |
54 | 11.9k | js.set_string("function_code", &msg.function.code.to_string())?; |
55 | 11.9k | js.set_string("access_type", &msg.access_type.to_string())?; |
56 | 11.9k | js.set_string("category", &msg.category.to_string())?; |
57 | 11.9k | js.set_string("error_flags", &msg.error_flags.to_string())?; |
58 | | |
59 | 11.9k | match &msg.data { |
60 | 148 | Data::Exception(exc) => { |
61 | 148 | js.open_object("exception")?; |
62 | 148 | js.set_uint("raw", exc.raw.into())?; |
63 | 148 | js.set_string("code", &exc.code.to_string())?; |
64 | 148 | js.close()?; |
65 | | } |
66 | 31 | Data::Diagnostic { func, data } => { |
67 | 31 | js.open_object("diagnostic")?; |
68 | 31 | js.set_uint("raw", func.raw.into())?; |
69 | 31 | js.set_string("code", &func.code.to_string())?; |
70 | 31 | js.set_string_from_bytes("data", data)?; |
71 | 31 | js.close()?; |
72 | | } |
73 | 22 | Data::MEI { mei_type, data } => { |
74 | 22 | js.open_object("mei")?; |
75 | 22 | js.set_uint("raw", mei_type.raw.into())?; |
76 | 22 | js.set_string("code", &mei_type.code.to_string())?; |
77 | 22 | js.set_string_from_bytes("data", data)?; |
78 | 22 | js.close()?; |
79 | | } |
80 | 551 | Data::Read(read) => { |
81 | 551 | js.open_object("read")?; |
82 | 551 | log_read(read, js)?; |
83 | 551 | js.close()?; |
84 | | } |
85 | 846 | Data::Write(write) => { |
86 | 846 | js.open_object("write")?; |
87 | 846 | log_write(write, js)?; |
88 | 846 | js.close()?; |
89 | | } |
90 | 0 | Data::ReadWrite { read, write } => { |
91 | 0 | js.open_object("read")?; |
92 | 0 | log_read(read, js)?; |
93 | 0 | js.close()?; |
94 | 0 | js.open_object("write")?; |
95 | 0 | log_write(write, js)?; |
96 | 0 | js.close()?; |
97 | | } |
98 | 1.28k | Data::ByteVec(data) => { |
99 | 1.28k | js.set_string_from_bytes("data", data)?; |
100 | | } |
101 | 9.09k | Data::Empty => {} |
102 | | } |
103 | | |
104 | 11.9k | Ok(()) |
105 | 11.9k | } |
106 | | |
107 | 551 | fn log_read(read: &Read, js: &mut JsonBuilder) -> Result<(), JsonError> { |
108 | 551 | match read { |
109 | 272 | Read::Request { address, quantity } => { |
110 | 272 | js.set_uint("address", (*address).into())?; |
111 | 272 | js.set_uint("quantity", (*quantity).into())?; |
112 | | } |
113 | 279 | Read::Response(data) => { |
114 | 279 | js.set_string_from_bytes("data", data)?; |
115 | | } |
116 | | } |
117 | | |
118 | 551 | Ok(()) |
119 | 551 | } |
120 | | |
121 | 846 | fn log_write(write: &Write, js: &mut JsonBuilder) -> Result<(), JsonError> { |
122 | 846 | match write { |
123 | | Write::MultReq { |
124 | 361 | address, |
125 | 361 | quantity, |
126 | 361 | data, |
127 | 361 | } => { |
128 | 361 | js.set_uint("address", (*address).into())?; |
129 | 361 | js.set_uint("quantity", (*quantity).into())?; |
130 | 361 | js.set_string_from_bytes("data", data)?; |
131 | | } |
132 | | Write::Mask { |
133 | 63 | address, |
134 | 63 | and_mask, |
135 | 63 | or_mask, |
136 | 63 | } => { |
137 | 63 | js.set_uint("address", (*address).into())?; |
138 | 63 | js.set_uint("and_mask", (*and_mask).into())?; |
139 | 63 | js.set_uint("or_mask", (*or_mask).into())?; |
140 | | } |
141 | 422 | Write::Other { address, data } => { |
142 | 422 | js.set_uint("address", (*address).into())?; |
143 | 422 | js.set_uint("data", (*data).into())?; |
144 | | } |
145 | | } |
146 | | |
147 | 846 | Ok(()) |
148 | 846 | } |