1use super::{Tunnel, TunnelConfig, TunnelMetrics, TunnelState, TunnelProtocol};
14use crate::{P2PError, Result};
15use async_trait::async_trait;
16use std::net::{Ipv4Addr, Ipv6Addr};
17use std::time::{Duration, Instant};
18use tokio::sync::RwLock;
19use tracing::{debug, info};
20
21const SIXTO4_PREFIX: u16 = 0x2002;
23
24const IPV6_IN_IPV4_PROTOCOL: u8 = 41;
26
27pub struct SixToFourTunnel {
29 config: TunnelConfig,
31 state: RwLock<TunnelState>,
33 metrics: RwLock<TunnelMetrics>,
35 local_ipv4: Option<Ipv4Addr>,
37 local_ipv6: Option<Ipv6Addr>,
39 established_at: Option<Instant>,
41}
42
43impl SixToFourTunnel {
44 pub fn new(config: TunnelConfig) -> Result<Self> {
46 if config.protocol != TunnelProtocol::SixToFour {
47 return Err(P2PError::Network(
48 "Invalid protocol for 6to4 tunnel".to_string()
49 ).into());
50 }
51
52 Ok(Self {
53 config,
54 state: RwLock::new(TunnelState::Disconnected),
55 metrics: RwLock::new(TunnelMetrics::default()),
56 local_ipv4: None,
57 local_ipv6: None,
58 established_at: None,
59 })
60 }
61
62 fn generate_ipv6_address(ipv4: Ipv4Addr) -> Ipv6Addr {
64 let octets = ipv4.octets();
65 Ipv6Addr::from([
66 (SIXTO4_PREFIX >> 8) as u8, (SIXTO4_PREFIX & 0xFF) as u8, octets[0], octets[1], octets[2], octets[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ])
74 }
75
76 fn extract_ipv4_destination(ipv6: &Ipv6Addr) -> Option<Ipv4Addr> {
78 let segments = ipv6.segments();
79
80 if segments[0] != SIXTO4_PREFIX {
82 return None;
83 }
84
85 let octet1 = (segments[1] >> 8) as u8;
87 let octet2 = (segments[1] & 0xFF) as u8;
88 let octet3 = (segments[2] >> 8) as u8;
89 let octet4 = (segments[2] & 0xFF) as u8;
90
91 Some(Ipv4Addr::new(octet1, octet2, octet3, octet4))
92 }
93
94 fn create_ipv4_header(&self, dst_ipv4: Ipv4Addr, payload_len: usize) -> Vec<u8> {
96 let mut header = vec![0u8; 20]; header[0] = 0x45;
100
101 header[1] = 0x00;
103
104 let total_len = 20 + payload_len;
106 header[2] = (total_len >> 8) as u8;
107 header[3] = (total_len & 0xFF) as u8;
108
109 header[4] = 0x00;
111 header[5] = 0x01;
112
113 header[6] = 0x40; header[7] = 0x00;
116
117 header[8] = 64;
119
120 header[9] = IPV6_IN_IPV4_PROTOCOL;
122
123 header[10] = 0x00;
125 header[11] = 0x00;
126
127 if let Some(src_ipv4) = self.local_ipv4 {
129 let src_octets = src_ipv4.octets();
130 header[12..16].copy_from_slice(&src_octets);
131 }
132
133 let dst_octets = dst_ipv4.octets();
135 header[16..20].copy_from_slice(&dst_octets);
136
137 let checksum = self.calculate_ipv4_checksum(&header);
139 header[10] = (checksum >> 8) as u8;
140 header[11] = (checksum & 0xFF) as u8;
141
142 header
143 }
144
145 fn calculate_ipv4_checksum(&self, header: &[u8]) -> u16 {
147 let mut sum: u32 = 0;
148
149 for i in (0..header.len()).step_by(2) {
151 if i + 1 < header.len() {
152 let word = ((header[i] as u32) << 8) + (header[i + 1] as u32);
153 sum = sum.wrapping_add(word);
154 }
155 }
156
157 while (sum >> 16) != 0 {
159 sum = (sum & 0xFFFF) + (sum >> 16);
160 }
161
162 (!sum) as u16
164 }
165
166 fn parse_ipv6_destination(&self, packet: &[u8]) -> Option<Ipv6Addr> {
168 if packet.len() < 40 { return None;
170 }
171
172 let mut addr_bytes = [0u8; 16];
174 addr_bytes.copy_from_slice(&packet[24..40]);
175 Some(Ipv6Addr::from(addr_bytes))
176 }
177
178 async fn update_send_metrics(&self, bytes: usize) {
180 let mut metrics = self.metrics.write().await;
181 metrics.bytes_sent += bytes as u64;
182 metrics.packets_sent += 1;
183 metrics.last_activity = Instant::now();
184 }
185
186 async fn update_receive_metrics(&self, bytes: usize) {
188 let mut metrics = self.metrics.write().await;
189 metrics.bytes_received += bytes as u64;
190 metrics.packets_received += 1;
191 metrics.last_activity = Instant::now();
192 }
193}
194
195#[async_trait]
196impl Tunnel for SixToFourTunnel {
197 fn protocol(&self) -> TunnelProtocol {
198 TunnelProtocol::SixToFour
199 }
200
201 fn config(&self) -> &TunnelConfig {
202 &self.config
203 }
204
205 async fn state(&self) -> TunnelState {
206 let state = self.state.read().await;
207 state.clone()
208 }
209
210 async fn metrics(&self) -> TunnelMetrics {
211 let metrics = self.metrics.read().await;
212 metrics.clone()
213 }
214
215 async fn connect(&mut self) -> Result<()> {
216 info!("Establishing 6to4 tunnel connection");
217
218 {
219 let mut state = self.state.write().await;
220 *state = TunnelState::Connecting;
221 }
222
223 let local_ipv4 = self.config.local_ipv4.ok_or_else(|| {
225 P2PError::Network("6to4 requires a local IPv4 address".to_string())
226 })?;
227
228 let local_ipv6 = Self::generate_ipv6_address(local_ipv4);
230
231 self.local_ipv4 = Some(local_ipv4);
233 self.local_ipv6 = Some(local_ipv6);
234 self.established_at = Some(Instant::now());
235
236 {
238 let mut state = self.state.write().await;
239 *state = TunnelState::Connected;
240 }
241
242 {
244 let mut metrics = self.metrics.write().await;
245 if let Some(established) = self.established_at {
246 metrics.establishment_time = established.elapsed();
247 }
248 }
249
250 info!("6to4 tunnel established: {} -> {}", local_ipv4, local_ipv6);
251 Ok(())
252 }
253
254 async fn disconnect(&mut self) -> Result<()> {
255 info!("Disconnecting 6to4 tunnel");
256
257 {
258 let mut state = self.state.write().await;
259 *state = TunnelState::Disconnecting;
260 }
261
262 self.local_ipv4 = None;
264 self.local_ipv6 = None;
265 self.established_at = None;
266
267 {
268 let mut state = self.state.write().await;
269 *state = TunnelState::Disconnected;
270 }
271
272 debug!("6to4 tunnel disconnected");
273 Ok(())
274 }
275
276 async fn is_active(&self) -> bool {
277 let state = self.state.read().await;
278 matches!(*state, TunnelState::Connected)
279 }
280
281 async fn encapsulate(&self, ipv6_packet: &[u8]) -> Result<Vec<u8>> {
282 if !self.is_active().await {
283 return Err(P2PError::Network("6to4 tunnel not active".to_string()).into());
284 }
285
286 let ipv6_dst = self.parse_ipv6_destination(ipv6_packet)
288 .ok_or_else(|| P2PError::Network("Invalid IPv6 packet".to_string()))?;
289
290 let ipv4_dst = Self::extract_ipv4_destination(&ipv6_dst)
292 .ok_or_else(|| P2PError::Network("Destination is not a 6to4 address".to_string()))?;
293
294 let ipv4_header = self.create_ipv4_header(ipv4_dst, ipv6_packet.len());
296
297 let mut encapsulated = Vec::with_capacity(ipv4_header.len() + ipv6_packet.len());
299 encapsulated.extend_from_slice(&ipv4_header);
300 encapsulated.extend_from_slice(ipv6_packet);
301
302 debug!("Encapsulated {} bytes for 6to4 transmission to {}",
303 encapsulated.len(), ipv4_dst);
304
305 Ok(encapsulated)
306 }
307
308 async fn decapsulate(&self, ipv4_packet: &[u8]) -> Result<Vec<u8>> {
309 if !self.is_active().await {
310 return Err(P2PError::Network("6to4 tunnel not active".to_string()).into());
311 }
312
313 if ipv4_packet.len() < 20 {
314 return Err(P2PError::Network("IPv4 packet too short".to_string()).into());
315 }
316
317 if ipv4_packet[9] != IPV6_IN_IPV4_PROTOCOL {
319 return Err(P2PError::Network("Not an IPv6-in-IPv4 packet".to_string()).into());
320 }
321
322 let header_len = ((ipv4_packet[0] & 0x0F) * 4) as usize;
324
325 if ipv4_packet.len() <= header_len {
326 return Err(P2PError::Network("IPv4 packet has no payload".to_string()).into());
327 }
328
329 let ipv6_payload = ipv4_packet[header_len..].to_vec();
331
332 debug!("Decapsulated {} bytes from 6to4 packet", ipv6_payload.len());
333
334 Ok(ipv6_payload)
335 }
336
337 async fn send(&mut self, packet: &[u8]) -> Result<()> {
338 let encapsulated = self.encapsulate(packet).await?;
339
340 debug!("Sending {} bytes via 6to4 tunnel", encapsulated.len());
343
344 tokio::time::sleep(Duration::from_millis(1)).await;
346
347 self.update_send_metrics(encapsulated.len()).await;
348 Ok(())
349 }
350
351 async fn receive(&mut self) -> Result<Vec<u8>> {
352 debug!("Receiving packet via 6to4 tunnel");
355
356 tokio::time::sleep(Duration::from_millis(2)).await;
358
359 let simulated_packet = vec![0u8; 64]; let decapsulated = self.decapsulate(&simulated_packet).await?;
363 self.update_receive_metrics(decapsulated.len()).await;
364
365 Ok(decapsulated)
366 }
367
368 async fn maintain(&mut self) -> Result<()> {
369 if !self.is_active().await {
370 return Ok(());
371 }
372
373 debug!("Performing 6to4 tunnel maintenance");
374
375 {
377 let mut metrics = self.metrics.write().await;
378 if let Some(established) = self.established_at {
379 metrics.establishment_time = established.elapsed();
380 }
381 }
382
383 Ok(())
390 }
391
392 async fn local_ipv6_addr(&self) -> Result<Ipv6Addr> {
393 self.local_ipv6.ok_or_else(|| {
394 P2PError::Network("6to4 tunnel not established".to_string()).into()
395 })
396 }
397
398 async fn local_ipv4_addr(&self) -> Result<Ipv4Addr> {
399 self.local_ipv4.ok_or_else(|| {
400 P2PError::Network("6to4 tunnel not established".to_string()).into()
401 })
402 }
403
404 async fn ping(&mut self, timeout: Duration) -> Result<Duration> {
405 if !self.is_active().await {
406 return Err(P2PError::Network("6to4 tunnel not active".to_string()).into());
407 }
408
409 let start = Instant::now();
410
411 debug!("Pinging via 6to4 tunnel with timeout {:?}", timeout);
413
414 let simulated_rtt = Duration::from_millis(20 + (rand::random::<u64>() % 30));
416 tokio::time::sleep(simulated_rtt).await;
417
418 let actual_rtt = start.elapsed();
419
420 {
422 let mut metrics = self.metrics.write().await;
423 metrics.rtt = Some(actual_rtt);
424 }
425
426 debug!("6to4 tunnel ping successful: RTT = {:?}", actual_rtt);
427 Ok(actual_rtt)
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434
435 #[test]
436 fn test_ipv6_address_generation() {
437 let ipv4 = Ipv4Addr::new(192, 168, 1, 1);
438 let ipv6 = SixToFourTunnel::generate_ipv6_address(ipv4);
439
440 assert_eq!(ipv6.segments()[0], 0x2002);
442 assert_eq!(ipv6.segments()[1], 0xc0a8); assert_eq!(ipv6.segments()[2], 0x0101); assert_eq!(ipv6.segments()[7], 0x0001); }
446
447 #[test]
448 fn test_ipv4_extraction() {
449 let ipv6 = Ipv6Addr::new(0x2002, 0xc0a8, 0x0101, 0, 0, 0, 0, 1);
450 let ipv4 = SixToFourTunnel::extract_ipv4_destination(&ipv6).unwrap();
451
452 assert_eq!(ipv4, Ipv4Addr::new(192, 168, 1, 1));
453 }
454
455 #[test]
456 fn test_non_6to4_address() {
457 let ipv6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
458 let result = SixToFourTunnel::extract_ipv4_destination(&ipv6);
459
460 assert!(result.is_none());
461 }
462
463 #[tokio::test]
464 async fn test_tunnel_creation() {
465 let config = TunnelConfig {
466 protocol: TunnelProtocol::SixToFour,
467 local_ipv4: Some(Ipv4Addr::new(203, 0, 113, 1)),
468 ..Default::default()
469 };
470
471 let tunnel = SixToFourTunnel::new(config).unwrap();
472 assert_eq!(tunnel.protocol(), TunnelProtocol::SixToFour);
473 assert_eq!(tunnel.state().await, TunnelState::Disconnected);
474 }
475
476 #[tokio::test]
477 async fn test_tunnel_connection() {
478 let config = TunnelConfig {
479 protocol: TunnelProtocol::SixToFour,
480 local_ipv4: Some(Ipv4Addr::new(203, 0, 113, 1)),
481 ..Default::default()
482 };
483
484 let mut tunnel = SixToFourTunnel::new(config).unwrap();
485
486 assert!(!tunnel.is_active().await);
487
488 tunnel.connect().await.unwrap();
489
490 assert!(tunnel.is_active().await);
491 assert_eq!(tunnel.state().await, TunnelState::Connected);
492
493 let ipv6_addr = tunnel.local_ipv6_addr().await.unwrap();
494 assert_eq!(ipv6_addr.segments()[0], 0x2002);
495 }
496}