ant_core/tunneling/
isatap.rs

1//! ISATAP (Intra-Site Automatic Tunnel Addressing Protocol) Implementation
2//!
3//! ISATAP provides automatic IPv6 connectivity over IPv4 infrastructure within
4//! enterprise networks. This implementation follows RFC 5214 and provides:
5//!
6//! - Automatic ISATAP address generation
7//! - ISATAP router discovery and Potential Router List (PRL) management
8//! - IPv6-in-IPv4 tunneling for enterprise environments
9//! - Integration with corporate network infrastructure
10//!
11//! ISATAP is particularly well-suited for:
12//! - Enterprise networks with existing IPv4 infrastructure
13//! - Corporate environments requiring IPv6 connectivity
14//! - P2P networks operating within organizational boundaries
15//! - Environments with dedicated ISATAP routers
16
17use crate::tunneling::{Tunnel, TunnelConfig, TunnelState, TunnelMetrics, TunnelProtocol};
18use crate::{Result, P2PError};
19use async_trait::async_trait;
20use std::net::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr};
21use std::time::{Duration, Instant, SystemTime};
22use tracing::{info, warn, debug};
23use tokio::net::UdpSocket;
24use serde::{Serialize, Deserialize};
25
26/// Default ISATAP interface identifier prefix (::0:5EFE:)
27const ISATAP_IID_PREFIX: u64 = 0x00005EFE;
28
29/// Default ISATAP router discovery interval
30const DEFAULT_ROUTER_DISCOVERY_INTERVAL: Duration = Duration::from_secs(300); // 5 minutes
31
32/// Maximum number of ISATAP routers in PRL
33const MAX_PRL_SIZE: usize = 10;
34
35/// ISATAP tunnel implementation
36/// 
37/// Provides IPv6 connectivity over IPv4 infrastructure using ISATAP protocol.
38/// Designed for enterprise environments with corporate network integration.
39pub struct IsatapTunnel {
40    /// Tunnel configuration
41    config: TunnelConfig,
42    /// Current tunnel state
43    state: TunnelState,
44    /// Performance and usage metrics
45    metrics: TunnelMetrics,
46    /// Local IPv4 address for tunnel endpoint
47    local_ipv4: Option<Ipv4Addr>,
48    /// Generated ISATAP IPv6 address
49    isatap_ipv6: Option<Ipv6Addr>,
50    /// UDP socket for tunnel communication
51    socket: Option<UdpSocket>,
52    /// Potential Router List (PRL) for ISATAP routers
53    potential_router_list: Vec<IsatapRouter>,
54    /// Last router discovery time
55    last_router_discovery: Option<Instant>,
56    /// Current active ISATAP router
57    active_router: Option<IsatapRouter>,
58}
59
60/// ISATAP router information
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct IsatapRouter {
63    /// Router IPv4 address
64    pub ipv4_addr: Ipv4Addr,
65    /// Router IPv6 prefix (if known)
66    pub ipv6_prefix: Option<Ipv6Addr>,
67    /// Router priority (lower = higher priority)
68    pub priority: u8,
69    /// Last successful communication time
70    pub last_seen: Option<SystemTime>,
71    /// Router reachability status
72    pub reachable: bool,
73    /// Round-trip time to router
74    pub rtt: Option<Duration>,
75}
76
77/// ISATAP router discovery method
78#[derive(Debug, Clone)]
79pub enum RouterDiscoveryMethod {
80    /// Use well-known DNS name (isatap.domain.com)
81    DnsWellKnown(String),
82    /// Use configured router addresses
83    ConfiguredList(Vec<Ipv4Addr>),
84    /// Use DHCP option (not implemented)
85    Dhcp,
86    /// Manual configuration
87    Manual(Vec<IsatapRouter>),
88}
89
90impl IsatapTunnel {
91    /// Create a new ISATAP tunnel
92    pub fn new(config: TunnelConfig) -> Result<Self> {
93        if config.protocol != TunnelProtocol::Isatap {
94            return Err(P2PError::Config(
95                "Invalid protocol for ISATAP tunnel".to_string()
96            ));
97        }
98
99        info!("Creating ISATAP tunnel for enterprise IPv6 connectivity");
100
101        Ok(Self {
102            config,
103            state: TunnelState::Disconnected,
104            metrics: TunnelMetrics::default(),
105            local_ipv4: None,
106            isatap_ipv6: None,
107            socket: None,
108            potential_router_list: Vec::new(),
109            last_router_discovery: None,
110            active_router: None,
111        })
112    }
113
114    /// Generate ISATAP IPv6 address from IPv4 address
115    /// 
116    /// ISATAP addresses use the format: prefix::0:5EFE:x.x.x.x
117    /// where x.x.x.x is the IPv4 address in hexadecimal
118    pub fn generate_isatap_address(ipv4_addr: Ipv4Addr, prefix: Option<Ipv6Addr>) -> Ipv6Addr {
119        let prefix = prefix.unwrap_or_else(|| "fe80::".parse().unwrap());
120        
121        // Convert IPv4 to the ISATAP interface identifier
122        let ipv4_bytes = ipv4_addr.octets();
123        let ipv4_u32 = u32::from_be_bytes(ipv4_bytes);
124        
125        // Create ISATAP interface identifier: ::0:5EFE:x.x.x.x
126        let iid_high = ISATAP_IID_PREFIX;
127        // Interface identifier low part is included in ipv4_u32
128        
129        // Combine prefix with ISATAP interface identifier
130        let prefix_bytes = prefix.octets();
131        let mut addr_bytes = [0u8; 16];
132        
133        // Copy prefix (first 8 bytes)
134        addr_bytes[..8].copy_from_slice(&prefix_bytes[..8]);
135        
136        // Set ISATAP interface identifier
137        addr_bytes[8..12].copy_from_slice(&iid_high.to_be_bytes()[4..]);
138        addr_bytes[12..16].copy_from_slice(&ipv4_u32.to_be_bytes());
139        
140        Ipv6Addr::from(addr_bytes)
141    }
142
143    /// Validate if an IPv6 address is a valid ISATAP address
144    pub fn is_isatap_address(addr: Ipv6Addr) -> bool {
145        let segments = addr.segments();
146        // Check for ISATAP interface identifier: xxxx:xxxx:xxxx:xxxx:0000:5EFE:xxxx:xxxx
147        segments[4] == 0x0000 && segments[5] == 0x5EFE
148    }
149
150    /// Extract IPv4 address from ISATAP IPv6 address
151    pub fn extract_ipv4_from_isatap(addr: Ipv6Addr) -> Option<Ipv4Addr> {
152        if !Self::is_isatap_address(addr) {
153            return None;
154        }
155
156        let segments = addr.segments();
157        let ipv4_bytes = [
158            ((segments[6] >> 8) & 0xFF) as u8,
159            (segments[6] & 0xFF) as u8,
160            ((segments[7] >> 8) & 0xFF) as u8,
161            (segments[7] & 0xFF) as u8,
162        ];
163
164        Some(Ipv4Addr::from(ipv4_bytes))
165    }
166
167    /// Discover ISATAP routers using various methods
168    pub async fn discover_routers(&mut self, method: RouterDiscoveryMethod) -> Result<Vec<IsatapRouter>> {
169        info!("Discovering ISATAP routers using: {:?}", method);
170
171        let discovered_routers = match method {
172            RouterDiscoveryMethod::DnsWellKnown(domain) => {
173                self.discover_routers_dns(&domain).await?
174            }
175            RouterDiscoveryMethod::ConfiguredList(addresses) => {
176                self.create_routers_from_addresses(addresses)
177            }
178            RouterDiscoveryMethod::Manual(routers) => routers,
179            RouterDiscoveryMethod::Dhcp => {
180                warn!("DHCP router discovery not yet implemented");
181                Vec::new()
182            }
183        };
184
185        // Update PRL with discovered routers
186        self.update_potential_router_list(discovered_routers.clone());
187        self.last_router_discovery = Some(Instant::now());
188
189        info!("Discovered {} ISATAP routers", discovered_routers.len());
190        Ok(discovered_routers)
191    }
192
193    /// Discover ISATAP routers via DNS
194    async fn discover_routers_dns(&self, domain: &str) -> Result<Vec<IsatapRouter>> {
195        let isatap_hostname = format!("isatap.{}", domain);
196        debug!("Looking up ISATAP router at: {}", isatap_hostname);
197
198        match tokio::net::lookup_host(format!("{}:80", isatap_hostname)).await {
199            Ok(addrs) => {
200                let mut routers = Vec::new();
201                for addr in addrs {
202                    if let IpAddr::V4(ipv4) = addr.ip() {
203                        routers.push(IsatapRouter {
204                            ipv4_addr: ipv4,
205                            ipv6_prefix: None,
206                            priority: 10, // Default priority
207                            last_seen: None,
208                            reachable: false,
209                            rtt: None,
210                        });
211                    }
212                }
213                Ok(routers)
214            }
215            Err(e) => {
216                warn!("Failed to resolve ISATAP router '{}': {}", isatap_hostname, e);
217                Ok(Vec::new())
218            }
219        }
220    }
221
222    /// Create router entries from IPv4 addresses
223    fn create_routers_from_addresses(&self, addresses: Vec<Ipv4Addr>) -> Vec<IsatapRouter> {
224        addresses.into_iter().enumerate().map(|(i, addr)| {
225            IsatapRouter {
226                ipv4_addr: addr,
227                ipv6_prefix: None,
228                priority: i as u8,
229                last_seen: None,
230                reachable: false,
231                rtt: None,
232            }
233        }).collect()
234    }
235
236    /// Update Potential Router List (PRL)
237    fn update_potential_router_list(&mut self, new_routers: Vec<IsatapRouter>) {
238        // Merge with existing PRL, avoiding duplicates
239        for new_router in new_routers {
240            if !self.potential_router_list.iter().any(|r| r.ipv4_addr == new_router.ipv4_addr) {
241                self.potential_router_list.push(new_router);
242            }
243        }
244
245        // Sort by priority and limit size
246        self.potential_router_list.sort_by_key(|r| r.priority);
247        self.potential_router_list.truncate(MAX_PRL_SIZE);
248
249        debug!("Updated PRL with {} routers", self.potential_router_list.len());
250    }
251
252    /// Test reachability of ISATAP router
253    pub async fn test_router_reachability(&self, router: &IsatapRouter) -> Result<Duration> {
254        let target = format!("{}:80", router.ipv4_addr);
255        let start = Instant::now();
256
257        match tokio::time::timeout(Duration::from_secs(5), tokio::net::TcpStream::connect(&target)).await {
258            Ok(Ok(_)) => {
259                let rtt = start.elapsed();
260                debug!("ISATAP router {} reachable, RTT: {:?}", router.ipv4_addr, rtt);
261                Ok(rtt)
262            }
263            Ok(Err(e)) => {
264                debug!("ISATAP router {} unreachable: {}", router.ipv4_addr, e);
265                Err(P2PError::Network(format!("Router unreachable: {}", e)))
266            }
267            Err(_) => {
268                debug!("ISATAP router {} timeout", router.ipv4_addr);
269                Err(P2PError::Network("Router reachability timeout".to_string()))
270            }
271        }
272    }
273
274    /// Select best ISATAP router from PRL
275    pub async fn select_router(&mut self) -> Result<IsatapRouter> {
276        if self.potential_router_list.is_empty() {
277            return Err(P2PError::Config("No ISATAP routers available".to_string()));
278        }
279
280        info!("Selecting best ISATAP router from {} candidates", self.potential_router_list.len());
281
282        // Test reachability and select best router
283        let mut best_router = None;
284        let mut best_rtt = Duration::from_secs(u64::MAX);
285
286        // Test each router and collect results
287        let mut test_results = Vec::new();
288        for (i, router) in self.potential_router_list.iter().enumerate() {
289            let rtt_result = self.test_router_reachability(router).await;
290            test_results.push((i, rtt_result));
291        }
292
293        // Update router states and find best
294        for (i, rtt_result) in test_results {
295            let router = &mut self.potential_router_list[i];
296            match rtt_result {
297                Ok(rtt) => {
298                    router.reachable = true;
299                    router.rtt = Some(rtt);
300                    router.last_seen = Some(SystemTime::now());
301
302                    if rtt < best_rtt {
303                        best_rtt = rtt;
304                        best_router = Some(router.clone());
305                    }
306                }
307                Err(_) => {
308                    router.reachable = false;
309                    router.rtt = None;
310                }
311            }
312        }
313
314        match best_router {
315            Some(router) => {
316                info!("Selected ISATAP router: {} (RTT: {:?})", router.ipv4_addr, router.rtt);
317                self.active_router = Some(router.clone());
318                Ok(router)
319            }
320            None => Err(P2PError::Network("No reachable ISATAP routers found".to_string()))
321        }
322    }
323
324    /// Initialize local IPv4 address and generate ISATAP address
325    pub async fn initialize_addresses(&mut self) -> Result<()> {
326        // Get local IPv4 address
327        let local_ipv4 = self.get_local_ipv4().await?;
328        self.local_ipv4 = Some(local_ipv4);
329
330        // Generate ISATAP IPv6 address
331        let prefix = self.get_ipv6_prefix();
332        let isatap_addr = Self::generate_isatap_address(local_ipv4, prefix);
333        self.isatap_ipv6 = Some(isatap_addr);
334
335        info!("Initialized ISATAP addresses: IPv4={}, IPv6={}", local_ipv4, isatap_addr);
336        Ok(())
337    }
338
339    /// Get local IPv4 address for ISATAP tunnel
340    async fn get_local_ipv4(&self) -> Result<Ipv4Addr> {
341        // Try to get configured local address
342        if let Some(addr) = self.config.local_ipv4 {
343            return Ok(addr);
344        }
345
346        // Auto-detect local IPv4 address by connecting to a remote address
347        match tokio::net::UdpSocket::bind("0.0.0.0:0").await {
348            Ok(socket) => {
349                // Connect to well-known address to determine local interface
350                if socket.connect("8.8.8.8:53").await.is_ok() {
351                    if let Ok(local_addr) = socket.local_addr() {
352                        if let IpAddr::V4(ipv4) = local_addr.ip() {
353                            return Ok(ipv4);
354                        }
355                    }
356                }
357            }
358            Err(e) => {
359                warn!("Failed to auto-detect local IPv4: {}", e);
360            }
361        }
362
363        Err(P2PError::Network("Could not determine local IPv4 address".to_string()))
364    }
365
366    /// Get IPv6 prefix for ISATAP address generation
367    fn get_ipv6_prefix(&self) -> Option<Ipv6Addr> {
368        self.config.ipv6_prefix.or_else(|| {
369            // Use link-local prefix as default
370            Some("fe80::".parse().unwrap())
371        })
372    }
373
374    /// Create UDP socket for tunnel communication
375    async fn create_socket(&mut self) -> Result<()> {
376        let local_ipv4 = self.local_ipv4.ok_or_else(|| {
377            P2PError::Config("Local IPv4 address not initialized".to_string())
378        })?;
379
380        let bind_addr = SocketAddr::new(IpAddr::V4(local_ipv4), 0);
381        let socket = UdpSocket::bind(bind_addr).await
382            .map_err(|e| P2PError::Network(format!("Failed to create ISATAP socket: {}", e)))?;
383
384        info!("Created ISATAP socket on: {}", socket.local_addr().unwrap());
385        self.socket = Some(socket);
386        Ok(())
387    }
388
389    /// Encapsulate IPv6 packet in IPv4 for ISATAP tunnel
390    pub fn encapsulate_ipv6_in_ipv4(&self, ipv6_packet: &[u8], dest_ipv4: Ipv4Addr) -> Result<Vec<u8>> {
391        if ipv6_packet.len() < 40 {
392            return Err(P2PError::Transport("IPv6 packet too short".to_string()));
393        }
394
395        // Verify it's an IPv6 packet
396        if (ipv6_packet[0] & 0xF0) != 0x60 {
397            return Err(P2PError::Transport("Not an IPv6 packet".to_string()));
398        }
399
400        let local_ipv4 = self.local_ipv4.ok_or_else(|| {
401            P2PError::Network("Local IPv4 address not available".to_string())
402        })?;
403
404        // Create IPv4 header for encapsulation
405        let mut ipv4_packet = Vec::with_capacity(20 + ipv6_packet.len());
406        
407        // IPv4 header (20 bytes)
408        ipv4_packet.push(0x45); // Version=4, IHL=5
409        ipv4_packet.push(0x00); // Type of Service
410        ipv4_packet.extend_from_slice(&((20 + ipv6_packet.len()) as u16).to_be_bytes()); // Total Length
411        ipv4_packet.extend_from_slice(&[0x00, 0x00]); // Identification
412        ipv4_packet.extend_from_slice(&[0x40, 0x00]); // Flags=DF, Fragment Offset=0
413        ipv4_packet.push(64); // TTL
414        ipv4_packet.push(41); // Protocol = IPv6
415        ipv4_packet.extend_from_slice(&[0x00, 0x00]); // Header Checksum (will calculate)
416        ipv4_packet.extend_from_slice(&local_ipv4.octets()); // Source IP
417        ipv4_packet.extend_from_slice(&dest_ipv4.octets()); // Destination IP
418
419        // Calculate and set checksum
420        let checksum = Self::calculate_ipv4_checksum(&ipv4_packet);
421        ipv4_packet[10..12].copy_from_slice(&checksum.to_be_bytes());
422
423        // Append IPv6 payload
424        ipv4_packet.extend_from_slice(ipv6_packet);
425
426        Ok(ipv4_packet)
427    }
428
429    /// Decapsulate IPv4 packet to extract IPv6 payload
430    pub fn decapsulate_ipv4_to_ipv6(&self, ipv4_packet: &[u8]) -> Result<Vec<u8>> {
431        if ipv4_packet.len() < 20 {
432            return Err(P2PError::Transport("IPv4 packet too short".to_string()));
433        }
434
435        // Verify IPv4 header
436        if (ipv4_packet[0] & 0xF0) != 0x40 {
437            return Err(P2PError::Transport("Not an IPv4 packet".to_string()));
438        }
439
440        // Check protocol field for IPv6 (41)
441        if ipv4_packet[9] != 41 {
442            return Err(P2PError::Transport("IPv4 packet does not contain IPv6".to_string()));
443        }
444
445        // Extract IPv4 header length
446        let ihl = (ipv4_packet[0] & 0x0F) as usize * 4;
447        if ipv4_packet.len() <= ihl {
448            return Err(P2PError::Transport("IPv4 header length invalid".to_string()));
449        }
450
451        // Extract IPv6 payload
452        let ipv6_packet = ipv4_packet[ihl..].to_vec();
453
454        // Verify IPv6 packet
455        if ipv6_packet.is_empty() || (ipv6_packet[0] & 0xF0) != 0x60 {
456            return Err(P2PError::Transport("Invalid IPv6 payload".to_string()));
457        }
458
459        Ok(ipv6_packet)
460    }
461
462    /// Calculate IPv4 header checksum
463    fn calculate_ipv4_checksum(header: &[u8]) -> u16 {
464        let mut sum: u32 = 0;
465        
466        // Sum all 16-bit words in header (except checksum field)
467        for i in (0..20).step_by(2) {
468            if i == 10 { continue; } // Skip checksum field
469            
470            let word = if i + 1 < header.len() {
471                u16::from_be_bytes([header[i], header[i + 1]])
472            } else {
473                u16::from_be_bytes([header[i], 0])
474            };
475            sum += word as u32;
476        }
477        
478        // Add carry bits
479        while (sum >> 16) != 0 {
480            sum = (sum & 0xFFFF) + (sum >> 16);
481        }
482        
483        // One's complement
484        !sum as u16
485    }
486}
487
488#[async_trait]
489impl Tunnel for IsatapTunnel {
490    fn protocol(&self) -> TunnelProtocol {
491        TunnelProtocol::Isatap
492    }
493
494    fn config(&self) -> &TunnelConfig {
495        &self.config
496    }
497
498    async fn state(&self) -> TunnelState {
499        self.state.clone()
500    }
501
502    async fn metrics(&self) -> TunnelMetrics {
503        self.metrics.clone()
504    }
505
506    async fn connect(&mut self) -> Result<()> {
507        info!("Connecting ISATAP tunnel for enterprise IPv6 connectivity");
508        self.state = TunnelState::Connecting;
509
510        // Initialize local addresses
511        if let Err(e) = self.initialize_addresses().await {
512            self.state = TunnelState::Failed(format!("Address initialization failed: {}", e));
513            return Err(e);
514        }
515
516        // Discover ISATAP routers
517        let discovery_method = if let Some(domain) = std::env::var("ISATAP_DOMAIN").ok() {
518            RouterDiscoveryMethod::DnsWellKnown(domain)
519        } else {
520            // Use well-known corporate addresses as fallback
521            RouterDiscoveryMethod::ConfiguredList(vec![
522                "192.168.1.1".parse().unwrap(),
523                "10.0.0.1".parse().unwrap(),
524            ])
525        };
526
527        if let Err(e) = self.discover_routers(discovery_method).await {
528            warn!("Router discovery failed: {}", e);
529        }
530
531        // Select best router
532        if self.select_router().await.is_err() {
533            warn!("No ISATAP router available, operating in host-to-host mode");
534        }
535
536        // Create tunnel socket
537        if let Err(e) = self.create_socket().await {
538            self.state = TunnelState::Failed(format!("Socket creation failed: {}", e));
539            return Err(e);
540        }
541
542        self.state = TunnelState::Connected;
543        info!("ISATAP tunnel connected successfully");
544        Ok(())
545    }
546
547    async fn is_active(&self) -> bool {
548        matches!(self.state, TunnelState::Connected)
549    }
550
551    async fn disconnect(&mut self) -> Result<()> {
552        info!("Disconnecting ISATAP tunnel");
553        
554        if let Some(socket) = self.socket.take() {
555            drop(socket);
556        }
557
558        self.state = TunnelState::Disconnected;
559        self.active_router = None;
560        info!("ISATAP tunnel disconnected");
561        Ok(())
562    }
563
564    async fn encapsulate(&self, ipv6_packet: &[u8]) -> Result<Vec<u8>> {
565        if !self.is_active().await {
566            return Err(P2PError::Network("ISATAP tunnel not connected".to_string()));
567        }
568
569        // Determine destination IPv4 address
570        let dest_ipv4 = if let Some(router) = &self.active_router {
571            router.ipv4_addr
572        } else {
573            // Try to extract from destination IPv6 address
574            if ipv6_packet.len() >= 40 {
575                let dest_ipv6_bytes = &ipv6_packet[24..40];
576                let dest_ipv6 = Ipv6Addr::from(<[u8; 16]>::try_from(dest_ipv6_bytes).unwrap());
577                
578                if let Some(ipv4) = Self::extract_ipv4_from_isatap(dest_ipv6) {
579                    ipv4
580                } else {
581                    return Err(P2PError::Network("No route to IPv6 destination".to_string()));
582                }
583            } else {
584                return Err(P2PError::Transport("IPv6 packet too short".to_string()));
585            }
586        };
587
588        self.encapsulate_ipv6_in_ipv4(ipv6_packet, dest_ipv4)
589    }
590
591    async fn decapsulate(&self, ipv4_packet: &[u8]) -> Result<Vec<u8>> {
592        if !self.is_active().await {
593            return Err(P2PError::Network("ISATAP tunnel not connected".to_string()));
594        }
595
596        self.decapsulate_ipv4_to_ipv6(ipv4_packet)
597    }
598
599    async fn send(&mut self, packet: &[u8]) -> Result<()> {
600        let socket = self.socket.as_ref().ok_or_else(|| {
601            P2PError::Network("ISATAP socket not available".to_string())
602        })?;
603
604        // For ISATAP, we need to determine the destination from the packet
605        if packet.len() < 20 {
606            return Err(P2PError::Transport("Packet too short".to_string()));
607        }
608
609        // Extract destination IPv4 address from packet header
610        let dest_bytes = &packet[16..20];
611        let dest_addr = Ipv4Addr::from(<[u8; 4]>::try_from(dest_bytes).unwrap());
612        let dest_port = 41; // IPv6-in-IPv4 doesn't use ports, but UDP requires one
613
614        socket.send_to(packet, (dest_addr, dest_port)).await
615            .map_err(|e| P2PError::Network(format!("Failed to send packet: {}", e)))?;
616
617        self.metrics.packets_sent += 1;
618        self.metrics.bytes_sent += packet.len() as u64;
619        Ok(())
620    }
621
622    async fn receive(&mut self) -> Result<Vec<u8>> {
623        let socket = self.socket.as_ref().ok_or_else(|| {
624            P2PError::Network("ISATAP socket not available".to_string())
625        })?;
626
627        let mut buffer = vec![0u8; 1500]; // Standard MTU
628        let (size, _) = socket.recv_from(&mut buffer).await
629            .map_err(|e| P2PError::Network(format!("Failed to receive packet: {}", e)))?;
630
631        buffer.truncate(size);
632        self.metrics.packets_received += 1;
633        self.metrics.bytes_received += size as u64;
634        Ok(buffer)
635    }
636
637    async fn maintain(&mut self) -> Result<()> {
638        // Periodically rediscover routers
639        if let Some(last_discovery) = self.last_router_discovery {
640            if last_discovery.elapsed() > DEFAULT_ROUTER_DISCOVERY_INTERVAL {
641                debug!("Performing periodic ISATAP router discovery");
642                
643                let discovery_method = RouterDiscoveryMethod::DnsWellKnown(
644                    std::env::var("ISATAP_DOMAIN").unwrap_or_else(|_| "corp.local".to_string())
645                );
646                
647                if let Err(e) = self.discover_routers(discovery_method).await {
648                    warn!("Periodic router discovery failed: {}", e);
649                }
650            }
651        }
652
653        // Test active router reachability
654        if let Some(router) = &self.active_router {
655            if let Err(_) = self.test_router_reachability(router).await {
656                warn!("Active ISATAP router {} became unreachable", router.ipv4_addr);
657                self.active_router = None;
658                
659                // Try to select new router
660                if let Err(e) = self.select_router().await {
661                    warn!("Failed to select new ISATAP router: {}", e);
662                }
663            }
664        }
665
666        Ok(())
667    }
668
669    async fn local_ipv6_addr(&self) -> Result<Ipv6Addr> {
670        self.isatap_ipv6.ok_or_else(|| {
671            P2PError::Network("ISATAP IPv6 address not available".to_string())
672        })
673    }
674
675    async fn local_ipv4_addr(&self) -> Result<Ipv4Addr> {
676        self.local_ipv4.ok_or_else(|| {
677            P2PError::Network("Local IPv4 address not available".to_string())
678        })
679    }
680
681    async fn ping(&mut self, _timeout: Duration) -> Result<Duration> {
682        let router = self.active_router.as_ref().ok_or_else(|| {
683            P2PError::Network("No active ISATAP router for ping".to_string())
684        })?;
685
686        self.test_router_reachability(router).await
687    }
688}