1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
2
3use pnet::util::MacAddr;
4
5use crate::{nbpf_pkt_info_t, nbpf_pkt_info_tuple_t};
6
7pub enum IPversion {
8 IPv4,
9 IPv6,
10}
11
12impl Default for IPversion {
13 fn default() -> Self {
14 Self::IPv4
15 }
16}
17
18impl From<IPversion> for u8 {
19 fn from(value: IPversion) -> Self {
20 match value {
21 IPversion::IPv4 => 4,
22 IPversion::IPv6 => 6,
23 }
24 }
25}
26
27#[derive(Default)]
28pub struct PacketInfoBuilder {
29 device_id: Option<u16>,
31 interface_id: Option<u16>,
32 dmac: Option<MacAddr>,
33 smac: Option<MacAddr>,
34 vlan_id: Option<u16>,
35 vlan_id_qinq: Option<u16>,
36 l3_eth_type: Option<u16>,
37 l3_ip_version: Option<IPversion>,
39 l3_proto: Option<u8>,
40 l3_ip_tos: Option<u8>,
41 l3_ip_src: Option<IpAddr>,
42 l3_ip_dst: Option<IpAddr>,
43 l4_src_port: Option<u16>,
45 l4_dst_port: Option<u16>,
46
47 tunnel_eth_type: Option<u16>,
49 tunnel_ip_version: Option<IPversion>,
50 tunnel_l3_proto: Option<u8>,
51 tunnel_ip_tos: Option<u8>,
52 tunnel_ip_src: Option<IpAddr>,
53 tunnel_ip_dst: Option<IpAddr>,
54 tunnel_l4_src_port: Option<u16>,
55 tunnel_l4_dst_port: Option<u16>,
56
57 master_l7_proto: Option<u16>,
59 l7_proto: Option<u16>,
60}
61
62impl PacketInfoBuilder {
63 pub fn new() -> Self {
64 Self::default()
65 }
66
67 pub fn with_device_id(&mut self, device_id: u16) {
68 self.device_id = Some(device_id);
69 }
70
71 pub fn with_l2(&mut self, interface_id: u16, smac: MacAddr, dmac: MacAddr, eth_type: u16) {
73 self.interface_id = Some(interface_id);
74 self.smac = Some(smac);
75 self.dmac = Some(dmac);
76 self.l3_eth_type = Some(eth_type);
77 }
78
79 pub fn with_l2_vlan(&mut self, vlan_id: u16, vlan_id_qinq: u16) {
81 self.vlan_id = Some(vlan_id);
82 self.vlan_id_qinq = Some(vlan_id_qinq);
83 }
84
85 pub fn with_tunnel_l2(&mut self, eth_type: u16) {
86 self.tunnel_eth_type = Some(eth_type);
87 }
88
89 pub fn with_l3(&mut self, ip_version: IPversion, proto: u8, tos: u8, src: IpAddr, dst: IpAddr) {
91 self.l3_ip_version = Some(ip_version);
92 self.l3_proto = Some(proto);
93 self.l3_ip_tos = Some(tos);
94 self.l3_ip_src = Some(src);
95 self.l3_ip_dst = Some(dst);
96 }
97
98 pub fn with_tunnel_l3(
99 &mut self,
100 ip_version: IPversion,
101 proto: u8,
102 tos: u8,
103 src: IpAddr,
104 dst: IpAddr,
105 ) {
106 self.tunnel_ip_version = Some(ip_version);
107 self.tunnel_l3_proto = Some(proto);
108 self.tunnel_ip_tos = Some(tos);
109 self.tunnel_ip_src = Some(src);
110 self.tunnel_ip_dst = Some(dst);
111 }
112
113 pub fn with_l4(&mut self, src_port: u16, dst_port: u16) {
115 self.l4_src_port = Some(src_port);
116 self.l4_dst_port = Some(dst_port);
117 }
118
119 pub fn with_tunnel_l4(&mut self, src_port: u16, dst_port: u16) {
120 self.tunnel_l4_src_port = Some(src_port);
121 self.tunnel_l4_dst_port = Some(dst_port);
122 }
123
124 pub fn with_l7_master_proto(&mut self, master_l7_proto: u16) {
126 self.master_l7_proto = Some(master_l7_proto);
127 }
128
129 pub fn with_l7_proto(&mut self, l7_proto: u16) {
130 self.l7_proto = Some(l7_proto);
131 }
132
133 pub fn build(self) -> PacketInfo {
134 let nbpf_pkt_info = Box::new(nbpf_pkt_info_t {
135 device_id: self.device_id.unwrap_or_default(),
136 interface_id: self.interface_id.unwrap_or_default(),
137 dmac: self.dmac.unwrap_or_default().into(),
138 smac: self.smac.unwrap_or_default().into(),
139 vlan_id: self.vlan_id.unwrap_or(0),
140 vlan_id_qinq: self.vlan_id_qinq.unwrap_or(0),
141 tuple: nbpf_pkt_info_tuple_t {
142 eth_type: self.l3_eth_type.unwrap_or(0),
143 ip_version: self.l3_ip_version.unwrap_or_default().into(),
144 l3_proto: self.l3_proto.unwrap_or_default(),
145 ip_tos: self.l3_ip_tos.unwrap_or_default(),
146 ip_src: self
147 .l3_ip_src
148 .unwrap_or(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)))
149 .into(),
150 ip_dst: self
151 .l3_ip_dst
152 .unwrap_or(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)))
153 .into(),
154 l4_src_port: self.l4_src_port.unwrap_or_default().to_be(),
155 l4_dst_port: self.l4_dst_port.unwrap_or_default().to_be(),
156 },
157 tunneled_tuple: nbpf_pkt_info_tuple_t {
158 eth_type: self.tunnel_eth_type.unwrap_or_default(),
159 ip_version: self.tunnel_ip_version.unwrap_or_default().into(),
160 l3_proto: self.tunnel_l3_proto.unwrap_or_default(),
161 ip_tos: self.tunnel_ip_tos.unwrap_or_default(),
162 ip_src: self
163 .tunnel_ip_src
164 .unwrap_or(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)))
165 .into(),
166 ip_dst: self
167 .tunnel_ip_dst
168 .unwrap_or(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)))
169 .into(),
170 l4_src_port: self.tunnel_l4_src_port.unwrap_or_default().to_be(),
171 l4_dst_port: self.tunnel_l4_dst_port.unwrap_or_default().to_be(),
172 },
173 master_l7_proto: self.master_l7_proto.unwrap_or_default(),
174 l7_proto: self.l7_proto.unwrap_or_default(),
175 });
176
177 PacketInfo {
178 ptr: Box::into_raw(nbpf_pkt_info),
179 }
180 }
181}
182
183pub struct PacketInfo {
184 ptr: *mut nbpf_pkt_info_t,
185}
186
187impl PacketInfo {
188 pub(crate) fn get_ptr(&self) -> *mut nbpf_pkt_info_t {
189 self.ptr
190 }
191}
192
193impl Drop for PacketInfo {
194 fn drop(&mut self) {
195 drop(unsafe { Box::from_raw(self.ptr) })
196 }
197}