1 #[cfg(test)]
2 mod chunk_test;
3
4 use super::net::*;
5 use crate::error::Result;
6
7 use std::fmt;
8 use std::net::{IpAddr, SocketAddr};
9 use std::ops::{BitAnd, BitOr};
10 use std::str::FromStr;
11 use std::sync::atomic::{AtomicU64, Ordering};
12 use std::time::SystemTime;
13
14 lazy_static! {
15 static ref TAG_CTR: AtomicU64 = AtomicU64::new(0);
16 }
17
18 /// Encodes a u64 value to a lowercase base 36 string.
base36(value: impl Into<u64>) -> String19 pub fn base36(value: impl Into<u64>) -> String {
20 let mut digits: Vec<u8> = vec![];
21
22 let mut value = value.into();
23 while value > 0 {
24 let digit = (value % 36) as usize;
25 value /= 36;
26
27 digits.push(b"0123456789abcdefghijklmnopqrstuvwxyz"[digit]);
28 }
29
30 digits.reverse();
31 format!("{:0>8}", String::from_utf8(digits).unwrap())
32 }
33
34 // Generate a base36-encoded unique tag
35 // See: https://play.golang.org/p/0ZaAID1q-HN
assign_chunk_tag() -> String36 fn assign_chunk_tag() -> String {
37 let n = TAG_CTR.fetch_add(1, Ordering::SeqCst);
38 base36(n)
39 }
40
41 #[derive(Copy, Clone, PartialEq, Debug)]
42 pub(crate) struct TcpFlag(pub(crate) u8);
43
44 pub(crate) const TCP_FLAG_ZERO: TcpFlag = TcpFlag(0x00);
45 pub(crate) const TCP_FLAG_FIN: TcpFlag = TcpFlag(0x01);
46 pub(crate) const TCP_FLAG_SYN: TcpFlag = TcpFlag(0x02);
47 pub(crate) const TCP_FLAG_RST: TcpFlag = TcpFlag(0x04);
48 pub(crate) const TCP_FLAG_PSH: TcpFlag = TcpFlag(0x08);
49 pub(crate) const TCP_FLAG_ACK: TcpFlag = TcpFlag(0x10);
50
51 impl BitOr for TcpFlag {
52 type Output = Self;
53
54 // rhs is the "right-hand side" of the expression `a | b`
bitor(self, rhs: Self) -> Self::Output55 fn bitor(self, rhs: Self) -> Self::Output {
56 Self(self.0 | rhs.0)
57 }
58 }
59
60 impl BitAnd for TcpFlag {
61 type Output = Self;
62
63 // rhs is the "right-hand side" of the expression `a & b`
bitand(self, rhs: Self) -> Self::Output64 fn bitand(self, rhs: Self) -> Self::Output {
65 Self(self.0 & rhs.0)
66 }
67 }
68
69 impl fmt::Display for TcpFlag {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 let mut sa = vec![];
72 if *self & TCP_FLAG_FIN != TCP_FLAG_ZERO {
73 sa.push("FIN");
74 }
75 if *self & TCP_FLAG_SYN != TCP_FLAG_ZERO {
76 sa.push("SYN");
77 }
78 if *self & TCP_FLAG_RST != TCP_FLAG_ZERO {
79 sa.push("RST");
80 }
81 if *self & TCP_FLAG_PSH != TCP_FLAG_ZERO {
82 sa.push("PSH");
83 }
84 if *self & TCP_FLAG_ACK != TCP_FLAG_ZERO {
85 sa.push("ACK");
86 }
87
88 write!(f, "{}", sa.join("-"))
89 }
90 }
91
92 // Chunk represents a packet passed around in the vnet
93 pub trait Chunk: fmt::Display + fmt::Debug {
set_timestamp(&mut self) -> SystemTime94 fn set_timestamp(&mut self) -> SystemTime; // used by router
get_timestamp(&self) -> SystemTime95 fn get_timestamp(&self) -> SystemTime; // used by router
get_source_ip(&self) -> IpAddr96 fn get_source_ip(&self) -> IpAddr; // used by routee
get_destination_ip(&self) -> IpAddr97 fn get_destination_ip(&self) -> IpAddr; // used by router
set_source_addr(&mut self, address: &str) -> Result<()>98 fn set_source_addr(&mut self, address: &str) -> Result<()>; // used by nat
set_destination_addr(&mut self, address: &str) -> Result<()>99 fn set_destination_addr(&mut self, address: &str) -> Result<()>; // used by nat
100
source_addr(&self) -> SocketAddr101 fn source_addr(&self) -> SocketAddr;
destination_addr(&self) -> SocketAddr102 fn destination_addr(&self) -> SocketAddr;
user_data(&self) -> Vec<u8>103 fn user_data(&self) -> Vec<u8>;
tag(&self) -> String104 fn tag(&self) -> String;
network(&self) -> String105 fn network(&self) -> String; // returns "udp" or "tcp"
clone_to(&self) -> Box<dyn Chunk + Send + Sync>106 fn clone_to(&self) -> Box<dyn Chunk + Send + Sync>;
107 }
108
109 #[derive(PartialEq, Debug)]
110 pub(crate) struct ChunkIp {
111 pub(crate) timestamp: SystemTime,
112 pub(crate) source_ip: IpAddr,
113 pub(crate) destination_ip: IpAddr,
114 pub(crate) tag: String,
115 }
116
117 impl ChunkIp {
set_timestamp(&mut self) -> SystemTime118 fn set_timestamp(&mut self) -> SystemTime {
119 self.timestamp = SystemTime::now();
120 self.timestamp
121 }
122
get_timestamp(&self) -> SystemTime123 fn get_timestamp(&self) -> SystemTime {
124 self.timestamp
125 }
126
get_destination_ip(&self) -> IpAddr127 fn get_destination_ip(&self) -> IpAddr {
128 self.destination_ip
129 }
130
get_source_ip(&self) -> IpAddr131 fn get_source_ip(&self) -> IpAddr {
132 self.source_ip
133 }
134
tag(&self) -> String135 fn tag(&self) -> String {
136 self.tag.clone()
137 }
138 }
139
140 #[derive(PartialEq, Debug)]
141 pub(crate) struct ChunkUdp {
142 pub(crate) chunk_ip: ChunkIp,
143 pub(crate) source_port: u16,
144 pub(crate) destination_port: u16,
145 pub(crate) user_data: Vec<u8>,
146 }
147
148 impl fmt::Display for ChunkUdp {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 write!(
151 f,
152 "{} chunk {} {} => {}",
153 self.network(),
154 self.tag(),
155 self.source_addr(),
156 self.destination_addr(),
157 )
158 }
159 }
160
161 impl Chunk for ChunkUdp {
set_timestamp(&mut self) -> SystemTime162 fn set_timestamp(&mut self) -> SystemTime {
163 self.chunk_ip.set_timestamp()
164 }
165
get_timestamp(&self) -> SystemTime166 fn get_timestamp(&self) -> SystemTime {
167 self.chunk_ip.get_timestamp()
168 }
169
get_destination_ip(&self) -> IpAddr170 fn get_destination_ip(&self) -> IpAddr {
171 self.chunk_ip.get_destination_ip()
172 }
173
get_source_ip(&self) -> IpAddr174 fn get_source_ip(&self) -> IpAddr {
175 self.chunk_ip.get_source_ip()
176 }
177
tag(&self) -> String178 fn tag(&self) -> String {
179 self.chunk_ip.tag()
180 }
181
source_addr(&self) -> SocketAddr182 fn source_addr(&self) -> SocketAddr {
183 SocketAddr::new(self.chunk_ip.source_ip, self.source_port)
184 }
185
destination_addr(&self) -> SocketAddr186 fn destination_addr(&self) -> SocketAddr {
187 SocketAddr::new(self.chunk_ip.destination_ip, self.destination_port)
188 }
189
user_data(&self) -> Vec<u8>190 fn user_data(&self) -> Vec<u8> {
191 self.user_data.clone()
192 }
193
clone_to(&self) -> Box<dyn Chunk + Send + Sync>194 fn clone_to(&self) -> Box<dyn Chunk + Send + Sync> {
195 Box::new(ChunkUdp {
196 chunk_ip: ChunkIp {
197 timestamp: self.chunk_ip.timestamp,
198 source_ip: self.chunk_ip.source_ip,
199 destination_ip: self.chunk_ip.destination_ip,
200 tag: self.chunk_ip.tag.clone(),
201 },
202 source_port: self.source_port,
203 destination_port: self.destination_port,
204 user_data: self.user_data.clone(),
205 })
206 }
207
network(&self) -> String208 fn network(&self) -> String {
209 UDP_STR.to_owned()
210 }
211
set_source_addr(&mut self, address: &str) -> Result<()>212 fn set_source_addr(&mut self, address: &str) -> Result<()> {
213 let addr = SocketAddr::from_str(address)?;
214 self.chunk_ip.source_ip = addr.ip();
215 self.source_port = addr.port();
216 Ok(())
217 }
218
set_destination_addr(&mut self, address: &str) -> Result<()>219 fn set_destination_addr(&mut self, address: &str) -> Result<()> {
220 let addr = SocketAddr::from_str(address)?;
221 self.chunk_ip.destination_ip = addr.ip();
222 self.destination_port = addr.port();
223 Ok(())
224 }
225 }
226
227 impl ChunkUdp {
new(src_addr: SocketAddr, dst_addr: SocketAddr) -> Self228 pub(crate) fn new(src_addr: SocketAddr, dst_addr: SocketAddr) -> Self {
229 ChunkUdp {
230 chunk_ip: ChunkIp {
231 timestamp: SystemTime::now(),
232 source_ip: src_addr.ip(),
233 destination_ip: dst_addr.ip(),
234 tag: assign_chunk_tag(),
235 },
236 source_port: src_addr.port(),
237 destination_port: dst_addr.port(),
238 user_data: vec![],
239 }
240 }
241 }
242
243 #[derive(PartialEq, Debug)]
244 pub(crate) struct ChunkTcp {
245 chunk_ip: ChunkIp,
246 source_port: u16,
247 destination_port: u16,
248 flags: TcpFlag, // control bits
249 user_data: Vec<u8>, // only with PSH flag
250 // seq :u32, // always starts with 0
251 // ack :u32, // always starts with 0
252 }
253
254 impl fmt::Display for ChunkTcp {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 write!(
257 f,
258 "{} {} chunk {} {} => {}",
259 self.network(),
260 self.flags,
261 self.chunk_ip.tag,
262 self.source_addr(),
263 self.destination_addr(),
264 )
265 }
266 }
267
268 impl Chunk for ChunkTcp {
set_timestamp(&mut self) -> SystemTime269 fn set_timestamp(&mut self) -> SystemTime {
270 self.chunk_ip.set_timestamp()
271 }
272
get_timestamp(&self) -> SystemTime273 fn get_timestamp(&self) -> SystemTime {
274 self.chunk_ip.get_timestamp()
275 }
276
get_destination_ip(&self) -> IpAddr277 fn get_destination_ip(&self) -> IpAddr {
278 self.chunk_ip.get_destination_ip()
279 }
280
get_source_ip(&self) -> IpAddr281 fn get_source_ip(&self) -> IpAddr {
282 self.chunk_ip.get_source_ip()
283 }
284
tag(&self) -> String285 fn tag(&self) -> String {
286 self.chunk_ip.tag()
287 }
288
source_addr(&self) -> SocketAddr289 fn source_addr(&self) -> SocketAddr {
290 SocketAddr::new(self.chunk_ip.source_ip, self.source_port)
291 }
292
destination_addr(&self) -> SocketAddr293 fn destination_addr(&self) -> SocketAddr {
294 SocketAddr::new(self.chunk_ip.destination_ip, self.destination_port)
295 }
296
user_data(&self) -> Vec<u8>297 fn user_data(&self) -> Vec<u8> {
298 self.user_data.clone()
299 }
300
clone_to(&self) -> Box<dyn Chunk + Send + Sync>301 fn clone_to(&self) -> Box<dyn Chunk + Send + Sync> {
302 Box::new(ChunkTcp {
303 chunk_ip: ChunkIp {
304 timestamp: self.chunk_ip.timestamp,
305 source_ip: self.chunk_ip.source_ip,
306 destination_ip: self.chunk_ip.destination_ip,
307 tag: self.chunk_ip.tag.clone(),
308 },
309 source_port: self.source_port,
310 destination_port: self.destination_port,
311 flags: self.flags,
312 user_data: self.user_data.clone(),
313 })
314 }
315
network(&self) -> String316 fn network(&self) -> String {
317 "tcp".to_owned()
318 }
319
set_source_addr(&mut self, address: &str) -> Result<()>320 fn set_source_addr(&mut self, address: &str) -> Result<()> {
321 let addr = SocketAddr::from_str(address)?;
322 self.chunk_ip.source_ip = addr.ip();
323 self.source_port = addr.port();
324 Ok(())
325 }
326
set_destination_addr(&mut self, address: &str) -> Result<()>327 fn set_destination_addr(&mut self, address: &str) -> Result<()> {
328 let addr = SocketAddr::from_str(address)?;
329 self.chunk_ip.destination_ip = addr.ip();
330 self.destination_port = addr.port();
331 Ok(())
332 }
333 }
334
335 impl ChunkTcp {
new(src_addr: SocketAddr, dst_addr: SocketAddr, flags: TcpFlag) -> Self336 pub(crate) fn new(src_addr: SocketAddr, dst_addr: SocketAddr, flags: TcpFlag) -> Self {
337 ChunkTcp {
338 chunk_ip: ChunkIp {
339 timestamp: SystemTime::now(),
340 source_ip: src_addr.ip(),
341 destination_ip: dst_addr.ip(),
342 tag: assign_chunk_tag(),
343 },
344 source_port: src_addr.port(),
345 destination_port: dst_addr.port(),
346 flags,
347 user_data: vec![],
348 }
349 }
350 }
351