net_file/jsons/
json_pcap_parser.rs

1use chrono::{DateTime, Utc};
2use serde_json::{json, Value};
3use unescape::unescape;
4
5use crate::jsons::json_parser::JsonParser;
6
7pub const PATH_SOURCE_LAYER: &str = "$.._source.layers";
8pub const PATH_FRAME_TIME: &str = "$..frame['frame.time']";
9pub const PATH_FRAME_TIME_EPOCH: &str = "$..frame['frame.time_epoch']";
10const L3_PATH: &str = "/l3";
11
12pub struct JsonPcapParser;
13
14impl JsonPcapParser {
15    pub fn filter_source_layer(json_binary: &[u8]) -> Value {
16        JsonParser::find(json_binary, PATH_SOURCE_LAYER)
17    }
18
19    pub fn find_frame_time(json_binary: &[u8]) -> DateTime<Utc> {
20        let value = JsonParser::find(json_binary, PATH_FRAME_TIME);
21        JsonParser::get_utc_frame_time(value)
22    }
23
24    pub fn find_utc_timestamp_millis(json_binary: &[u8]) -> i64 {
25        let value = JsonParser::find(json_binary, PATH_FRAME_TIME_EPOCH);
26        JsonParser::get_utc_timestamp_millis(value)
27    }
28
29    pub fn find_utc_timestamp_nanos(json_binary: &[u8]) -> i64 {
30        let value = JsonParser::find(json_binary, PATH_FRAME_TIME_EPOCH);
31        JsonParser::get_utc_timestamp_nanos(value)
32    }
33
34    pub fn split_into_layers(value_json: &Value) -> Value {
35        let mut new_json = json!({});
36        let object_json = new_json.as_object_mut().unwrap();
37
38        value_json
39            .as_object()
40            .unwrap()
41            .keys()
42            .map(|k| k.as_str())
43            .enumerate()
44            .for_each(|(index, field)| {
45                object_json.insert(
46                    format!("l{}", index + 1),
47                    json!({ field: &value_json[field] }),
48                );
49            });
50
51        new_json
52    }
53
54    fn extract_field_name(l3_value: &Value) -> &str {
55        l3_value
56            .as_object()
57            .unwrap()
58            .keys()
59            .map(|k| k.as_str())
60            .last()
61            .unwrap()
62    }
63
64    ///
65    ///
66    /// # Arguments
67    ///
68    /// * `l3_field_name`:
69    ///
70    /// returns: &str
71    ///
72    /// # Examples
73    ///
74    /// ```json
75    /// {
76    ///     "ip": {
77    //          "ip.version": "4",
78    //          "ip.src": "0.0.0.0",
79    //          "ip.hdr_len": "20",
80    //          "ip.dsfield": "0x00"
81    //      }
82    //  }
83    //
84    // /ip/ip.src
85    // /ip/ip.dst
86    //
87    /// ```
88    fn create_src_addr_path(field_name_prefix: &str, field_name_suffix: &str) -> String {
89        format!(
90            "/{}/{}.{}",
91            field_name_prefix, field_name_prefix, field_name_suffix
92        )
93    }
94
95    fn extract_ip_addr_l3(json_value: &Value, target: &str) -> Option<String> {
96        let l3_value = json_value.pointer(L3_PATH).unwrap();
97        let l3_field_name = Self::extract_field_name(l3_value);
98        let addr_path = Self::create_src_addr_path(l3_field_name, target);
99        let addr_value = l3_value.pointer(addr_path.as_str());
100
101        match addr_value {
102            None => None,
103            Some(addr_value) => unescape(addr_value.as_str().unwrap()),
104        }
105    }
106
107    pub fn extract_src_addr_l3(json_value: &Value) -> Option<String> {
108        Self::extract_ip_addr_l3(json_value, "src")
109    }
110
111    pub fn extract_dst_addr_l3(json_value: &Value) -> Option<String> {
112        Self::extract_ip_addr_l3(json_value, "dst")
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use std::str::from_utf8;
119    use crate::file::files::Files;
120    use crate::test_resources;
121
122    use super::*;
123
124    #[test]
125    fn expected_filter_source_layer() {
126        let pcap_buffer = Files::read_vector(test_resources!("captures/arp.json"));
127        let json_buffer = Files::read_vector(test_resources!("captures/arp_layer_extracted.json"));
128
129        let result = JsonPcapParser::filter_source_layer(&pcap_buffer);
130        let json = JsonParser::print(&result);
131
132        assert_eq!(json, from_utf8(&json_buffer).unwrap());
133    }
134
135    #[test]
136    fn expected_filter_source_layer_pretty() {
137        let pcap_buffer = Files::read_vector(test_resources!("captures/arp.json"));
138        let json_buffer =
139            Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
140
141        let result = JsonPcapParser::filter_source_layer(&pcap_buffer);
142        let json = JsonParser::pretty(&result);
143
144        assert_eq!(json, from_utf8(&json_buffer).unwrap());
145    }
146
147    #[test]
148    fn expected_extract_frame_time() {
149        let pcap_buffer =
150            Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
151
152        let result = JsonPcapParser::find_frame_time(&pcap_buffer);
153
154        assert_eq!(result.to_string(), "2013-09-18 04:49:07 UTC");
155    }
156
157    #[test]
158    fn expected_extract_utc_timestamp_millis() {
159        const EXPECTED_TIME: i64 = 1379479747000;
160        let pcap_buffer =
161            Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
162        let result = JsonPcapParser::find_utc_timestamp_millis(&pcap_buffer);
163
164        assert_eq!(EXPECTED_TIME, result);
165    }
166
167    #[test]
168    fn expected_extract_utc_timestamp_nanos() {
169        const EXPECTED_TIME: i64 = 1379479747000000000;
170        let pcap_buffer =
171            Files::read_vector(test_resources!("captures/arp_layer_extracted_pretty.json"));
172        let result = JsonPcapParser::find_utc_timestamp_nanos(&pcap_buffer);
173
174        assert_eq!(EXPECTED_TIME, result);
175    }
176
177    #[test]
178    fn expected_extract_utc_timestamp_nanos_2() {
179        const EXPECTED_TIME: i64 = 1688714981480935000;
180        let pcap_buffer =
181            Files::read_vector(test_resources!("captures/epoch_frame_time.json"));
182        let result = JsonPcapParser::find_utc_timestamp_nanos(&pcap_buffer);
183
184        assert_eq!(EXPECTED_TIME, result);
185    }
186
187    #[test]
188    fn expected_layered_json_into_layers() {
189        let pcap_buffer = Files::read_vector(test_resources!("captures/arp.json"));
190        let json_buffer = Files::read_vector(test_resources!("captures/arp_layers.json"));
191
192        let result = JsonParser::find(&pcap_buffer, "$.._source.layers");
193        let first_value = JsonParser::first(&result).unwrap();
194        let layered_json = JsonPcapParser::split_into_layers(&first_value);
195        let json = JsonParser::pretty(&layered_json);
196
197        assert_eq!(json, from_utf8(&json_buffer).unwrap());
198    }
199
200    #[test]
201    fn expected_extract_src_address_from_l3() {
202        let pcap_buffer = Files::read_vector(test_resources!("captures/dhcp_one_packet.json"));
203
204        let result = JsonParser::find(&pcap_buffer, "$.._source.layers");
205        let first_value = JsonParser::first(&result).unwrap();
206        let layered_json = JsonPcapParser::split_into_layers(&first_value);
207
208        let string = JsonPcapParser::extract_src_addr_l3(&layered_json).unwrap();
209
210        assert_eq!(string, "0.0.0.0");
211    }
212
213    #[test]
214    fn expected_extract_dst_address_from_l3() {
215        let pcap_buffer = Files::read_vector(test_resources!("captures/dhcp_one_packet.json"));
216
217        let result = JsonParser::find(&pcap_buffer, "$.._source.layers");
218        let first_value = JsonParser::first(&result).unwrap();
219        let layered_json = JsonPcapParser::split_into_layers(&first_value);
220
221        let string = JsonPcapParser::extract_dst_addr_l3(&layered_json).unwrap();
222
223        assert_eq!(string, "255.255.255.255");
224    }
225
226    #[test]
227    fn expected_none_when_path_invalid() {
228        let pcap_buffer = Files::read_vector(test_resources!("captures/dhcp_one_packet.json"));
229
230        let result = JsonParser::find(&pcap_buffer, "$.._source.layers");
231        let first_value = JsonParser::first(&result).unwrap();
232        let layered_json = JsonPcapParser::split_into_layers(&first_value);
233
234        let string = JsonPcapParser::extract_ip_addr_l3(&layered_json, "any");
235
236        assert_eq!(string, None);
237    }
238}