ant_core/tunneling/
sixto4.rs

1//! 6to4 Tunneling Protocol Implementation
2//!
3//! This module implements the 6to4 automatic tunneling mechanism as defined in RFC 3056.
4//! 6to4 allows IPv6 packets to be transmitted over an IPv4 network without explicit tunnel setup.
5//!
6//! ## How 6to4 Works
7//!
8//! - Uses the IPv6 prefix 2002::/16 for automatic tunneling
9//! - Embeds the IPv4 address in the IPv6 address format: 2002:WWXX:YYZZ::/48
10//! - Automatically encapsulates IPv6 packets in IPv4 headers
11//! - Provides bidirectional IPv6 connectivity over IPv4 infrastructure
12
13use 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
21/// IPv6 prefix for 6to4 tunneling (2002::/16)
22const SIXTO4_PREFIX: u16 = 0x2002;
23
24/// Protocol number for IPv6-in-IPv4 encapsulation (41)
25const IPV6_IN_IPV4_PROTOCOL: u8 = 41;
26
27/// 6to4 tunnel implementation
28pub struct SixToFourTunnel {
29    /// Tunnel configuration
30    config: TunnelConfig,
31    /// Current tunnel state
32    state: RwLock<TunnelState>,
33    /// Performance metrics
34    metrics: RwLock<TunnelMetrics>,
35    /// Local IPv4 address used for tunneling
36    local_ipv4: Option<Ipv4Addr>,
37    /// Generated IPv6 address for this tunnel
38    local_ipv6: Option<Ipv6Addr>,
39    /// Connection establishment time
40    established_at: Option<Instant>,
41}
42
43impl SixToFourTunnel {
44    /// Create a new 6to4 tunnel with the given configuration
45    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    /// Generate a 6to4 IPv6 address from an IPv4 address
63    fn generate_ipv6_address(ipv4: Ipv4Addr) -> Ipv6Addr {
64        let octets = ipv4.octets();
65        Ipv6Addr::from([
66            (SIXTO4_PREFIX >> 8) as u8,  // 0x20
67            (SIXTO4_PREFIX & 0xFF) as u8, // 0x02
68            octets[0], octets[1],         // First two octets of IPv4
69            octets[2], octets[3],         // Last two octets of IPv4
70            0x00, 0x00,                   // Subnet ID (can be configured)
71            0x00, 0x00, 0x00, 0x00,       // Interface ID
72            0x00, 0x00, 0x00, 0x01,       // Interface ID (::1)
73        ])
74    }
75
76    /// Extract IPv4 destination from a 6to4 IPv6 address
77    fn extract_ipv4_destination(ipv6: &Ipv6Addr) -> Option<Ipv4Addr> {
78        let segments = ipv6.segments();
79        
80        // Check if this is a 6to4 address (prefix 2002::/16)
81        if segments[0] != SIXTO4_PREFIX {
82            return None;
83        }
84
85        // Extract IPv4 address from segments 1 and 2
86        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    /// Create an IPv4 header for encapsulation
95    fn create_ipv4_header(&self, dst_ipv4: Ipv4Addr, payload_len: usize) -> Vec<u8> {
96        let mut header = vec![0u8; 20]; // Standard IPv4 header size
97
98        // Version (4) and Header Length (5 * 4 = 20 bytes)
99        header[0] = 0x45;
100        
101        // Type of Service
102        header[1] = 0x00;
103        
104        // Total Length (header + payload)
105        let total_len = 20 + payload_len;
106        header[2] = (total_len >> 8) as u8;
107        header[3] = (total_len & 0xFF) as u8;
108        
109        // Identification (can be random)
110        header[4] = 0x00;
111        header[5] = 0x01;
112        
113        // Flags and Fragment Offset
114        header[6] = 0x40; // Don't Fragment bit set
115        header[7] = 0x00;
116        
117        // Time to Live
118        header[8] = 64;
119        
120        // Protocol (IPv6-in-IPv4)
121        header[9] = IPV6_IN_IPV4_PROTOCOL;
122        
123        // Header Checksum (will be calculated)
124        header[10] = 0x00;
125        header[11] = 0x00;
126        
127        // Source IPv4 Address
128        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        // Destination IPv4 Address
134        let dst_octets = dst_ipv4.octets();
135        header[16..20].copy_from_slice(&dst_octets);
136        
137        // Calculate checksum
138        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    /// Calculate IPv4 header checksum
146    fn calculate_ipv4_checksum(&self, header: &[u8]) -> u16 {
147        let mut sum: u32 = 0;
148        
149        // Sum all 16-bit words in the header
150        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        // Add carry bits
158        while (sum >> 16) != 0 {
159            sum = (sum & 0xFFFF) + (sum >> 16);
160        }
161        
162        // One's complement
163        (!sum) as u16
164    }
165
166    /// Parse IPv6 packet to extract destination address
167    fn parse_ipv6_destination(&self, packet: &[u8]) -> Option<Ipv6Addr> {
168        if packet.len() < 40 { // Minimum IPv6 header size
169            return None;
170        }
171
172        // IPv6 destination address is at bytes 24-39
173        let mut addr_bytes = [0u8; 16];
174        addr_bytes.copy_from_slice(&packet[24..40]);
175        Some(Ipv6Addr::from(addr_bytes))
176    }
177
178    /// Update metrics for sent data
179    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    /// Update metrics for received data
187    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        // For 6to4, we need a public IPv4 address
224        let local_ipv4 = self.config.local_ipv4.ok_or_else(|| {
225            P2PError::Network("6to4 requires a local IPv4 address".to_string())
226        })?;
227
228        // Generate the corresponding IPv6 address
229        let local_ipv6 = Self::generate_ipv6_address(local_ipv4);
230
231        // Update instance state
232        self.local_ipv4 = Some(local_ipv4);
233        self.local_ipv6 = Some(local_ipv6);
234        self.established_at = Some(Instant::now());
235
236        // Update tunnel state
237        {
238            let mut state = self.state.write().await;
239            *state = TunnelState::Connected;
240        }
241
242        // Update metrics
243        {
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        // Reset state
263        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        // Parse the IPv6 packet to get the destination
287        let ipv6_dst = self.parse_ipv6_destination(ipv6_packet)
288            .ok_or_else(|| P2PError::Network("Invalid IPv6 packet".to_string()))?;
289
290        // Extract IPv4 destination from 6to4 address
291        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        // Create IPv4 header
295        let ipv4_header = self.create_ipv4_header(ipv4_dst, ipv6_packet.len());
296
297        // Combine header and payload
298        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        // Check if this is an IPv6-in-IPv4 packet
318        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        // Extract header length (in 4-byte words)
323        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        // Extract the IPv6 payload
330        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        // In a real implementation, this would send the packet via raw sockets
341        // For now, we simulate the send operation
342        debug!("Sending {} bytes via 6to4 tunnel", encapsulated.len());
343        
344        // Simulate network transmission delay
345        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        // In a real implementation, this would receive packets from raw sockets
353        // For now, we simulate receiving a packet
354        debug!("Receiving packet via 6to4 tunnel");
355        
356        // Simulate network reception delay
357        tokio::time::sleep(Duration::from_millis(2)).await;
358        
359        // Simulate a received IPv4 packet containing IPv6 data
360        let simulated_packet = vec![0u8; 64]; // Placeholder
361        
362        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        // Update metrics
376        {
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        // In a real implementation, this might:
384        // - Check tunnel connectivity
385        // - Refresh route table entries
386        // - Update firewall rules
387        // - Monitor for IPv4 address changes
388
389        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        // Simulate a ping operation
412        debug!("Pinging via 6to4 tunnel with timeout {:?}", timeout);
413        
414        // Simulate network round trip time
415        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        // Update metrics with RTT
421        {
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        // Should be 2002:c0a8:0101::1
441        assert_eq!(ipv6.segments()[0], 0x2002);
442        assert_eq!(ipv6.segments()[1], 0xc0a8);  // 192.168
443        assert_eq!(ipv6.segments()[2], 0x0101);  // 1.1
444        assert_eq!(ipv6.segments()[7], 0x0001);  // ::1
445    }
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}