pcapsql_core/protocol/
mod.rs1mod context;
42mod field;
43mod projection;
44mod pruning;
45mod registry;
46
47mod arp;
49mod bgp;
50mod dhcp;
51mod dns;
52mod ethernet;
53mod gre;
54mod gtp;
55mod icmp;
56mod icmpv6;
57mod ipsec;
58mod ipv4;
59mod ipv6;
60mod linux_sll;
61mod mpls;
62mod netlink;
63mod ntp;
64mod ospf;
65mod quic;
66mod rtnetlink;
67mod ssh;
68mod tcp;
69mod tls;
70mod udp;
71mod vlan;
72mod vxlan;
73
74#[cfg(test)]
76pub mod test_utils;
77
78pub use context::{FieldEntry, HintEntry, ParseContext, ParseResult, TunnelLayer, TunnelType};
79pub use field::{FieldValue, OwnedFieldValue};
80pub use projection::{chain_fields_for_protocol, merge_with_chain_fields, ProjectionConfig};
81pub use pruning::{compute_required_protocols, should_continue_parsing, should_run_parser};
82pub use registry::{BuiltinProtocol, PayloadMode, Protocol, ProtocolRegistry};
83
84pub use arp::ArpProtocol;
86pub use bgp::BgpProtocol;
87pub use dhcp::DhcpProtocol;
88pub use dns::DnsProtocol;
89pub use ethernet::EthernetProtocol;
90pub use gre::GreProtocol;
91pub use gtp::GtpProtocol;
92pub use icmp::IcmpProtocol;
93pub use icmpv6::Icmpv6Protocol;
94pub use ipsec::IpsecProtocol;
95pub use ipv4::Ipv4Protocol;
96pub use ipv6::Ipv6Protocol;
97pub use linux_sll::LinuxSllProtocol;
98pub use mpls::MplsProtocol;
99pub use netlink::NetlinkProtocol;
100pub use ntp::NtpProtocol;
101pub use ospf::OspfProtocol;
102pub use quic::QuicProtocol;
103pub use rtnetlink::RtnetlinkProtocol;
104pub use ssh::SshProtocol;
105pub use tcp::TcpProtocol;
106pub use tls::TlsProtocol;
107pub use udp::UdpProtocol;
108pub use vlan::VlanProtocol;
109pub use vxlan::VxlanProtocol;
110
111pub use dns::{rcode, record_type};
113pub use ethernet::ethertype;
114pub use ipv6::next_header;
115pub use netlink::family as netlink_family;
116
117pub fn default_registry() -> ProtocolRegistry {
119 let mut registry = ProtocolRegistry::new();
120
121 registry.register(EthernetProtocol);
123 registry.register(LinuxSllProtocol);
124 registry.register(ArpProtocol);
125 registry.register(VlanProtocol);
126 registry.register(MplsProtocol);
127
128 registry.register(Ipv4Protocol);
130 registry.register(Ipv6Protocol);
131
132 registry.register(TcpProtocol);
134 registry.register(UdpProtocol);
135 registry.register(IcmpProtocol);
136 registry.register(Icmpv6Protocol);
137
138 registry.register(GreProtocol);
140 registry.register(VxlanProtocol);
141 registry.register(GtpProtocol);
142 registry.register(IpsecProtocol);
143
144 registry.register(BgpProtocol);
146 registry.register(OspfProtocol);
147
148 registry.register(DnsProtocol);
151 registry.register(DhcpProtocol);
152 registry.register(NtpProtocol);
153 registry.register(TlsProtocol);
154 registry.register(SshProtocol);
155 registry.register(QuicProtocol);
156
157 registry.register(NetlinkProtocol);
159 registry.register(RtnetlinkProtocol);
160
161 registry
162}
163
164use std::collections::{HashMap, HashSet};
165
166pub fn parse_packet<'a>(
172 registry: &ProtocolRegistry,
173 link_type: u16,
174 data: &'a [u8],
175) -> Vec<(&'static str, ParseResult<'a>)> {
176 let mut results = Vec::with_capacity(8);
179 let mut context = ParseContext::new(link_type);
180 let mut remaining = data;
181
182 while !remaining.is_empty() {
183 if let Some(parser) = registry.find_parser(&context) {
184 let mut result = parser.parse(remaining, &context);
185
186 result.set_encap_context(&context);
189
190 if let Some(tunnel_type_val) = result.hint("tunnel_type") {
193 let tunnel_id = result.hint("tunnel_id");
194 context.push_tunnel(TunnelType::from_u64(tunnel_type_val), tunnel_id);
195 }
196
197 context.parent_protocol = Some(parser.name());
199 context.hints = result.child_hints.clone();
200 context.offset += remaining.len() - result.remaining.len();
201
202 let should_stop = result.error.is_some();
203 remaining = result.remaining;
204
205 results.push((parser.name(), result));
206
207 if should_stop {
208 break;
209 }
210 } else {
211 break;
212 }
213 }
214
215 results
216}
217
218pub fn parse_packet_pruned<'a>(
249 registry: &ProtocolRegistry,
250 link_type: u16,
251 data: &'a [u8],
252 required: &HashSet<String>,
253) -> Vec<(&'static str, ParseResult<'a>)> {
254 if required.is_empty() {
256 return parse_packet(registry, link_type, data);
257 }
258
259 let mut results = Vec::with_capacity(4);
261 let mut parsed_protocols: Vec<&str> = Vec::with_capacity(4);
262 let mut context = ParseContext::new(link_type);
263 let mut remaining = data;
264
265 while !remaining.is_empty() {
266 if !should_continue_parsing(&parsed_protocols, required) {
268 break;
269 }
270
271 let parser = match registry.find_parser(&context) {
273 Some(p) => p,
274 None => break,
275 };
276
277 let name = parser.name();
278
279 if !should_run_parser(name, required, registry) {
281 break;
283 }
284
285 let mut result = parser.parse(remaining, &context);
287 parsed_protocols.push(name);
288
289 result.set_encap_context(&context);
291
292 if let Some(tunnel_type_val) = result.hint("tunnel_type") {
294 let tunnel_id = result.hint("tunnel_id");
295 context.push_tunnel(TunnelType::from_u64(tunnel_type_val), tunnel_id);
296 }
297
298 context.parent_protocol = Some(name);
300 context.hints = result.child_hints.clone();
301 context.offset += remaining.len() - result.remaining.len();
302
303 let should_stop = result.error.is_some() || result.remaining.is_empty();
304 remaining = result.remaining;
305
306 results.push((name, result));
308
309 if should_stop {
310 break;
311 }
312 }
313
314 results
315}
316
317pub fn parse_packet_projected<'a>(
350 registry: &ProtocolRegistry,
351 link_type: u16,
352 data: &'a [u8],
353 projections: &HashMap<String, HashSet<String>>,
354) -> Vec<(&'static str, ParseResult<'a>)> {
355 if projections.is_empty() {
357 return parse_packet(registry, link_type, data);
358 }
359
360 let mut results = Vec::with_capacity(4);
362 let mut context = ParseContext::new(link_type);
363 let mut remaining = data;
364
365 while !remaining.is_empty() {
366 if let Some(parser) = registry.find_parser(&context) {
367 let name = parser.name();
368
369 let projection = projections.get(name);
371
372 let mut result = parser.parse_projected(remaining, &context, projection);
374
375 result.set_encap_context(&context);
377
378 if let Some(tunnel_type_val) = result.hint("tunnel_type") {
380 let tunnel_id = result.hint("tunnel_id");
381 context.push_tunnel(TunnelType::from_u64(tunnel_type_val), tunnel_id);
382 }
383
384 context.parent_protocol = Some(name);
386 context.hints = result.child_hints.clone();
387 context.offset += remaining.len() - result.remaining.len();
388
389 let should_stop = result.error.is_some();
390 remaining = result.remaining;
391
392 results.push((name, result));
393
394 if should_stop {
395 break;
396 }
397 } else {
398 break;
399 }
400 }
401
402 results
403}
404
405pub fn parse_packet_pruned_projected<'a>(
423 registry: &ProtocolRegistry,
424 link_type: u16,
425 data: &'a [u8],
426 required: &HashSet<String>,
427 projections: &HashMap<String, HashSet<String>>,
428) -> Vec<(&'static str, ParseResult<'a>)> {
429 if required.is_empty() && projections.is_empty() {
431 return parse_packet(registry, link_type, data);
432 }
433
434 if projections.is_empty() {
436 return parse_packet_pruned(registry, link_type, data, required);
437 }
438
439 if required.is_empty() {
441 return parse_packet_projected(registry, link_type, data, projections);
442 }
443
444 let mut results = Vec::with_capacity(4);
447 let mut parsed_protocols: Vec<&str> = Vec::with_capacity(4);
448 let mut context = ParseContext::new(link_type);
449 let mut remaining = data;
450
451 while !remaining.is_empty() {
452 if !should_continue_parsing(&parsed_protocols, required) {
454 break;
455 }
456
457 let parser = match registry.find_parser(&context) {
459 Some(p) => p,
460 None => break,
461 };
462
463 let name = parser.name();
464
465 if !should_run_parser(name, required, registry) {
467 break;
468 }
469
470 let projection = projections.get(name);
472
473 let mut result = parser.parse_projected(remaining, &context, projection);
475 parsed_protocols.push(name);
476
477 result.set_encap_context(&context);
479
480 if let Some(tunnel_type_val) = result.hint("tunnel_type") {
482 let tunnel_id = result.hint("tunnel_id");
483 context.push_tunnel(TunnelType::from_u64(tunnel_type_val), tunnel_id);
484 }
485
486 context.parent_protocol = Some(name);
488 context.hints = result.child_hints.clone();
489 context.offset += remaining.len() - result.remaining.len();
490
491 let should_stop = result.error.is_some() || result.remaining.is_empty();
492 remaining = result.remaining;
493
494 results.push((name, result));
495
496 if should_stop {
497 break;
498 }
499 }
500
501 results
502}
503
504#[cfg(test)]
505mod payload_mode_tests {
506 use super::*;
507
508 #[test]
510 fn test_default_payload_mode() {
511 let eth = EthernetProtocol;
513 assert_eq!(eth.payload_mode(), PayloadMode::Chain);
514
515 let ipv4 = Ipv4Protocol;
516 assert_eq!(ipv4.payload_mode(), PayloadMode::Chain);
517
518 let udp = UdpProtocol;
519 assert_eq!(udp.payload_mode(), PayloadMode::Chain);
520 }
521
522 #[test]
524 fn test_tcp_stream_mode() {
525 let tcp = TcpProtocol;
526 assert_eq!(tcp.payload_mode(), PayloadMode::Stream);
527 }
528
529 #[test]
531 fn test_tcp_no_child_protocols() {
532 let tcp = TcpProtocol;
533 assert!(tcp.child_protocols().is_empty());
534 }
535
536 #[test]
538 fn test_payload_mode_values() {
539 assert_ne!(PayloadMode::Chain, PayloadMode::Stream);
540 assert_ne!(PayloadMode::Stream, PayloadMode::None);
541 assert_ne!(PayloadMode::Chain, PayloadMode::None);
542 }
543}