1use crate::errors::{Result, SandboxError};
4use serde::{Deserialize, Serialize};
5use std::net::{IpAddr, Ipv4Addr, SocketAddr};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct NetworkInterface {
10 pub name: String,
12 pub ipv4: Ipv4Addr,
14 pub netmask: Ipv4Addr,
16 pub gateway: Option<Ipv4Addr>,
18 pub enabled: bool,
20}
21
22impl Default for NetworkInterface {
23 fn default() -> Self {
24 Self {
25 name: "eth0".to_string(),
26 ipv4: Ipv4Addr::new(172, 17, 0, 2),
27 netmask: Ipv4Addr::new(255, 255, 255, 0),
28 gateway: Some(Ipv4Addr::new(172, 17, 0, 1)),
29 enabled: true,
30 }
31 }
32}
33
34impl NetworkInterface {
35 pub fn new(name: &str, ipv4: Ipv4Addr) -> Self {
37 Self {
38 name: name.to_string(),
39 ipv4,
40 netmask: Ipv4Addr::new(255, 255, 255, 0),
41 gateway: Some(Ipv4Addr::new(172, 17, 0, 1)),
42 enabled: true,
43 }
44 }
45
46 pub fn validate(&self) -> Result<()> {
48 if self.name.is_empty() {
49 return Err(SandboxError::InvalidConfig(
50 "Interface name cannot be empty".to_string(),
51 ));
52 }
53
54 if self.ipv4.is_unspecified() || self.ipv4.is_broadcast() {
56 return Err(SandboxError::InvalidConfig(
57 "Invalid IP address for interface".to_string(),
58 ));
59 }
60
61 Ok(())
62 }
63
64 pub fn get_cidr(&self) -> String {
66 format!("{}/{}", self.ipv4, self.netmask_bits())
67 }
68
69 pub fn netmask_bits(&self) -> u8 {
71 let octets = self.netmask.octets();
72 let mut bits = 0u8;
73
74 for octet in octets {
75 bits += octet.count_ones() as u8;
76 }
77
78 bits
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
84pub enum NetworkMode {
85 #[default]
87 Isolated,
88 Bridge,
90 Host,
92 Custom,
94}
95
96impl std::fmt::Display for NetworkMode {
97 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 match self {
99 NetworkMode::Isolated => write!(f, "isolated"),
100 NetworkMode::Bridge => write!(f, "bridge"),
101 NetworkMode::Host => write!(f, "host"),
102 NetworkMode::Custom => write!(f, "custom"),
103 }
104 }
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct NetworkConfig {
110 pub mode: NetworkMode,
112 pub interfaces: Vec<NetworkInterface>,
114 pub dns_servers: Vec<IpAddr>,
116 pub port_mappings: Vec<PortMapping>,
118 pub ip_forward: bool,
120 pub bandwidth_limit: u64,
122}
123
124impl Default for NetworkConfig {
125 fn default() -> Self {
126 Self {
127 mode: NetworkMode::Isolated,
128 interfaces: vec![NetworkInterface::default()],
129 dns_servers: vec![
130 IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)),
131 IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)),
132 ],
133 port_mappings: Vec::new(),
134 ip_forward: false,
135 bandwidth_limit: 0,
136 }
137 }
138}
139
140impl NetworkConfig {
141 pub fn isolated() -> Self {
143 Self {
144 mode: NetworkMode::Isolated,
145 interfaces: vec![NetworkInterface::default()],
146 dns_servers: vec![IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))],
147 port_mappings: Vec::new(),
148 ip_forward: false,
149 bandwidth_limit: 0,
150 }
151 }
152
153 pub fn host() -> Self {
155 Self {
156 mode: NetworkMode::Host,
157 interfaces: Vec::new(),
158 dns_servers: Vec::new(),
159 port_mappings: Vec::new(),
160 ip_forward: true,
161 bandwidth_limit: 0,
162 }
163 }
164
165 pub fn add_interface(&mut self, iface: NetworkInterface) -> Result<()> {
167 iface.validate()?;
168 self.interfaces.push(iface);
169 Ok(())
170 }
171
172 pub fn add_port_mapping(&mut self, mapping: PortMapping) -> Result<()> {
174 mapping.validate()?;
175 self.port_mappings.push(mapping);
176 Ok(())
177 }
178
179 pub fn validate(&self) -> Result<()> {
181 for iface in &self.interfaces {
182 iface.validate()?;
183 }
184
185 for mapping in &self.port_mappings {
186 mapping.validate()?;
187 }
188
189 Ok(())
190 }
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct PortMapping {
196 pub container_port: u16,
198 pub host_port: u16,
200 pub protocol: String,
202}
203
204impl PortMapping {
205 pub fn new(container_port: u16, host_port: u16) -> Self {
207 Self {
208 container_port,
209 host_port,
210 protocol: "tcp".to_string(),
211 }
212 }
213
214 pub fn validate(&self) -> Result<()> {
216 if self.container_port == 0 || self.host_port == 0 {
217 return Err(SandboxError::InvalidConfig(
218 "Port numbers must be > 0".to_string(),
219 ));
220 }
221
222 if !["tcp", "udp"].contains(&self.protocol.as_str()) {
223 return Err(SandboxError::InvalidConfig(
224 "Protocol must be tcp or udp".to_string(),
225 ));
226 }
227
228 Ok(())
229 }
230
231 pub fn get_host_addr(&self) -> SocketAddr {
233 SocketAddr::from((Ipv4Addr::LOCALHOST, self.host_port))
234 }
235
236 pub fn get_container_addr(&self, ip: Ipv4Addr) -> SocketAddr {
238 SocketAddr::from((ip, self.container_port))
239 }
240}
241
242#[derive(Debug, Clone, Default, Serialize, Deserialize)]
244pub struct NetworkStats {
245 pub bytes_recv: u64,
247 pub bytes_sent: u64,
249 pub packets_recv: u64,
251 pub packets_sent: u64,
253 pub errors: u64,
255 pub dropped: u64,
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262
263 #[test]
264 fn test_network_interface_creation() {
265 let iface = NetworkInterface::new("eth0", Ipv4Addr::new(192, 168, 1, 10));
266 assert_eq!(iface.name, "eth0");
267 assert_eq!(iface.ipv4, Ipv4Addr::new(192, 168, 1, 10));
268 }
269
270 #[test]
271 fn test_network_interface_validation() {
272 let mut iface = NetworkInterface::default();
273 assert!(iface.validate().is_ok());
274
275 iface.ipv4 = Ipv4Addr::UNSPECIFIED;
276 assert!(iface.validate().is_err());
277 }
278
279 #[test]
280 fn test_network_interface_cidr() {
281 let iface = NetworkInterface::default();
282 let cidr = iface.get_cidr();
283 assert!(cidr.contains("/"));
284 }
285
286 #[test]
287 fn test_netmask_bits() {
288 let iface = NetworkInterface {
289 netmask: Ipv4Addr::new(255, 255, 255, 0),
290 ..Default::default()
291 };
292 assert_eq!(iface.netmask_bits(), 24);
293 }
294
295 #[test]
296 fn test_network_mode_display() {
297 assert_eq!(NetworkMode::Isolated.to_string(), "isolated");
298 assert_eq!(NetworkMode::Bridge.to_string(), "bridge");
299 assert_eq!(NetworkMode::Host.to_string(), "host");
300 }
301
302 #[test]
303 fn test_network_config_default() {
304 let config = NetworkConfig::default();
305 assert_eq!(config.mode, NetworkMode::Isolated);
306 assert!(!config.interfaces.is_empty());
307 }
308
309 #[test]
310 fn test_network_config_isolated() {
311 let config = NetworkConfig::isolated();
312 assert_eq!(config.mode, NetworkMode::Isolated);
313 }
314
315 #[test]
316 fn test_network_config_host() {
317 let config = NetworkConfig::host();
318 assert_eq!(config.mode, NetworkMode::Host);
319 assert!(config.ip_forward);
320 }
321
322 #[test]
323 fn test_port_mapping_creation() {
324 let mapping = PortMapping::new(8080, 8080);
325 assert_eq!(mapping.container_port, 8080);
326 assert_eq!(mapping.host_port, 8080);
327 }
328
329 #[test]
330 fn test_port_mapping_validation() {
331 let mapping = PortMapping::new(8080, 8080);
332 assert!(mapping.validate().is_ok());
333
334 let bad_mapping = PortMapping {
335 container_port: 0,
336 host_port: 8080,
337 protocol: "tcp".to_string(),
338 };
339 assert!(bad_mapping.validate().is_err());
340 }
341
342 #[test]
343 fn test_port_mapping_addresses() {
344 let mapping = PortMapping::new(8080, 8080);
345 let host_addr = mapping.get_host_addr();
346 assert_eq!(host_addr.port(), 8080);
347 }
348
349 #[test]
350 fn test_network_stats_default() {
351 let stats = NetworkStats::default();
352 assert_eq!(stats.bytes_recv, 0);
353 assert_eq!(stats.bytes_sent, 0);
354 }
355}