ant_core/
tunneling.rs

1//! IPv6/IPv4 Tunneling Implementation
2//!
3//! This module provides comprehensive tunneling solutions for enabling IPv6 connectivity
4//! over IPv4 networks. It implements multiple tunneling protocols to ensure universal
5//! connectivity for the P2P Foundation networking stack.
6//!
7//! ## Supported Protocols
8//!
9//! - **6to4**: Automatic tunneling of IPv6 traffic over IPv4 networks
10//! - **Teredo**: NAT traversal for IPv6 connectivity through NAT devices
11//! - **6in4**: Configured tunneling for IPv6 over IPv4 with explicit endpoints
12//! - **DS-Lite**: ISP-provided dual-stack lite tunneling
13//! - **ISATAP**: Enterprise network tunneling for corporate environments
14//! - **MAP-E**: ISP IPv4 sharing via encapsulation with mapping rules
15//! - **MAP-T**: ISP IPv4/IPv6 translation with mapping rules
16//!
17//! ## Architecture
18//!
19//! The tunneling system uses a trait-based architecture that allows for:
20//! - Protocol-agnostic tunnel management
21//! - Automatic protocol selection based on network conditions
22//! - Seamless integration with the transport layer
23//! - Performance monitoring and failover capabilities
24
25use crate::{P2PError, Result};
26use async_trait::async_trait;
27use serde::{Deserialize, Serialize};
28use std::net::{Ipv4Addr, Ipv6Addr};
29use std::time::{Duration, Instant};
30use tokio::sync::RwLock;
31use tracing::{debug, info, warn};
32
33/// Tunneling protocol types supported by the P2P Foundation
34#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
35pub enum TunnelProtocol {
36    /// 6to4 automatic tunneling protocol (RFC 3056)
37    SixToFour,
38    /// Teredo tunneling protocol for NAT traversal (RFC 4380)
39    Teredo,
40    /// 6in4 static tunneling protocol (RFC 4213)
41    SixInFour,
42    /// DS-Lite (Dual-Stack Lite) ISP-provided tunneling (RFC 6333)
43    DsLite,
44    /// ISATAP (Intra-Site Automatic Tunnel Addressing Protocol) for enterprise networks (RFC 5214)
45    Isatap,
46    /// MAP-E (Mapping of Address and Port - Encapsulation) for ISP IPv4 sharing (RFC 7597)
47    MapE,
48    /// MAP-T (Mapping of Address and Port - Translation) for ISP IPv4/IPv6 translation (RFC 7599)
49    MapT,
50}
51
52/// Configuration for tunneling protocols
53#[derive(Debug, Clone)]
54pub struct TunnelConfig {
55    /// Protocol to use for tunneling
56    pub protocol: TunnelProtocol,
57    /// Local IPv4 address for tunnel endpoint
58    pub local_ipv4: Option<Ipv4Addr>,
59    /// Remote IPv4 address for tunnel endpoint (6in4 only)
60    pub remote_ipv4: Option<Ipv4Addr>,
61    /// IPv6 prefix to use for the tunnel
62    pub ipv6_prefix: Option<Ipv6Addr>,
63    /// DS-Lite AFTR (Address Family Transition Router) IPv6 address
64    pub aftr_ipv6: Option<Ipv6Addr>,
65    /// DS-Lite AFTR domain name for DNS resolution
66    pub aftr_name: Option<String>,
67    /// Maximum transmission unit for tunnel packets
68    pub mtu: u16,
69    /// Keepalive interval for maintaining tunnel state
70    pub keepalive_interval: Duration,
71    /// Maximum time to wait for tunnel establishment
72    pub establishment_timeout: Duration,
73}
74
75/// Statistics and performance metrics for tunnel connections
76#[derive(Debug, Clone)]
77pub struct TunnelMetrics {
78    /// Total bytes sent through the tunnel
79    pub bytes_sent: u64,
80    /// Total bytes received through the tunnel
81    pub bytes_received: u64,
82    /// Number of packets successfully transmitted
83    pub packets_sent: u64,
84    /// Number of packets successfully received
85    pub packets_received: u64,
86    /// Number of packets dropped due to errors
87    pub packets_dropped: u64,
88    /// Current round-trip time
89    pub rtt: Option<Duration>,
90    /// Tunnel establishment time
91    pub establishment_time: Duration,
92    /// Last activity timestamp
93    pub last_activity: Instant,
94}
95
96/// Current state of a tunnel connection
97#[derive(Debug, Clone, PartialEq)]
98pub enum TunnelState {
99    /// Tunnel is not yet established
100    Disconnected,
101    /// Tunnel is in the process of being established
102    Connecting,
103    /// Tunnel is established and ready for use
104    Connected,
105    /// Tunnel has failed and cannot be used
106    Failed(String),
107    /// Tunnel is being torn down
108    Disconnecting,
109}
110
111/// Core trait for all tunneling protocol implementations
112#[async_trait]
113pub trait Tunnel: Send + Sync {
114    /// Get the protocol type for this tunnel
115    fn protocol(&self) -> TunnelProtocol;
116    
117    /// Get the current configuration
118    fn config(&self) -> &TunnelConfig;
119    
120    /// Get the current tunnel state
121    async fn state(&self) -> TunnelState;
122    
123    /// Get tunnel performance metrics
124    async fn metrics(&self) -> TunnelMetrics;
125    
126    /// Establish the tunnel connection
127    async fn connect(&mut self) -> Result<()>;
128    
129    /// Close the tunnel connection
130    async fn disconnect(&mut self) -> Result<()>;
131    
132    /// Check if the tunnel is currently active and usable
133    async fn is_active(&self) -> bool;
134    
135    /// Encapsulate IPv6 packet for transmission over IPv4
136    async fn encapsulate(&self, ipv6_packet: &[u8]) -> Result<Vec<u8>>;
137    
138    /// Decapsulate IPv4 packet to extract IPv6 content
139    async fn decapsulate(&self, ipv4_packet: &[u8]) -> Result<Vec<u8>>;
140    
141    /// Send a packet through the tunnel
142    async fn send(&mut self, packet: &[u8]) -> Result<()>;
143    
144    /// Receive a packet from the tunnel
145    async fn receive(&mut self) -> Result<Vec<u8>>;
146    
147    /// Perform periodic maintenance (keepalive, metrics update, etc.)
148    async fn maintain(&mut self) -> Result<()>;
149    
150    /// Get the IPv6 address assigned to this tunnel
151    async fn local_ipv6_addr(&self) -> Result<Ipv6Addr>;
152    
153    /// Get the IPv4 endpoint address for this tunnel
154    async fn local_ipv4_addr(&self) -> Result<Ipv4Addr>;
155    
156    /// Test tunnel connectivity with a ping
157    async fn ping(&mut self, timeout: Duration) -> Result<Duration>;
158}
159
160/// Manager for multiple tunnel connections with automatic failover
161pub struct TunnelManager {
162    /// Available tunnel implementations
163    tunnels: RwLock<Vec<Box<dyn Tunnel>>>,
164    /// Currently active tunnel
165    active_tunnel: RwLock<Option<usize>>,
166    /// Configuration for tunnel selection
167    config: TunnelManagerConfig,
168}
169
170/// Configuration for the tunnel manager
171#[derive(Debug, Clone)]
172pub struct TunnelManagerConfig {
173    /// Preferred protocol order for tunnel selection
174    pub protocol_preference: Vec<TunnelProtocol>,
175    /// How often to test tunnel connectivity
176    pub health_check_interval: Duration,
177    /// Timeout for tunnel health checks
178    pub health_check_timeout: Duration,
179    /// Whether to automatically failover to backup tunnels
180    pub auto_failover: bool,
181    /// Maximum number of concurrent tunnel attempts
182    pub max_concurrent_attempts: usize,
183}
184
185/// Result of tunnel auto-selection process
186#[derive(Debug, Clone)]
187pub struct TunnelSelection {
188    /// Selected protocol
189    pub protocol: TunnelProtocol,
190    /// Reason for selection
191    pub reason: String,
192    /// Time taken for selection process
193    pub selection_time: Duration,
194    /// Whether this was a fallback choice
195    pub is_fallback: bool,
196}
197
198/// Capabilities of the current network environment for tunneling
199#[derive(Debug, Clone)]
200pub struct NetworkCapabilities {
201    /// Whether IPv6 is natively available
202    pub has_ipv6: bool,
203    /// Whether IPv4 is available
204    pub has_ipv4: bool,
205    /// Whether the host is behind NAT
206    pub behind_nat: bool,
207    /// Detected public IPv4 address
208    pub public_ipv4: Option<Ipv4Addr>,
209    /// Available IPv6 addresses
210    pub ipv6_addresses: Vec<Ipv6Addr>,
211    /// Whether UPnP is available for port mapping
212    pub has_upnp: bool,
213    /// MTU of the primary network interface
214    pub interface_mtu: u16,
215}
216
217/// Quality metrics for tunnel monitoring and selection
218#[derive(Debug, Clone)]
219pub struct TunnelQualityMetric {
220    /// Protocol type
221    pub protocol: TunnelProtocol,
222    /// Current tunnel state
223    pub state: TunnelState,
224    /// Round-trip time
225    pub rtt: Option<Duration>,
226    /// Packet loss percentage (0-100)
227    pub packet_loss: Option<f32>,
228    /// Throughput in bytes per second
229    pub throughput: Option<f64>,
230    /// Overall reliability score (0.0-1.0)
231    pub reliability_score: f32,
232    /// Last activity timestamp
233    pub last_activity: Instant,
234}
235
236impl Default for TunnelConfig {
237    fn default() -> Self {
238        Self {
239            protocol: TunnelProtocol::SixToFour,
240            local_ipv4: None,
241            remote_ipv4: None,
242            ipv6_prefix: None,
243            aftr_ipv6: None,
244            aftr_name: None,
245            mtu: 1280, // Minimum IPv6 MTU
246            keepalive_interval: Duration::from_secs(30),
247            establishment_timeout: Duration::from_secs(10),
248        }
249    }
250}
251
252impl Default for TunnelManagerConfig {
253    fn default() -> Self {
254        Self {
255            protocol_preference: vec![
256                TunnelProtocol::DsLite,     // ISP-provided, most reliable
257                TunnelProtocol::Isatap,     // Enterprise networks, excellent for corporate
258                TunnelProtocol::SixToFour,  // Automatic, good for public IPv4
259                TunnelProtocol::Teredo,     // NAT traversal capable
260                TunnelProtocol::SixInFour,  // Manual configuration fallback
261            ],
262            health_check_interval: Duration::from_secs(60),
263            health_check_timeout: Duration::from_secs(5),
264            auto_failover: true,
265            max_concurrent_attempts: 3,
266        }
267    }
268}
269
270impl Default for TunnelMetrics {
271    fn default() -> Self {
272        Self {
273            bytes_sent: 0,
274            bytes_received: 0,
275            packets_sent: 0,
276            packets_received: 0,
277            packets_dropped: 0,
278            rtt: None,
279            establishment_time: Duration::ZERO,
280            last_activity: Instant::now(),
281        }
282    }
283}
284
285impl TunnelManager {
286    /// Create a new tunnel manager with default configuration
287    pub fn new() -> Self {
288        Self::with_config(TunnelManagerConfig::default())
289    }
290    
291    /// Create a new tunnel manager with custom configuration
292    pub fn with_config(config: TunnelManagerConfig) -> Self {
293        Self {
294            tunnels: RwLock::new(Vec::new()),
295            active_tunnel: RwLock::new(None),
296            config,
297        }
298    }
299    
300    /// Add a tunnel implementation to the manager
301    pub async fn add_tunnel(&self, tunnel: Box<dyn Tunnel>) {
302        let mut tunnels = self.tunnels.write().await;
303        tunnels.push(tunnel);
304    }
305    
306    /// Get the currently active tunnel
307    pub async fn active_tunnel(&self) -> Option<TunnelProtocol> {
308        let active_idx = self.active_tunnel.read().await;
309        if let Some(idx) = *active_idx {
310            let tunnels = self.tunnels.read().await;
311            if let Some(tunnel) = tunnels.get(idx) {
312                return Some(tunnel.protocol());
313            }
314        }
315        None
316    }
317    
318    /// Select the best available tunnel based on network capabilities
319    pub async fn select_tunnel(&self, capabilities: &NetworkCapabilities) -> Option<TunnelSelection> {
320        let start_time = Instant::now();
321        
322        // If IPv6 is natively available, no tunneling needed
323        if capabilities.has_ipv6 && !capabilities.ipv6_addresses.is_empty() {
324            info!("Native IPv6 connectivity detected, no tunneling required");
325            return None;
326        }
327        
328        info!("Selecting optimal tunnel protocol based on network conditions");
329        debug!("Network capabilities: {:?}", capabilities);
330        
331        // Perform intelligent protocol selection
332        let selection = self.intelligent_protocol_selection(capabilities).await;
333        
334        if let Some(ref selection) = selection {
335            info!("Selected {} tunnel: {}", 
336                  format!("{:?}", selection.protocol), selection.reason);
337        } else {
338            warn!("No suitable tunnel protocol found for current network conditions");
339        }
340        
341        selection.map(|mut sel| {
342            sel.selection_time = start_time.elapsed();
343            sel
344        })
345    }
346    
347    /// Intelligent protocol selection with scoring and fallback logic
348    async fn intelligent_protocol_selection(&self, capabilities: &NetworkCapabilities) -> Option<TunnelSelection> {
349        let tunnels = self.tunnels.read().await;
350        
351        // Score each available protocol
352        let mut scored_protocols: Vec<(TunnelProtocol, f32, String)> = Vec::new();
353        
354        for tunnel in tunnels.iter() {
355            let protocol = tunnel.protocol();
356            let (score, reason) = self.score_protocol(&protocol, capabilities).await;
357            
358            debug!("Protocol {:?} scored {:.2}: {}", protocol, score, reason);
359            
360            if score > 0.0 {
361                scored_protocols.push((protocol, score, reason));
362            }
363        }
364        
365        // Sort by score (highest first)
366        scored_protocols.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
367        
368        // Try protocols in order of score, with validation
369        for (protocol, score, reason) in scored_protocols {
370            if let Some(tunnel_idx) = self.find_tunnel_index(&protocol, &tunnels).await {
371                // Test protocol viability if configured to do so
372                if self.config.max_concurrent_attempts > 0 {
373                    if let Ok(_) = self.test_protocol_viability(&protocol, tunnel_idx).await {
374                        let mut active = self.active_tunnel.write().await;
375                        *active = Some(tunnel_idx);
376                        
377                        return Some(TunnelSelection {
378                            protocol,
379                            reason: format!("{} (score: {:.2})", reason, score),
380                            selection_time: Duration::ZERO, // Will be set by caller
381                            is_fallback: score < 0.7, // Consider scores below 0.7 as fallback
382                        });
383                    } else {
384                        warn!("Protocol {:?} failed viability test despite good score", protocol);
385                    }
386                } else {
387                    // Skip viability testing, use based on score alone
388                    let mut active = self.active_tunnel.write().await;
389                    *active = Some(tunnel_idx);
390                    
391                    return Some(TunnelSelection {
392                        protocol,
393                        reason: format!("{} (score: {:.2})", reason, score),
394                        selection_time: Duration::ZERO,
395                        is_fallback: score < 0.7,
396                    });
397                }
398            }
399        }
400        
401        None
402    }
403    
404    /// Score a protocol based on network conditions (0.0 = unsuitable, 1.0 = perfect)
405    async fn score_protocol(&self, protocol: &TunnelProtocol, capabilities: &NetworkCapabilities) -> (f32, String) {
406        let mut score = 0.0;
407        let mut reasons = Vec::new();
408        
409        match protocol {
410            TunnelProtocol::SixToFour => {
411                if !capabilities.has_ipv4 {
412                    return (0.0, "No IPv4 connectivity".to_string());
413                }
414                
415                if capabilities.behind_nat {
416                    return (0.0, "6to4 requires public IPv4 address, behind NAT".to_string());
417                }
418                
419                if capabilities.public_ipv4.is_some() {
420                    score += 0.8; // High score for public IPv4
421                    reasons.push("has public IPv4");
422                } else {
423                    return (0.0, "6to4 requires public IPv4 address".to_string());
424                }
425                
426                // Bonus for higher MTU
427                if capabilities.interface_mtu >= 1500 {
428                    score += 0.2;
429                    reasons.push("good MTU");
430                }
431                
432                (score, format!("6to4 suitable: {}", reasons.join(", ")))
433            }
434            
435            TunnelProtocol::Teredo => {
436                if !capabilities.has_ipv4 {
437                    return (0.0, "No IPv4 connectivity".to_string());
438                }
439                
440                score += 0.6; // Base score for Teredo
441                reasons.push("works with any IPv4");
442                
443                if capabilities.behind_nat {
444                    score += 0.3; // Teredo is designed for NAT traversal
445                    reasons.push("excellent NAT traversal");
446                } else {
447                    score += 0.1; // Still works without NAT
448                }
449                
450                if capabilities.has_upnp {
451                    score += 0.1; // UPnP can help with port mapping
452                    reasons.push("UPnP available");
453                }
454                
455                (score, format!("Teredo suitable: {}", reasons.join(", ")))
456            }
457            
458            TunnelProtocol::SixInFour => {
459                if !capabilities.has_ipv4 {
460                    return (0.0, "No IPv4 connectivity".to_string());
461                }
462                
463                // 6in4 requires explicit configuration, so it's a fallback
464                score += 0.4;
465                reasons.push("requires manual configuration");
466                
467                if !capabilities.behind_nat && capabilities.public_ipv4.is_some() {
468                    score += 0.3; // Better with public IP
469                    reasons.push("has public IPv4");
470                }
471                
472                // Higher MTU is beneficial for 6in4
473                if capabilities.interface_mtu >= 1500 {
474                    score += 0.2;
475                    reasons.push("good MTU");
476                }
477                
478                (score, format!("6in4 suitable: {}", reasons.join(", ")))
479            }
480            
481            TunnelProtocol::DsLite => {
482                if !capabilities.has_ipv6 {
483                    return (0.0, "DS-Lite requires IPv6 connectivity".to_string());
484                }
485                
486                // DS-Lite gets high score as it's ISP-provided and reliable
487                score += 0.9;
488                reasons.push("ISP-provided infrastructure");
489                
490                // DS-Lite works best with native IPv6
491                if capabilities.has_ipv6 && !capabilities.ipv6_addresses.is_empty() {
492                    score += 0.1;
493                    reasons.push("native IPv6 available");
494                }
495                
496                // DS-Lite handles NAT automatically at the AFTR
497                if capabilities.behind_nat {
498                    // No penalty for being behind NAT - AFTR handles this
499                    reasons.push("AFTR provides centralized NAT");
500                } else {
501                    score += 0.05; // Small bonus for not needing NAT
502                    reasons.push("direct connectivity");
503                }
504                
505                // Higher MTU is beneficial (less fragmentation)
506                if capabilities.interface_mtu >= 1520 {
507                    score += 0.05;
508                    reasons.push("supports optimal MTU");
509                }
510                
511                (score, format!("DS-Lite suitable: {}", reasons.join(", ")))
512            }
513            
514            TunnelProtocol::Isatap => {
515                if !capabilities.has_ipv4 {
516                    return (0.0, "ISATAP requires IPv4 connectivity".to_string());
517                }
518                
519                // ISATAP is excellent for enterprise environments
520                score += 0.8;
521                reasons.push("enterprise-grade tunneling");
522                
523                // ISATAP works well in corporate networks with or without NAT
524                if capabilities.behind_nat {
525                    score += 0.1; // Works fine behind corporate NAT
526                    reasons.push("corporate NAT compatible");
527                } else {
528                    score += 0.15; // Even better with direct connectivity
529                    reasons.push("direct enterprise connectivity");
530                }
531                
532                // ISATAP benefits from good MTU for enterprise traffic
533                if capabilities.interface_mtu >= 1500 {
534                    score += 0.1;
535                    reasons.push("enterprise MTU");
536                }
537                
538                // Check for enterprise network indicators (private IP ranges)
539                if let Some(ipv4) = capabilities.public_ipv4 {
540                    if ipv4.is_private() {
541                        score += 0.2; // Bonus for private networks (enterprise indicator)
542                        reasons.push("private network detected");
543                    }
544                }
545                
546                (score, format!("ISATAP suitable: {}", reasons.join(", ")))
547            }
548            
549            TunnelProtocol::MapE => {
550                if !capabilities.has_ipv4 {
551                    return (0.0, "MAP-E requires IPv4 connectivity".to_string());
552                }
553                
554                // MAP-E is excellent for ISP deployment scenarios
555                score += 0.9;
556                reasons.push("ISP-grade address sharing");
557                
558                // MAP-E works well with any IPv4 connectivity
559                if capabilities.public_ipv4.is_some() {
560                    score += 0.1;
561                    reasons.push("public IPv4 available");
562                }
563                
564                // MAP-E is stateless and highly scalable
565                if capabilities.interface_mtu >= 1460 {
566                    reasons.push("sufficient MTU for encapsulation");
567                } else {
568                    score -= 0.1; // Slight penalty for low MTU
569                    reasons.push("low MTU may affect performance");
570                }
571                
572                (score, format!("MAP-E suitable: {}", reasons.join(", ")))
573            }
574            
575            TunnelProtocol::MapT => {
576                if !capabilities.has_ipv4 {
577                    return (0.0, "MAP-T requires IPv4 connectivity".to_string());
578                }
579                
580                // MAP-T is excellent for pure IPv6 networks with IPv4 translation
581                score += 0.85;
582                reasons.push("stateless IPv4/IPv6 translation");
583                
584                // MAP-T works well with any IPv4 connectivity
585                if capabilities.public_ipv4.is_some() {
586                    score += 0.1;
587                    reasons.push("public IPv4 available");
588                }
589                
590                // MAP-T has no encapsulation overhead
591                score += 0.05;
592                reasons.push("no encapsulation overhead");
593                
594                (score, format!("MAP-T suitable: {}", reasons.join(", ")))
595            }
596        }
597    }
598    
599    /// Find the index of a tunnel with the specified protocol
600    async fn find_tunnel_index(&self, protocol: &TunnelProtocol, tunnels: &[Box<dyn Tunnel>]) -> Option<usize> {
601        for (idx, tunnel) in tunnels.iter().enumerate() {
602            if tunnel.protocol() == *protocol {
603                return Some(idx);
604            }
605        }
606        None
607    }
608    
609    /// Test if a protocol is actually viable by attempting a quick connection test
610    async fn test_protocol_viability(&self, _protocol: &TunnelProtocol, tunnel_idx: usize) -> Result<()> {
611        let tunnels = self.tunnels.read().await;
612        
613        if let Some(tunnel) = tunnels.get(tunnel_idx) {
614            // For now, just check if the tunnel reports as suitable for its state
615            match tunnel.state().await {
616                TunnelState::Connected => Ok(()),
617                TunnelState::Failed(_) => Err(P2PError::Network("Tunnel in failed state".to_string())),
618                _ => {
619                    // Could perform more sophisticated testing here:
620                    // - Try to establish a test connection
621                    // - Send a ping packet
622                    // - Verify routing tables
623                    Ok(()) // Assume viable for now
624                }
625            }
626        } else {
627            Err(P2PError::Network("Tunnel not found".to_string()))
628        }
629    }
630    
631    /// Check if a protocol is suitable for the current network conditions
632    #[allow(dead_code)]
633    fn is_protocol_suitable(&self, protocol: &TunnelProtocol, capabilities: &NetworkCapabilities) -> bool {
634        match protocol {
635            TunnelProtocol::SixToFour => {
636                // 6to4 requires a public IPv4 address
637                capabilities.has_ipv4 && capabilities.public_ipv4.is_some() && !capabilities.behind_nat
638            }
639            TunnelProtocol::Teredo => {
640                // Teredo works behind NAT and with private IPv4
641                capabilities.has_ipv4
642            }
643            TunnelProtocol::SixInFour => {
644                // 6in4 requires explicit configuration
645                capabilities.has_ipv4
646            }
647            TunnelProtocol::DsLite => {
648                // DS-Lite requires IPv6 connectivity (native or tunneled)
649                capabilities.has_ipv6
650            }
651            TunnelProtocol::Isatap => {
652                // ISATAP works with any IPv4 connectivity, ideal for enterprise networks
653                capabilities.has_ipv4
654            }
655            TunnelProtocol::MapE => {
656                // MAP-E requires IPv4 connectivity and is used by ISPs for address sharing
657                capabilities.has_ipv4
658            }
659            TunnelProtocol::MapT => {
660                // MAP-T requires IPv4 connectivity and provides stateless translation
661                capabilities.has_ipv4
662            }
663        }
664    }
665    
666    /// Connect using the currently selected tunnel
667    pub async fn connect(&self) -> Result<()> {
668        let active_idx = {
669            let active = self.active_tunnel.read().await;
670            *active
671        };
672        
673        if let Some(idx) = active_idx {
674            let mut tunnels = self.tunnels.write().await;
675            if let Some(tunnel) = tunnels.get_mut(idx) {
676                tunnel.connect().await?;
677                info!("Successfully connected using {} tunnel", 
678                      format!("{:?}", tunnel.protocol()));
679                return Ok(());
680            }
681        }
682        
683        Err(P2PError::Network("No active tunnel selected".to_string()).into())
684    }
685    
686    /// Disconnect the currently active tunnel
687    pub async fn disconnect(&self) -> Result<()> {
688        let active_idx = {
689            let active = self.active_tunnel.read().await;
690            *active
691        };
692        
693        if let Some(idx) = active_idx {
694            let mut tunnels = self.tunnels.write().await;
695            if let Some(tunnel) = tunnels.get_mut(idx) {
696                tunnel.disconnect().await?;
697                debug!("Disconnected {} tunnel", format!("{:?}", tunnel.protocol()));
698            }
699        }
700        
701        Ok(())
702    }
703    
704    /// Send a packet through the active tunnel
705    pub async fn send(&self, packet: &[u8]) -> Result<()> {
706        let active_idx = {
707            let active = self.active_tunnel.read().await;
708            *active
709        };
710        
711        if let Some(idx) = active_idx {
712            let mut tunnels = self.tunnels.write().await;
713            if let Some(tunnel) = tunnels.get_mut(idx) {
714                return tunnel.send(packet).await;
715            }
716        }
717        
718        Err(P2PError::Network("No active tunnel for sending".to_string()).into())
719    }
720    
721    /// Receive a packet from the active tunnel
722    pub async fn receive(&self) -> Result<Vec<u8>> {
723        let active_idx = {
724            let active = self.active_tunnel.read().await;
725            *active
726        };
727        
728        if let Some(idx) = active_idx {
729            let mut tunnels = self.tunnels.write().await;
730            if let Some(tunnel) = tunnels.get_mut(idx) {
731                return tunnel.receive().await;
732            }
733        }
734        
735        Err(P2PError::Network("No active tunnel for receiving".to_string()).into())
736    }
737    
738    /// Get metrics for the currently active tunnel
739    pub async fn metrics(&self) -> Option<TunnelMetrics> {
740        let active_idx = {
741            let active = self.active_tunnel.read().await;
742            *active
743        };
744        
745        if let Some(idx) = active_idx {
746            let tunnels = self.tunnels.read().await;
747            if let Some(tunnel) = tunnels.get(idx) {
748                return Some(tunnel.metrics().await);
749            }
750        }
751        
752        None
753    }
754    
755    /// Perform health checks on all tunnels
756    pub async fn health_check(&self) -> Result<()> {
757        let mut tunnels = self.tunnels.write().await;
758        let current_active = {
759            let active = self.active_tunnel.read().await;
760            *active
761        };
762        
763        let mut active_tunnel_failed = false;
764        
765        for (idx, tunnel) in tunnels.iter_mut().enumerate() {
766            match tunnel.ping(self.config.health_check_timeout).await {
767                Ok(rtt) => {
768                    debug!("Health check passed for {} tunnel (RTT: {:?})", 
769                           format!("{:?}", tunnel.protocol()), rtt);
770                }
771                Err(e) => {
772                    warn!("Health check failed for {} tunnel: {}", 
773                          format!("{:?}", tunnel.protocol()), e);
774                    
775                    // Check if this is the currently active tunnel
776                    if current_active == Some(idx) {
777                        active_tunnel_failed = true;
778                    }
779                    
780                    if self.config.auto_failover {
781                        // Try to reconnect
782                        if let Err(reconnect_err) = tunnel.connect().await {
783                            warn!("Failed to reconnect {} tunnel: {}", 
784                                  format!("{:?}", tunnel.protocol()), reconnect_err);
785                        }
786                    }
787                }
788            }
789        }
790        
791        // If active tunnel failed and auto-failover is enabled, find replacement
792        if active_tunnel_failed && self.config.auto_failover {
793            drop(tunnels); // Release write lock before calling failover
794            self.perform_automatic_failover().await?;
795        }
796        
797        Ok(())
798    }
799    
800    /// Perform automatic failover to the next best available tunnel
801    pub async fn perform_automatic_failover(&self) -> Result<()> {
802        info!("Performing automatic tunnel failover...");
803        
804        // Detect current network capabilities
805        let capabilities = detect_network_capabilities().await?;
806        
807        // Select new tunnel, excluding the currently failed one
808        if let Some(selection) = self.select_tunnel(&capabilities).await {
809            info!("Failover successful: switched to {} tunnel ({})", 
810                  format!("{:?}", selection.protocol), selection.reason);
811            
812            // Connect to the new tunnel
813            self.connect().await?;
814            
815            Ok(())
816        } else {
817            let error_msg = "No suitable backup tunnel available for failover";
818            warn!("{}", error_msg);
819            Err(P2PError::Network(error_msg.to_string()))
820        }
821    }
822    
823    /// Get tunnel quality metrics for monitoring and selection
824    pub async fn get_tunnel_quality_metrics(&self) -> Vec<TunnelQualityMetric> {
825        let tunnels = self.tunnels.read().await;
826        let mut metrics = Vec::new();
827        
828        for tunnel in tunnels.iter() {
829            let tunnel_metrics = tunnel.metrics().await;
830            let state = tunnel.state().await;
831            
832            let quality = TunnelQualityMetric {
833                protocol: tunnel.protocol(),
834                state: state.clone(),
835                rtt: tunnel_metrics.rtt,
836                packet_loss: if tunnel_metrics.packets_sent > 0 {
837                    Some((tunnel_metrics.packets_dropped as f32 / tunnel_metrics.packets_sent as f32) * 100.0)
838                } else {
839                    None
840                },
841                throughput: calculate_throughput(&tunnel_metrics),
842                reliability_score: calculate_reliability_score(&state, &tunnel_metrics),
843                last_activity: tunnel_metrics.last_activity,
844            };
845            
846            metrics.push(quality);
847        }
848        
849        metrics
850    }
851    
852    /// Start automatic monitoring task for continuous health checks
853    pub async fn start_monitoring(&self) -> Result<()> {
854        if self.config.health_check_interval.is_zero() {
855            debug!("Health check monitoring disabled (interval is zero)");
856            return Ok(());
857        }
858        
859        info!("Starting tunnel monitoring with interval {:?}", self.config.health_check_interval);
860        
861        // In a real implementation, this would spawn a background task
862        // For now, we just log that monitoring would start
863        debug!("Tunnel monitoring task would be spawned here");
864        
865        Ok(())
866    }
867    
868    /// Perform maintenance on all tunnels
869    pub async fn maintain(&self) -> Result<()> {
870        let mut tunnels = self.tunnels.write().await;
871        
872        for tunnel in tunnels.iter_mut() {
873            if let Err(e) = tunnel.maintain().await {
874                warn!("Maintenance failed for {} tunnel: {}", 
875                      format!("{:?}", tunnel.protocol()), e);
876            }
877        }
878        
879        Ok(())
880    }
881}
882
883impl Default for TunnelManager {
884    fn default() -> Self {
885        Self::new()
886    }
887}
888
889/// Detect current network capabilities for tunnel selection
890pub async fn detect_network_capabilities() -> Result<NetworkCapabilities> {
891    debug!("Detecting network capabilities...");
892    
893    let mut capabilities = NetworkCapabilities {
894        has_ipv6: false,
895        has_ipv4: false,
896        behind_nat: false,
897        public_ipv4: None,
898        ipv6_addresses: Vec::new(),
899        has_upnp: false,
900        interface_mtu: 1500,
901    };
902    
903    // Detect IPv4 connectivity
904    capabilities.has_ipv4 = detect_ipv4_connectivity().await;
905    debug!("IPv4 connectivity: {}", capabilities.has_ipv4);
906    
907    // Detect IPv6 connectivity
908    let ipv6_result = detect_ipv6_connectivity().await;
909    capabilities.has_ipv6 = !ipv6_result.is_empty();
910    capabilities.ipv6_addresses = ipv6_result;
911    debug!("IPv6 connectivity: {}, addresses: {:?}", capabilities.has_ipv6, capabilities.ipv6_addresses);
912    
913    // Detect NAT presence and public IPv4
914    if capabilities.has_ipv4 {
915        let nat_detection = detect_nat_and_public_ip().await;
916        capabilities.behind_nat = nat_detection.0;
917        capabilities.public_ipv4 = nat_detection.1;
918        debug!("NAT detection: behind_nat={}, public_ipv4={:?}", capabilities.behind_nat, capabilities.public_ipv4);
919    }
920    
921    // Test UPnP availability
922    capabilities.has_upnp = test_upnp_availability().await;
923    debug!("UPnP availability: {}", capabilities.has_upnp);
924    
925    // Detect interface MTU
926    capabilities.interface_mtu = detect_interface_mtu().await;
927    debug!("Interface MTU: {}", capabilities.interface_mtu);
928    
929    info!("Network capabilities detected: IPv4={}, IPv6={}, NAT={}, UPnP={}, MTU={}", 
930          capabilities.has_ipv4, capabilities.has_ipv6, capabilities.behind_nat,
931          capabilities.has_upnp, capabilities.interface_mtu);
932    
933    Ok(capabilities)
934}
935
936/// Detect IPv4 connectivity by testing connection to known servers
937async fn detect_ipv4_connectivity() -> bool {
938    // Try to connect to well-known IPv4 addresses
939    let test_addresses = [
940        "8.8.8.8:53",     // Google DNS
941        "1.1.1.1:53",     // Cloudflare DNS
942        "208.67.222.222:53", // OpenDNS
943    ];
944    
945    for addr in &test_addresses {
946        if let Ok(_) = tokio::time::timeout(
947            Duration::from_secs(3),
948            tokio::net::TcpStream::connect(addr)
949        ).await {
950            debug!("IPv4 connectivity confirmed via {}", addr);
951            return true;
952        }
953    }
954    
955    debug!("IPv4 connectivity test failed");
956    false
957}
958
959/// Detect IPv6 connectivity and available addresses
960async fn detect_ipv6_connectivity() -> Vec<Ipv6Addr> {
961    let mut ipv6_addrs = Vec::new();
962    
963    // Get local IPv6 addresses
964    if let Ok(interfaces) = get_network_interfaces().await {
965        for interface in interfaces {
966            for addr in interface.ipv6_addrs {
967                if !addr.is_loopback() && !addr.is_multicast() {
968                    ipv6_addrs.push(addr);
969                }
970            }
971        }
972    }
973    
974    // Test connectivity to IPv6 servers if we have addresses
975    if !ipv6_addrs.is_empty() {
976        let test_addresses = [
977            "[2001:4860:4860::8888]:53", // Google DNS
978            "[2606:4700:4700::1111]:53", // Cloudflare DNS
979        ];
980        
981        for addr in &test_addresses {
982            if let Ok(_) = tokio::time::timeout(
983                Duration::from_secs(3),
984                tokio::net::TcpStream::connect(addr)
985            ).await {
986                debug!("IPv6 connectivity confirmed via {}", addr);
987                return ipv6_addrs;
988            }
989        }
990        
991        debug!("IPv6 addresses found but no external connectivity");
992        ipv6_addrs.clear(); // Clear if no external connectivity
993    }
994    
995    ipv6_addrs
996}
997
998/// Detect NAT presence and discover public IPv4 address
999async fn detect_nat_and_public_ip() -> (bool, Option<Ipv4Addr>) {
1000    // Get local IPv4 address
1001    let local_ipv4 = get_local_ipv4_addr().await;
1002    
1003    // Try to discover public IP via STUN-like service
1004    if let Ok(public_ip) = discover_public_ipv4().await {
1005        let behind_nat = local_ipv4.map_or(true, |local| local != public_ip);
1006        return (behind_nat, Some(public_ip));
1007    }
1008    
1009    // Fallback: check if local IP is private
1010    if let Some(local) = local_ipv4 {
1011        let behind_nat = local.is_private();
1012        (behind_nat, if behind_nat { None } else { Some(local) })
1013    } else {
1014        (true, None)
1015    }
1016}
1017
1018/// Discover public IPv4 address using external services
1019async fn discover_public_ipv4() -> Result<Ipv4Addr> {
1020    // Try multiple IP discovery services
1021    let services = [
1022        "https://api.ipify.org",
1023        "https://icanhazip.com",
1024        "https://ifconfig.me/ip",
1025    ];
1026    
1027    for service in &services {
1028        if let Ok(response) = tokio::time::timeout(
1029            Duration::from_secs(5),
1030            reqwest::get(*service)
1031        ).await {
1032            if let Ok(response) = response {
1033                if let Ok(ip_str) = response.text().await {
1034                    if let Ok(ip) = ip_str.trim().parse::<Ipv4Addr>() {
1035                        debug!("Public IPv4 discovered via {}: {}", service, ip);
1036                        return Ok(ip);
1037                    }
1038                }
1039            }
1040        }
1041    }
1042    
1043    Err(P2PError::Network("Failed to discover public IPv4 address".to_string()))
1044}
1045
1046/// Get local IPv4 address
1047async fn get_local_ipv4_addr() -> Option<Ipv4Addr> {
1048    if let Ok(interfaces) = get_network_interfaces().await {
1049        for interface in interfaces {
1050            for addr in interface.ipv4_addrs {
1051                if !addr.is_loopback() && !addr.is_multicast() {
1052                    return Some(addr);
1053                }
1054            }
1055        }
1056    }
1057    None
1058}
1059
1060/// Test UPnP availability for automatic port forwarding
1061async fn test_upnp_availability() -> bool {
1062    // This would test for UPnP Internet Gateway Device Protocol
1063    // For now, return false as a conservative default
1064    // In production, this would:
1065    // 1. Send M-SEARCH multicast to discover UPnP devices
1066    // 2. Parse device descriptions
1067    // 3. Test port mapping capabilities
1068    debug!("UPnP testing not implemented, assuming unavailable");
1069    false
1070}
1071
1072/// Detect interface MTU
1073async fn detect_interface_mtu() -> u16 {
1074    // Try to detect the MTU of the primary network interface
1075    // For now, return standard Ethernet MTU
1076    // In production, this would:
1077    // 1. Query interface statistics
1078    // 2. Perform path MTU discovery
1079    // 3. Test actual payload sizes
1080    1500
1081}
1082
1083/// Network interface information
1084#[allow(dead_code)]
1085#[derive(Debug)]
1086struct NetworkInterface {
1087    _name: String,
1088    ipv4_addrs: Vec<Ipv4Addr>,
1089    ipv6_addrs: Vec<Ipv6Addr>,
1090}
1091
1092/// Get network interfaces (simplified implementation)
1093async fn get_network_interfaces() -> Result<Vec<NetworkInterface>> {
1094    // This is a placeholder - in production this would use platform-specific APIs
1095    // to enumerate network interfaces and their addresses
1096    
1097    // For now, simulate a typical interface
1098    let interface = NetworkInterface {
1099        _name: "eth0".to_string(),
1100        ipv4_addrs: vec![Ipv4Addr::new(192, 168, 1, 100)],
1101        ipv6_addrs: vec![],
1102    };
1103    
1104    Ok(vec![interface])
1105}
1106
1107/// Calculate throughput based on tunnel metrics
1108fn calculate_throughput(metrics: &TunnelMetrics) -> Option<f64> {
1109    let elapsed = metrics.last_activity.elapsed();
1110    if elapsed.as_secs() > 0 {
1111        let total_bytes = metrics.bytes_sent + metrics.bytes_received;
1112        Some(total_bytes as f64 / elapsed.as_secs_f64())
1113    } else {
1114        None
1115    }
1116}
1117
1118/// Calculate reliability score based on tunnel state and metrics
1119fn calculate_reliability_score(state: &TunnelState, metrics: &TunnelMetrics) -> f32 {
1120    let mut score = match state {
1121        TunnelState::Connected => 1.0,
1122        TunnelState::Connecting => 0.5,
1123        TunnelState::Disconnected => 0.0,
1124        TunnelState::Failed(_) => 0.0,
1125        TunnelState::Disconnecting => 0.2,
1126    };
1127    
1128    // Adjust score based on packet loss
1129    if metrics.packets_sent > 0 {
1130        let packet_loss = metrics.packets_dropped as f32 / metrics.packets_sent as f32;
1131        score *= (1.0 - packet_loss).max(0.0);
1132    }
1133    
1134    // Adjust score based on activity recency
1135    let inactive_time = metrics.last_activity.elapsed();
1136    if inactive_time > Duration::from_secs(300) { // 5 minutes
1137        score *= 0.5; // Penalize stale tunnels
1138    }
1139    
1140    score.min(1.0).max(0.0)
1141}
1142
1143// Tunneling protocol implementations
1144pub mod sixto4;
1145pub mod teredo;
1146pub mod sixinfour;
1147pub mod dslite;
1148pub mod isatap;
1149pub mod map;
1150
1151pub use sixto4::SixToFourTunnel;
1152pub use teredo::TeredoTunnel;
1153pub use sixinfour::SixInFourTunnel;
1154pub use dslite::DsLiteTunnel;
1155pub use isatap::IsatapTunnel;
1156pub use map::{MapTunnel, MapProtocol, MapRule, PortParameters, PortSet};
1157
1158#[cfg(test)]
1159mod tests {
1160    use super::*;
1161    use std::sync::Arc;
1162    use std::sync::atomic::{AtomicUsize, Ordering};
1163    use tokio::sync::Mutex;
1164
1165    /// Mock tunnel implementation for testing
1166    struct MockTunnel {
1167        protocol: TunnelProtocol,
1168        config: TunnelConfig,
1169        state: Arc<Mutex<TunnelState>>,
1170        metrics: Arc<Mutex<TunnelMetrics>>,
1171        should_fail: bool,
1172        packet_counter: AtomicUsize,
1173    }
1174
1175    impl MockTunnel {
1176        fn new(config: TunnelConfig) -> Self {
1177            Self {
1178                protocol: config.protocol.clone(),
1179                config,
1180                state: Arc::new(Mutex::new(TunnelState::Disconnected)),
1181                metrics: Arc::new(Mutex::new(TunnelMetrics::default())),
1182                should_fail: false,
1183                packet_counter: AtomicUsize::new(0),
1184            }
1185        }
1186
1187        fn with_failure(mut self) -> Self {
1188            self.should_fail = true;
1189            self
1190        }
1191
1192        async fn set_state(&self, new_state: TunnelState) {
1193            let mut state = self.state.lock().await;
1194            *state = new_state;
1195        }
1196    }
1197
1198    #[async_trait]
1199    impl Tunnel for MockTunnel {
1200        fn protocol(&self) -> TunnelProtocol {
1201            self.protocol.clone()
1202        }
1203
1204        fn config(&self) -> &TunnelConfig {
1205            &self.config
1206        }
1207
1208        async fn state(&self) -> TunnelState {
1209            self.state.lock().await.clone()
1210        }
1211
1212        async fn metrics(&self) -> TunnelMetrics {
1213            self.metrics.lock().await.clone()
1214        }
1215
1216        async fn connect(&mut self) -> Result<()> {
1217            if self.should_fail {
1218                let mut state = self.state.lock().await;
1219                *state = TunnelState::Failed("Connection failed".to_string());
1220                return Err(P2PError::Network("Mock connection failure".to_string()));
1221            }
1222
1223            let mut state = self.state.lock().await;
1224            *state = TunnelState::Connecting;
1225            tokio::time::sleep(Duration::from_millis(10)).await;
1226            *state = TunnelState::Connected;
1227
1228            let mut metrics = self.metrics.lock().await;
1229            metrics.establishment_time = Duration::from_millis(10);
1230            metrics.last_activity = Instant::now();
1231
1232            Ok(())
1233        }
1234
1235        async fn disconnect(&mut self) -> Result<()> {
1236            let mut state = self.state.lock().await;
1237            *state = TunnelState::Disconnecting;
1238            tokio::time::sleep(Duration::from_millis(5)).await;
1239            *state = TunnelState::Disconnected;
1240            Ok(())
1241        }
1242
1243        async fn is_active(&self) -> bool {
1244            matches!(self.state().await, TunnelState::Connected)
1245        }
1246
1247        async fn encapsulate(&self, ipv6_packet: &[u8]) -> Result<Vec<u8>> {
1248            if !self.is_active().await {
1249                return Err(P2PError::Network("Tunnel not active".to_string()));
1250            }
1251
1252            // Mock encapsulation: prepend 4-byte IPv4 header
1253            let mut ipv4_packet = vec![0x45, 0x00, 0x00, 0x00]; // Mock IPv4 header
1254            ipv4_packet.extend_from_slice(ipv6_packet);
1255            Ok(ipv4_packet)
1256        }
1257
1258        async fn decapsulate(&self, ipv4_packet: &[u8]) -> Result<Vec<u8>> {
1259            if !self.is_active().await {
1260                return Err(P2PError::Network("Tunnel not active".to_string()));
1261            }
1262
1263            if ipv4_packet.len() < 4 {
1264                return Err(P2PError::Network("Invalid IPv4 packet".to_string()));
1265            }
1266
1267            // Mock decapsulation: remove 4-byte IPv4 header
1268            Ok(ipv4_packet[4..].to_vec())
1269        }
1270
1271        async fn send(&mut self, packet: &[u8]) -> Result<()> {
1272            if !self.is_active().await {
1273                return Err(P2PError::Network("Tunnel not active".to_string()));
1274            }
1275
1276            let mut metrics = self.metrics.lock().await;
1277            metrics.bytes_sent += packet.len() as u64;
1278            metrics.packets_sent += 1;
1279            metrics.last_activity = Instant::now();
1280
1281            self.packet_counter.fetch_add(1, Ordering::Relaxed);
1282            Ok(())
1283        }
1284
1285        async fn receive(&mut self) -> Result<Vec<u8>> {
1286            if !self.is_active().await {
1287                return Err(P2PError::Network("Tunnel not active".to_string()));
1288            }
1289
1290            let packet = b"mock_packet".to_vec();
1291            let mut metrics = self.metrics.lock().await;
1292            metrics.bytes_received += packet.len() as u64;
1293            metrics.packets_received += 1;
1294            metrics.last_activity = Instant::now();
1295
1296            Ok(packet)
1297        }
1298
1299        async fn maintain(&mut self) -> Result<()> {
1300            let mut metrics = self.metrics.lock().await;
1301            metrics.last_activity = Instant::now();
1302            Ok(())
1303        }
1304
1305        async fn local_ipv6_addr(&self) -> Result<Ipv6Addr> {
1306            self.config.ipv6_prefix
1307                .ok_or_else(|| P2PError::Network("No IPv6 prefix configured".to_string()))
1308        }
1309
1310        async fn local_ipv4_addr(&self) -> Result<Ipv4Addr> {
1311            self.config.local_ipv4
1312                .ok_or_else(|| P2PError::Network("No IPv4 address configured".to_string()))
1313        }
1314
1315        async fn ping(&mut self, timeout: Duration) -> Result<Duration> {
1316            if self.should_fail {
1317                return Err(P2PError::Network("Ping failed".to_string()));
1318            }
1319
1320            if !self.is_active().await {
1321                return Err(P2PError::Network("Tunnel not active".to_string()));
1322            }
1323
1324            // Mock ping with random latency
1325            let rtt = Duration::from_millis(10 + (timeout.as_millis() % 50) as u64);
1326            
1327            let mut metrics = self.metrics.lock().await;
1328            metrics.rtt = Some(rtt);
1329            metrics.last_activity = Instant::now();
1330
1331            Ok(rtt)
1332        }
1333    }
1334
1335    fn create_test_tunnel_config(protocol: TunnelProtocol) -> TunnelConfig {
1336        TunnelConfig {
1337            protocol,
1338            local_ipv4: Some(Ipv4Addr::new(192, 168, 1, 100)),
1339            remote_ipv4: Some(Ipv4Addr::new(203, 0, 113, 1)),
1340            ipv6_prefix: Some(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
1341            aftr_ipv6: Some(Ipv6Addr::new(0x2001, 0xdb8, 0, 1, 0, 0, 0, 1)),
1342            aftr_name: Some("aftr.test.com".to_string()),
1343            mtu: 1280,
1344            keepalive_interval: Duration::from_secs(30),
1345            establishment_timeout: Duration::from_secs(10),
1346        }
1347    }
1348
1349    fn create_test_network_capabilities() -> NetworkCapabilities {
1350        NetworkCapabilities {
1351            has_ipv6: false,
1352            has_ipv4: true,
1353            behind_nat: false,
1354            public_ipv4: Some(Ipv4Addr::new(203, 0, 113, 100)),
1355            ipv6_addresses: vec![],
1356            has_upnp: false,
1357            interface_mtu: 1500,
1358        }
1359    }
1360
1361    #[test]
1362    fn test_tunnel_protocol_equality() {
1363        assert_eq!(TunnelProtocol::SixToFour, TunnelProtocol::SixToFour);
1364        assert_ne!(TunnelProtocol::SixToFour, TunnelProtocol::Teredo);
1365        assert_eq!(TunnelProtocol::MapE, TunnelProtocol::MapE);
1366    }
1367
1368    #[test]
1369    fn test_tunnel_state_variants() {
1370        let disconnected = TunnelState::Disconnected;
1371        let connecting = TunnelState::Connecting;
1372        let connected = TunnelState::Connected;
1373        let failed = TunnelState::Failed("test error".to_string());
1374        let disconnecting = TunnelState::Disconnecting;
1375
1376        assert!(matches!(disconnected, TunnelState::Disconnected));
1377        assert!(matches!(connecting, TunnelState::Connecting));
1378        assert!(matches!(connected, TunnelState::Connected));
1379        assert!(matches!(failed, TunnelState::Failed(_)));
1380        assert!(matches!(disconnecting, TunnelState::Disconnecting));
1381    }
1382
1383    #[test]
1384    fn test_tunnel_config_default() {
1385        let config = TunnelConfig::default();
1386
1387        assert_eq!(config.protocol, TunnelProtocol::SixToFour);
1388        assert_eq!(config.mtu, 1280);
1389        assert_eq!(config.keepalive_interval, Duration::from_secs(30));
1390        assert_eq!(config.establishment_timeout, Duration::from_secs(10));
1391        assert!(config.local_ipv4.is_none());
1392        assert!(config.remote_ipv4.is_none());
1393    }
1394
1395    #[test]
1396    fn test_tunnel_manager_config_default() {
1397        let config = TunnelManagerConfig::default();
1398
1399        assert_eq!(config.protocol_preference.len(), 5);
1400        assert_eq!(config.protocol_preference[0], TunnelProtocol::DsLite);
1401        assert_eq!(config.health_check_interval, Duration::from_secs(60));
1402        assert!(config.auto_failover);
1403        assert_eq!(config.max_concurrent_attempts, 3);
1404    }
1405
1406    #[test]
1407    fn test_tunnel_metrics_default() {
1408        let metrics = TunnelMetrics::default();
1409
1410        assert_eq!(metrics.bytes_sent, 0);
1411        assert_eq!(metrics.bytes_received, 0);
1412        assert_eq!(metrics.packets_sent, 0);
1413        assert_eq!(metrics.packets_received, 0);
1414        assert_eq!(metrics.packets_dropped, 0);
1415        assert!(metrics.rtt.is_none());
1416        assert_eq!(metrics.establishment_time, Duration::ZERO);
1417    }
1418
1419    #[tokio::test]
1420    async fn test_tunnel_manager_creation() {
1421        let manager = TunnelManager::new();
1422        assert!(manager.active_tunnel().await.is_none());
1423
1424        let custom_config = TunnelManagerConfig {
1425            auto_failover: false,
1426            max_concurrent_attempts: 1,
1427            ..Default::default()
1428        };
1429        let custom_manager = TunnelManager::with_config(custom_config);
1430        assert!(custom_manager.active_tunnel().await.is_none());
1431    }
1432
1433    #[tokio::test]
1434    async fn test_tunnel_addition_and_retrieval() {
1435        let manager = TunnelManager::new();
1436        let config = create_test_tunnel_config(TunnelProtocol::SixToFour);
1437        let tunnel = MockTunnel::new(config);
1438
1439        manager.add_tunnel(Box::new(tunnel)).await;
1440
1441        let tunnels = manager.tunnels.read().await;
1442        assert_eq!(tunnels.len(), 1);
1443        assert_eq!(tunnels[0].protocol(), TunnelProtocol::SixToFour);
1444    }
1445
1446    #[tokio::test]
1447    async fn test_mock_tunnel_lifecycle() -> Result<()> {
1448        let config = create_test_tunnel_config(TunnelProtocol::Teredo);
1449        let mut tunnel = MockTunnel::new(config);
1450
1451        // Initial state
1452        assert_eq!(tunnel.state().await, TunnelState::Disconnected);
1453        assert!(!tunnel.is_active().await);
1454
1455        // Connect
1456        tunnel.connect().await?;
1457        assert_eq!(tunnel.state().await, TunnelState::Connected);
1458        assert!(tunnel.is_active().await);
1459
1460        // Test addresses
1461        let ipv6 = tunnel.local_ipv6_addr().await?;
1462        let ipv4 = tunnel.local_ipv4_addr().await?;
1463        assert_eq!(ipv6, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
1464        assert_eq!(ipv4, Ipv4Addr::new(192, 168, 1, 100));
1465
1466        // Test ping
1467        let rtt = tunnel.ping(Duration::from_secs(1)).await?;
1468        assert!(rtt > Duration::ZERO);
1469
1470        // Disconnect
1471        tunnel.disconnect().await?;
1472        assert_eq!(tunnel.state().await, TunnelState::Disconnected);
1473        assert!(!tunnel.is_active().await);
1474
1475        Ok(())
1476    }
1477
1478    #[tokio::test]
1479    async fn test_tunnel_packet_operations() -> Result<()> {
1480        let config = create_test_tunnel_config(TunnelProtocol::SixToFour);
1481        let mut tunnel = MockTunnel::new(config);
1482        
1483        tunnel.connect().await?;
1484
1485        // Test encapsulation
1486        let ipv6_packet = vec![0x60, 0x00, 0x00, 0x00]; // Mock IPv6 header
1487        let ipv4_packet = tunnel.encapsulate(&ipv6_packet).await?;
1488        assert_eq!(ipv4_packet.len(), ipv6_packet.len() + 4);
1489
1490        // Test decapsulation
1491        let decapsulated = tunnel.decapsulate(&ipv4_packet).await?;
1492        assert_eq!(decapsulated, ipv6_packet);
1493
1494        // Test send/receive
1495        let test_packet = b"test data";
1496        tunnel.send(test_packet).await?;
1497        
1498        let received = tunnel.receive().await?;
1499        assert_eq!(received, b"mock_packet");
1500
1501        // Check metrics
1502        let metrics = tunnel.metrics().await;
1503        assert_eq!(metrics.packets_sent, 1);
1504        assert_eq!(metrics.packets_received, 1);
1505        assert_eq!(metrics.bytes_sent, test_packet.len() as u64);
1506
1507        Ok(())
1508    }
1509
1510    #[tokio::test]
1511    async fn test_tunnel_failure_handling() {
1512        let config = create_test_tunnel_config(TunnelProtocol::Teredo);
1513        let mut failing_tunnel = MockTunnel::new(config).with_failure();
1514
1515        // Connection should fail
1516        let result = failing_tunnel.connect().await;
1517        assert!(result.is_err());
1518        assert!(matches!(failing_tunnel.state().await, TunnelState::Failed(_)));
1519
1520        // Operations should fail when tunnel failed
1521        let packet = vec![1, 2, 3, 4];
1522        assert!(failing_tunnel.send(&packet).await.is_err());
1523        assert!(failing_tunnel.receive().await.is_err());
1524        assert!(failing_tunnel.ping(Duration::from_secs(1)).await.is_err());
1525    }
1526
1527    #[tokio::test]
1528    async fn test_tunnel_operations_when_disconnected() {
1529        let config = create_test_tunnel_config(TunnelProtocol::SixInFour);
1530        let tunnel = MockTunnel::new(config);
1531
1532        // Operations should fail when disconnected
1533        let packet = vec![1, 2, 3, 4];
1534        assert!(tunnel.encapsulate(&packet).await.is_err());
1535        assert!(tunnel.decapsulate(&packet).await.is_err());
1536    }
1537
1538    #[tokio::test]
1539    async fn test_tunnel_selection_with_native_ipv6() {
1540        let manager = TunnelManager::new();
1541        let capabilities = NetworkCapabilities {
1542            has_ipv6: true,
1543            ipv6_addresses: vec![Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)],
1544            ..create_test_network_capabilities()
1545        };
1546
1547        let selection = manager.select_tunnel(&capabilities).await;
1548        assert!(selection.is_none()); // No tunneling needed with native IPv6
1549    }
1550
1551    #[tokio::test]
1552    async fn test_tunnel_selection_scoring() {
1553        let manager = TunnelManager::new();
1554        let config = create_test_tunnel_config(TunnelProtocol::SixToFour);
1555        let tunnel = MockTunnel::new(config);
1556        manager.add_tunnel(Box::new(tunnel)).await;
1557
1558        let capabilities = create_test_network_capabilities();
1559        let selection = manager.select_tunnel(&capabilities).await;
1560
1561        assert!(selection.is_some());
1562        let selection = selection.unwrap();
1563        assert_eq!(selection.protocol, TunnelProtocol::SixToFour);
1564        assert!(selection.reason.contains("6to4 suitable"));
1565        assert!(!selection.is_fallback);
1566    }
1567
1568    #[tokio::test]
1569    async fn test_tunnel_selection_behind_nat() {
1570        let manager = TunnelManager::new();
1571        
1572        // Add Teredo tunnel (good for NAT)
1573        let teredo_config = create_test_tunnel_config(TunnelProtocol::Teredo);
1574        let teredo_tunnel = MockTunnel::new(teredo_config);
1575        manager.add_tunnel(Box::new(teredo_tunnel)).await;
1576
1577        let capabilities = NetworkCapabilities {
1578            behind_nat: true,
1579            public_ipv4: None,
1580            ..create_test_network_capabilities()
1581        };
1582
1583        let selection = manager.select_tunnel(&capabilities).await;
1584        assert!(selection.is_some());
1585        let selection = selection.unwrap();
1586        assert_eq!(selection.protocol, TunnelProtocol::Teredo);
1587        assert!(selection.reason.contains("NAT traversal"));
1588    }
1589
1590    #[tokio::test]
1591    async fn test_tunnel_selection_ds_lite() {
1592        let manager = TunnelManager::new();
1593        
1594        let dslite_config = create_test_tunnel_config(TunnelProtocol::DsLite);
1595        let dslite_tunnel = MockTunnel::new(dslite_config);
1596        manager.add_tunnel(Box::new(dslite_tunnel)).await;
1597
1598        let capabilities = NetworkCapabilities {
1599            has_ipv6: true,
1600            ipv6_addresses: vec![], // No working IPv6 yet
1601            ..create_test_network_capabilities()
1602        };
1603
1604        let selection = manager.select_tunnel(&capabilities).await;
1605        assert!(selection.is_some());
1606        let selection = selection.unwrap();
1607        assert_eq!(selection.protocol, TunnelProtocol::DsLite);
1608        assert!(selection.reason.contains("ISP-provided"));
1609    }
1610
1611    #[tokio::test]
1612    async fn test_tunnel_manager_connection() -> Result<()> {
1613        let manager = TunnelManager::new();
1614        let config = create_test_tunnel_config(TunnelProtocol::SixToFour);
1615        let tunnel = MockTunnel::new(config);
1616        manager.add_tunnel(Box::new(tunnel)).await;
1617
1618        // Select tunnel first
1619        let capabilities = create_test_network_capabilities();
1620        manager.select_tunnel(&capabilities).await;
1621
1622        // Connect
1623        manager.connect().await?;
1624
1625        // Should have active tunnel
1626        assert_eq!(manager.active_tunnel().await, Some(TunnelProtocol::SixToFour));
1627
1628        Ok(())
1629    }
1630
1631    #[tokio::test]
1632    async fn test_tunnel_manager_send_receive() -> Result<()> {
1633        let manager = TunnelManager::new();
1634        let config = create_test_tunnel_config(TunnelProtocol::Teredo);
1635        let tunnel = MockTunnel::new(config);
1636        manager.add_tunnel(Box::new(tunnel)).await;
1637
1638        let capabilities = create_test_network_capabilities();
1639        manager.select_tunnel(&capabilities).await;
1640        manager.connect().await?;
1641
1642        // Test sending
1643        let packet = b"test packet";
1644        manager.send(packet).await?;
1645
1646        // Test receiving
1647        let received = manager.receive().await?;
1648        assert_eq!(received, b"mock_packet");
1649
1650        // Test metrics
1651        let metrics = manager.metrics().await;
1652        assert!(metrics.is_some());
1653        let metrics = metrics.unwrap();
1654        assert_eq!(metrics.packets_sent, 1);
1655
1656        Ok(())
1657    }
1658
1659    #[tokio::test]
1660    async fn test_tunnel_manager_no_active_tunnel() {
1661        let manager = TunnelManager::new();
1662
1663        // Operations should fail without active tunnel
1664        assert!(manager.connect().await.is_err());
1665        assert!(manager.send(b"test").await.is_err());
1666        assert!(manager.receive().await.is_err());
1667        assert!(manager.metrics().await.is_none());
1668    }
1669
1670    #[tokio::test]
1671    async fn test_tunnel_manager_health_check() -> Result<()> {
1672        let manager = TunnelManager::new();
1673        let config = create_test_tunnel_config(TunnelProtocol::SixToFour);
1674        let tunnel = MockTunnel::new(config);
1675        manager.add_tunnel(Box::new(tunnel)).await;
1676
1677        let capabilities = create_test_network_capabilities();
1678        manager.select_tunnel(&capabilities).await;
1679        manager.connect().await?;
1680
1681        // Health check should pass
1682        manager.health_check().await?;
1683
1684        Ok(())
1685    }
1686
1687    #[tokio::test]
1688    async fn test_tunnel_manager_health_check_with_failure() -> Result<()> {
1689        // Create manager with auto-failover disabled to avoid trying to switch
1690        let config = TunnelManagerConfig {
1691            auto_failover: false,
1692            ..Default::default()
1693        };
1694        let manager = TunnelManager::with_config(config);
1695        
1696        let tunnel_config = create_test_tunnel_config(TunnelProtocol::Teredo);
1697        let failing_tunnel = MockTunnel::new(tunnel_config).with_failure();
1698        manager.add_tunnel(Box::new(failing_tunnel)).await;
1699
1700        let capabilities = create_test_network_capabilities();
1701        manager.select_tunnel(&capabilities).await;
1702
1703        // Health check should handle failures gracefully
1704        manager.health_check().await?;
1705
1706        Ok(())
1707    }
1708
1709    #[tokio::test]
1710    async fn test_tunnel_manager_monitoring() -> Result<()> {
1711        let manager = TunnelManager::new();
1712        
1713        // Start monitoring (should not fail)
1714        manager.start_monitoring().await?;
1715
1716        Ok(())
1717    }
1718
1719    #[tokio::test]
1720    async fn test_tunnel_manager_maintenance() -> Result<()> {
1721        let manager = TunnelManager::new();
1722        let config = create_test_tunnel_config(TunnelProtocol::SixInFour);
1723        let tunnel = MockTunnel::new(config);
1724        manager.add_tunnel(Box::new(tunnel)).await;
1725
1726        // Maintenance should not fail
1727        manager.maintain().await?;
1728
1729        Ok(())
1730    }
1731
1732    #[tokio::test]
1733    async fn test_tunnel_quality_metrics() {
1734        let manager = TunnelManager::new();
1735        let config = create_test_tunnel_config(TunnelProtocol::SixToFour);
1736        let tunnel = MockTunnel::new(config);
1737        tunnel.set_state(TunnelState::Connected).await;
1738        manager.add_tunnel(Box::new(tunnel)).await;
1739
1740        let quality_metrics = manager.get_tunnel_quality_metrics().await;
1741        assert_eq!(quality_metrics.len(), 1);
1742        
1743        let metric = &quality_metrics[0];
1744        assert_eq!(metric.protocol, TunnelProtocol::SixToFour);
1745        assert_eq!(metric.state, TunnelState::Connected);
1746        assert!(metric.reliability_score > 0.0);
1747    }
1748
1749    #[tokio::test]
1750    async fn test_network_capabilities_detection() -> Result<()> {
1751        let capabilities = detect_network_capabilities().await?;
1752
1753        // Should have basic network information
1754        assert!(capabilities.interface_mtu > 0);
1755        // Other fields depend on network environment
1756
1757        Ok(())
1758    }
1759
1760    #[test]
1761    fn test_create_tunnel_config_sixto4() {
1762        let capabilities = create_test_network_capabilities();
1763        let config = create_tunnel_config(TunnelProtocol::SixToFour, &capabilities);
1764
1765        assert_eq!(config.protocol, TunnelProtocol::SixToFour);
1766        assert_eq!(config.local_ipv4, capabilities.public_ipv4);
1767        assert!(config.ipv6_prefix.is_some());
1768        
1769        // Should generate 6to4 prefix (2002::/16)
1770        let ipv6 = config.ipv6_prefix.unwrap();
1771        let segments = ipv6.segments();
1772        assert_eq!(segments[0], 0x2002);
1773    }
1774
1775    #[test]
1776    fn test_create_tunnel_config_teredo() {
1777        let capabilities = create_test_network_capabilities();
1778        let config = create_tunnel_config(TunnelProtocol::Teredo, &capabilities);
1779
1780        assert_eq!(config.protocol, TunnelProtocol::Teredo);
1781        assert_eq!(config.mtu, 1280);
1782        
1783        // Should use Teredo prefix (2001::/32)
1784        let ipv6 = config.ipv6_prefix.unwrap();
1785        let segments = ipv6.segments();
1786        assert_eq!(segments[0], 0x2001);
1787    }
1788
1789    #[test]
1790    fn test_create_tunnel_config_dslite() {
1791        let capabilities = create_test_network_capabilities();
1792        let config = create_tunnel_config(TunnelProtocol::DsLite, &capabilities);
1793
1794        assert_eq!(config.protocol, TunnelProtocol::DsLite);
1795        assert_eq!(config.mtu, 1520);
1796        assert!(config.aftr_name.is_some());
1797        assert_eq!(config.aftr_name.unwrap(), "aftr.example.com");
1798    }
1799
1800    #[test]
1801    fn test_create_tunnel_config_map_protocols() {
1802        let capabilities = create_test_network_capabilities();
1803        
1804        let map_e_config = create_tunnel_config(TunnelProtocol::MapE, &capabilities);
1805        assert_eq!(map_e_config.protocol, TunnelProtocol::MapE);
1806        assert_eq!(map_e_config.mtu, 1460);
1807        assert_eq!(map_e_config.local_ipv4, capabilities.public_ipv4);
1808        
1809        let map_t_config = create_tunnel_config(TunnelProtocol::MapT, &capabilities);
1810        assert_eq!(map_t_config.protocol, TunnelProtocol::MapT);
1811        assert_eq!(map_t_config.mtu, 1500);
1812        assert_eq!(map_t_config.local_ipv4, capabilities.public_ipv4);
1813    }
1814
1815    #[test]
1816    fn test_calculate_reliability_score() {
1817        let metrics = TunnelMetrics {
1818            packets_sent: 100,
1819            packets_dropped: 5,
1820            last_activity: Instant::now(),
1821            ..Default::default()
1822        };
1823
1824        let score_connected = calculate_reliability_score(&TunnelState::Connected, &metrics);
1825        assert!(score_connected > 0.9); // Should be high for connected with low loss
1826
1827        let score_failed = calculate_reliability_score(&TunnelState::Failed("error".to_string()), &metrics);
1828        assert_eq!(score_failed, 0.0); // Should be 0 for failed state
1829
1830        let score_connecting = calculate_reliability_score(&TunnelState::Connecting, &metrics);
1831        assert!(score_connecting > 0.4 && score_connecting < 0.6); // Intermediate score
1832    }
1833
1834    #[test]
1835    fn test_calculate_throughput() {
1836        let old_activity = Instant::now() - Duration::from_secs(10);
1837        let metrics = TunnelMetrics {
1838            bytes_sent: 1000,
1839            bytes_received: 500,
1840            last_activity: old_activity,
1841            ..Default::default()
1842        };
1843
1844        let throughput = calculate_throughput(&metrics);
1845        assert!(throughput.is_some());
1846        assert!(throughput.unwrap() > 0.0);
1847
1848        // Test with very recent activity (should return None)
1849        let recent_metrics = TunnelMetrics {
1850            last_activity: Instant::now(),
1851            ..Default::default()
1852        };
1853        let recent_throughput = calculate_throughput(&recent_metrics);
1854        assert!(recent_throughput.is_none());
1855    }
1856
1857    #[tokio::test]
1858    async fn test_protocol_scoring_comprehensive() {
1859        let manager = TunnelManager::new();
1860
1861        // Test 6to4 scoring with public IP
1862        let public_capabilities = create_test_network_capabilities();
1863        let (score, reason) = manager.score_protocol(&TunnelProtocol::SixToFour, &public_capabilities).await;
1864        assert!(score > 0.8);
1865        assert!(reason.contains("6to4 suitable"));
1866
1867        // Test 6to4 scoring behind NAT (should fail)
1868        let nat_capabilities = NetworkCapabilities {
1869            behind_nat: true,
1870            public_ipv4: None,
1871            ..public_capabilities
1872        };
1873        let (nat_score, nat_reason) = manager.score_protocol(&TunnelProtocol::SixToFour, &nat_capabilities).await;
1874        assert_eq!(nat_score, 0.0);
1875        assert!(nat_reason.contains("behind NAT"));
1876
1877        // Test Teredo with NAT (should score well)
1878        let (teredo_score, teredo_reason) = manager.score_protocol(&TunnelProtocol::Teredo, &nat_capabilities).await;
1879        assert!(teredo_score > 0.8);
1880        assert!(teredo_reason.contains("NAT traversal"));
1881
1882        // Test ISATAP with enterprise network indicators
1883        let enterprise_capabilities = NetworkCapabilities {
1884            public_ipv4: Some(Ipv4Addr::new(10, 0, 0, 1)), // Private IP
1885            ..create_test_network_capabilities()
1886        };
1887        let (isatap_score, isatap_reason) = manager.score_protocol(&TunnelProtocol::Isatap, &enterprise_capabilities).await;
1888        assert!(isatap_score > 0.9);
1889        assert!(isatap_reason.contains("private network"));
1890    }
1891
1892    #[tokio::test]
1893    async fn test_tunnel_selection_no_suitable_protocols() {
1894        let manager = TunnelManager::new();
1895        
1896        // Add tunnel that requires IPv6
1897        let dslite_config = create_test_tunnel_config(TunnelProtocol::DsLite);
1898        let dslite_tunnel = MockTunnel::new(dslite_config);
1899        manager.add_tunnel(Box::new(dslite_tunnel)).await;
1900
1901        // Test with IPv4-only capabilities
1902        let ipv4_only_capabilities = NetworkCapabilities {
1903            has_ipv6: false,
1904            ipv6_addresses: vec![],
1905            ..create_test_network_capabilities()
1906        };
1907
1908        let selection = manager.select_tunnel(&ipv4_only_capabilities).await;
1909        assert!(selection.is_none());
1910    }
1911
1912    #[tokio::test]
1913    async fn test_tunnel_manager_disconnect() -> Result<()> {
1914        let manager = TunnelManager::new();
1915        let config = create_test_tunnel_config(TunnelProtocol::SixToFour);
1916        let tunnel = MockTunnel::new(config);
1917        manager.add_tunnel(Box::new(tunnel)).await;
1918
1919        let capabilities = create_test_network_capabilities();
1920        manager.select_tunnel(&capabilities).await;
1921        manager.connect().await?;
1922
1923        // Disconnect should work
1924        manager.disconnect().await?;
1925
1926        Ok(())
1927    }
1928
1929    #[test]
1930    fn test_tunnel_selection_structure() {
1931        let selection = TunnelSelection {
1932            protocol: TunnelProtocol::MapE,
1933            reason: "Test reason".to_string(),
1934            selection_time: Duration::from_millis(100),
1935            is_fallback: false,
1936        };
1937
1938        assert_eq!(selection.protocol, TunnelProtocol::MapE);
1939        assert_eq!(selection.reason, "Test reason");
1940        assert_eq!(selection.selection_time, Duration::from_millis(100));
1941        assert!(!selection.is_fallback);
1942    }
1943
1944    #[test]
1945    fn test_tunnel_protocol_suitability_checks() {
1946        let manager = TunnelManager::new();
1947        let capabilities = create_test_network_capabilities();
1948
1949        // Test all protocols with IPv4-only
1950        assert!(manager.is_protocol_suitable(&TunnelProtocol::SixToFour, &capabilities));
1951        assert!(manager.is_protocol_suitable(&TunnelProtocol::Teredo, &capabilities));
1952        assert!(manager.is_protocol_suitable(&TunnelProtocol::SixInFour, &capabilities));
1953        assert!(manager.is_protocol_suitable(&TunnelProtocol::Isatap, &capabilities));
1954        assert!(manager.is_protocol_suitable(&TunnelProtocol::MapE, &capabilities));
1955        assert!(manager.is_protocol_suitable(&TunnelProtocol::MapT, &capabilities));
1956
1957        // DS-Lite requires IPv6
1958        assert!(!manager.is_protocol_suitable(&TunnelProtocol::DsLite, &capabilities));
1959
1960        let ipv6_capabilities = NetworkCapabilities {
1961            has_ipv6: true,
1962            ..capabilities
1963        };
1964        assert!(manager.is_protocol_suitable(&TunnelProtocol::DsLite, &ipv6_capabilities));
1965    }
1966}
1967
1968/// Create a tunnel configuration for a specific protocol
1969pub fn create_tunnel_config(protocol: TunnelProtocol, capabilities: &NetworkCapabilities) -> TunnelConfig {
1970    let mut config = TunnelConfig::default();
1971    config.protocol = protocol.clone();
1972    
1973    match protocol {
1974        TunnelProtocol::SixToFour => {
1975            // 6to4 uses well-known prefix 2002::/16
1976            if let Some(ipv4) = capabilities.public_ipv4 {
1977                config.local_ipv4 = Some(ipv4);
1978                // Generate 6to4 IPv6 address: 2002:WWXX:YYZZ::/48
1979                let octets = ipv4.octets();
1980                let ipv6_bytes = [
1981                    0x20, 0x02, // 6to4 prefix
1982                    octets[0], octets[1], octets[2], octets[3], // IPv4 address
1983                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 // Interface ID
1984                ];
1985                config.ipv6_prefix = Some(Ipv6Addr::from(ipv6_bytes));
1986            }
1987        }
1988        TunnelProtocol::Teredo => {
1989            // Teredo uses prefix 2001::/32
1990            let teredo_prefix = Ipv6Addr::new(0x2001, 0, 0, 0, 0, 0, 0, 1);
1991            config.ipv6_prefix = Some(teredo_prefix);
1992            config.mtu = 1280; // Teredo MTU is typically lower
1993        }
1994        TunnelProtocol::SixInFour => {
1995            // 6in4 requires explicit endpoint configuration
1996            config.mtu = 1480; // Account for IPv4 header overhead
1997            // Note: local_ipv4 and remote_ipv4 must be set by caller
1998            // IPv6 prefix can be configured or will use default
1999        }
2000        TunnelProtocol::DsLite => {
2001            // DS-Lite uses IPv4-in-IPv6 encapsulation
2002            config.mtu = 1520; // Account for IPv6 header overhead (40 bytes)
2003            // AFTR address discovery will be handled by the tunnel implementation
2004            // For now, use a placeholder AFTR name that could be configured
2005            config.aftr_name = Some("aftr.example.com".to_string());
2006        }
2007        TunnelProtocol::Isatap => {
2008            // ISATAP uses link-local or site-local prefix with ::0:5EFE:x.x.x.x interface ID
2009            config.mtu = 1500; // Standard MTU for enterprise networks
2010            // Use link-local prefix by default, can be overridden by enterprise configuration
2011            config.ipv6_prefix = Some("fe80::".parse().unwrap());
2012            // Local IPv4 will be auto-detected or can be configured
2013            if let Some(ipv4) = capabilities.public_ipv4 {
2014                config.local_ipv4 = Some(ipv4);
2015            }
2016        }
2017        TunnelProtocol::MapE => {
2018            // MAP-E uses IPv4-in-IPv6 encapsulation with mapping rules
2019            config.mtu = 1460; // Account for IPv6 header overhead (40 bytes)
2020            // MAP-E configuration will be provided by ISP via DHCP or configuration
2021            if let Some(ipv4) = capabilities.public_ipv4 {
2022                config.local_ipv4 = Some(ipv4);
2023            }
2024            // IPv6 prefix will be calculated based on MAP rules
2025        }
2026        TunnelProtocol::MapT => {
2027            // MAP-T uses stateless IPv4/IPv6 translation with mapping rules
2028            config.mtu = 1500; // No encapsulation overhead
2029            // MAP-T configuration will be provided by ISP via DHCP or configuration
2030            if let Some(ipv4) = capabilities.public_ipv4 {
2031                config.local_ipv4 = Some(ipv4);
2032            }
2033            // IPv6 prefix will be calculated based on MAP rules
2034        }
2035    }
2036    
2037    config
2038}
2039
2040/// Create a tunnel instance for a specific protocol
2041pub fn create_tunnel(config: TunnelConfig) -> Result<Box<dyn Tunnel>> {
2042    match config.protocol {
2043        TunnelProtocol::SixToFour => {
2044            let tunnel = SixToFourTunnel::new(config)?;
2045            Ok(Box::new(tunnel))
2046        }
2047        TunnelProtocol::Teredo => {
2048            let tunnel = TeredoTunnel::new(config)?;
2049            Ok(Box::new(tunnel))
2050        }
2051        TunnelProtocol::SixInFour => {
2052            let tunnel = SixInFourTunnel::new(config)?;
2053            Ok(Box::new(tunnel))
2054        }
2055        TunnelProtocol::DsLite => {
2056            let tunnel = DsLiteTunnel::new(config)?;
2057            Ok(Box::new(tunnel))
2058        }
2059        TunnelProtocol::Isatap => {
2060            let tunnel = IsatapTunnel::new(config)?;
2061            Ok(Box::new(tunnel))
2062        }
2063        TunnelProtocol::MapE => {
2064            let tunnel = MapTunnel::new(config, MapProtocol::MapE)?;
2065            Ok(Box::new(tunnel))
2066        }
2067        TunnelProtocol::MapT => {
2068            let tunnel = MapTunnel::new(config, MapProtocol::MapT)?;
2069            Ok(Box::new(tunnel))
2070        }
2071    }
2072}