p2p_foundation/tunneling/
map.rs1use crate::tunneling::{Tunnel, TunnelConfig, TunnelState, TunnelMetrics, TunnelProtocol};
22use crate::{Result, P2PError};
23use async_trait::async_trait;
24use std::net::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr};
25use std::time::{Duration, Instant};
26use std::collections::HashMap;
27use tracing::{info, warn, debug};
28use tokio::net::UdpSocket;
29use serde::{Serialize, Deserialize};
30
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33pub enum MapProtocol {
34 MapE,
36 MapT,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct MapRule {
43 pub ipv6_prefix: Ipv6Addr,
45 pub ipv6_prefix_len: u8,
47 pub ipv4_prefix: Ipv4Addr,
49 pub ipv4_prefix_len: u8,
51 pub port_params: PortParameters,
53 pub border_relay: Option<Ipv6Addr>,
55 pub is_fmr: bool,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct PortParameters {
62 pub psid_offset: u8,
64 pub psid_length: u8,
66 pub excluded_ports: u16,
68}
69
70#[derive(Debug, Clone)]
72pub struct PortSet {
73 pub psid: u16,
75 pub start_port: u16,
77 pub port_count: u16,
79 pub available_ports: Vec<u16>,
81}
82
83pub struct MapTunnel {
85 protocol_variant: MapProtocol,
87 config: TunnelConfig,
89 state: TunnelState,
91 metrics: TunnelMetrics,
93 map_rules: Vec<MapRule>,
95 port_set: Option<PortSet>,
97 local_ipv4: Option<Ipv4Addr>,
99 assigned_ipv6: Option<Ipv6Addr>,
101 socket: Option<UdpSocket>,
103 border_relay: Option<Ipv6Addr>,
105 translation_table: HashMap<(Ipv4Addr, u16), (Ipv6Addr, u16)>,
107}
108
109impl MapTunnel {
110 pub fn new(config: TunnelConfig, protocol_variant: MapProtocol) -> Result<Self> {
112 match config.protocol {
113 TunnelProtocol::MapE if protocol_variant != MapProtocol::MapE => {
114 return Err(P2PError::Config("Protocol mismatch: expected MAP-E".to_string()));
115 }
116 TunnelProtocol::MapT if protocol_variant != MapProtocol::MapT => {
117 return Err(P2PError::Config("Protocol mismatch: expected MAP-T".to_string()));
118 }
119 TunnelProtocol::MapE | TunnelProtocol::MapT => {
120 }
122 _ => {
123 return Err(P2PError::Config("Invalid protocol for MAP tunnel".to_string()));
124 }
125 }
126
127 info!("Creating MAP tunnel: {:?}", protocol_variant);
128
129 Ok(Self {
130 protocol_variant,
131 config,
132 state: TunnelState::Disconnected,
133 metrics: TunnelMetrics::default(),
134 map_rules: Vec::new(),
135 port_set: None,
136 local_ipv4: None,
137 assigned_ipv6: None,
138 socket: None,
139 border_relay: None,
140 translation_table: HashMap::new(),
141 })
142 }
143
144 pub fn add_map_rule(&mut self, rule: MapRule) {
146 info!("Adding MAP rule: IPv6 prefix: {}/{}, IPv4 prefix: {}/{}",
147 rule.ipv6_prefix, rule.ipv6_prefix_len,
148 rule.ipv4_prefix, rule.ipv4_prefix_len);
149
150 if rule.border_relay.is_some() && self.protocol_variant == MapProtocol::MapE {
151 self.border_relay = rule.border_relay;
152 }
153
154 self.map_rules.push(rule);
155 }
156
157 pub fn calculate_ipv6_address(&self, ipv4_addr: Ipv4Addr, rule: &MapRule) -> Result<Ipv6Addr> {
159 let ipv4_bytes = ipv4_addr.octets();
161 let ipv4_suffix = u32::from_be_bytes(ipv4_bytes);
162
163 let host_bits = 32 - rule.ipv4_prefix_len;
165 let psid_bits = rule.port_params.psid_length;
166
167 if host_bits < psid_bits {
168 return Err(P2PError::Config("Invalid MAP rule: insufficient host bits for PSID".to_string()));
169 }
170
171 let psid_mask = (1u32 << psid_bits) - 1;
173 let psid_shift = host_bits - psid_bits;
174 let psid = (ipv4_suffix >> psid_shift) & psid_mask;
175
176 let prefix_bytes = rule.ipv6_prefix.octets();
178 let mut ipv6_bytes = [0u8; 16];
179
180 let prefix_len = rule.ipv6_prefix_len as usize / 8;
182 ipv6_bytes[..prefix_len].copy_from_slice(&prefix_bytes[..prefix_len]);
183
184 ipv6_bytes[prefix_len..prefix_len + 4].copy_from_slice(&ipv4_bytes);
186
187 if psid_bits > 0 {
189 let psid_bytes = (psid as u16).to_be_bytes();
190 ipv6_bytes[prefix_len + 4..prefix_len + 6].copy_from_slice(&psid_bytes);
191 }
192
193 Ok(Ipv6Addr::from(ipv6_bytes))
194 }
195
196 pub fn calculate_port_set(&self, psid: u16, rule: &MapRule) -> PortSet {
198 let port_params = &rule.port_params;
199
200 let total_ports = 65536u32;
202 let excluded_ports = port_params.excluded_ports as u32;
203 let ports_per_set = if port_params.psid_length > 0 {
204 ((total_ports - excluded_ports) >> port_params.psid_length) as u16
205 } else {
206 (total_ports - excluded_ports) as u16
207 };
208
209 let start_port = port_params.excluded_ports + (psid * ports_per_set);
210
211 let mut available_ports = Vec::new();
213 for i in 0..ports_per_set {
214 let port = start_port + i;
215 if port > 0 && port < 65535 {
216 available_ports.push(port);
217 }
218 }
219
220 PortSet {
221 psid,
222 start_port,
223 port_count: ports_per_set,
224 available_ports,
225 }
226 }
227
228 pub fn extract_psid(&self, ipv4_addr: Ipv4Addr, rule: &MapRule) -> u16 {
230 let ipv4_bytes = ipv4_addr.octets();
231 let ipv4_u32 = u32::from_be_bytes(ipv4_bytes);
232
233 let host_bits = 32 - rule.ipv4_prefix_len;
234 let psid_bits = rule.port_params.psid_length;
235
236 if psid_bits == 0 {
237 return 0;
238 }
239
240 let psid_mask = (1u32 << psid_bits) - 1;
241 let psid_shift = host_bits - psid_bits;
242
243 ((ipv4_u32 >> psid_shift) & psid_mask) as u16
244 }
245
246 pub async fn initialize_addresses(&mut self) -> Result<()> {
248 self.initialize_map().await
249 }
250
251 async fn initialize_map(&mut self) -> Result<()> {
253 if self.map_rules.is_empty() {
254 return Err(P2PError::Config("No MAP rules configured".to_string()));
255 }
256
257 let rule = &self.map_rules[0].clone();
259
260 let local_ipv4 = self.get_local_ipv4().await?;
262 self.local_ipv4 = Some(local_ipv4);
263
264 let ipv6_addr = self.calculate_ipv6_address(local_ipv4, rule)?;
266 self.assigned_ipv6 = Some(ipv6_addr);
267
268 let psid = self.extract_psid(local_ipv4, rule);
270 let port_set = self.calculate_port_set(psid, rule);
271 self.port_set = Some(port_set);
272
273 info!("MAP initialization complete: IPv4={}, IPv6={}, PSID={}",
274 local_ipv4, ipv6_addr, psid);
275
276 Ok(())
277 }
278
279 async fn get_local_ipv4(&self) -> Result<Ipv4Addr> {
281 if let Some(addr) = self.config.local_ipv4 {
282 return Ok(addr);
283 }
284
285 match tokio::net::UdpSocket::bind("0.0.0.0:0").await {
287 Ok(socket) => {
288 if socket.connect("8.8.8.8:53").await.is_ok() {
289 if let Ok(local_addr) = socket.local_addr() {
290 if let IpAddr::V4(ipv4) = local_addr.ip() {
291 return Ok(ipv4);
292 }
293 }
294 }
295 }
296 Err(e) => {
297 warn!("Failed to detect local IPv4 address: {}", e);
298 }
299 }
300
301 Err(P2PError::Network("Could not determine local IPv4 address".to_string()))
302 }
303
304 async fn create_socket(&mut self) -> Result<()> {
306 let local_ipv4 = self.local_ipv4.ok_or_else(|| {
307 P2PError::Config("Local IPv4 address not initialized".to_string())
308 })?;
309
310 let bind_addr = SocketAddr::new(IpAddr::V4(local_ipv4), 0);
311 let socket = UdpSocket::bind(bind_addr).await
312 .map_err(|e| P2PError::Network(format!("Failed to create MAP socket: {}", e)))?;
313
314 info!("Created MAP socket on: {}", socket.local_addr().unwrap());
315 self.socket = Some(socket);
316 Ok(())
317 }
318
319 pub fn encapsulate_ipv4_in_ipv6(&self, ipv4_packet: &[u8]) -> Result<Vec<u8>> {
321 if self.protocol_variant != MapProtocol::MapE {
322 return Err(P2PError::Transport("MAP-E encapsulation requires MAP-E protocol".to_string()));
323 }
324
325 if ipv4_packet.len() < 20 {
326 return Err(P2PError::Transport("IPv4 packet too short".to_string()));
327 }
328
329 let local_ipv6 = self.assigned_ipv6.ok_or_else(|| {
330 P2PError::Network("Local IPv6 address not available".to_string())
331 })?;
332
333 let border_relay = self.border_relay.ok_or_else(|| {
334 P2PError::Config("Border relay not configured".to_string())
335 })?;
336
337 let mut ipv6_packet = Vec::with_capacity(40 + ipv4_packet.len());
339
340 ipv6_packet.push(0x60); ipv6_packet.extend_from_slice(&[0x00, 0x00, 0x00]); ipv6_packet.extend_from_slice(&((ipv4_packet.len()) as u16).to_be_bytes()); ipv6_packet.push(4); ipv6_packet.push(64); ipv6_packet.extend_from_slice(&local_ipv6.octets()); ipv6_packet.extend_from_slice(&border_relay.octets()); ipv6_packet.extend_from_slice(ipv4_packet);
351
352 Ok(ipv6_packet)
353 }
354
355 pub fn translate_ipv4_to_ipv6(&mut self, ipv4_packet: &[u8]) -> Result<Vec<u8>> {
357 if self.protocol_variant != MapProtocol::MapT {
358 return Err(P2PError::Transport("MAP-T translation requires MAP-T protocol".to_string()));
359 }
360
361 if ipv4_packet.len() < 20 {
362 return Err(P2PError::Transport("IPv4 packet too short".to_string()));
363 }
364
365 let src_ipv4 = Ipv4Addr::from(<[u8; 4]>::try_from(&ipv4_packet[12..16]).unwrap());
367 let dst_ipv4 = Ipv4Addr::from(<[u8; 4]>::try_from(&ipv4_packet[16..20]).unwrap());
368
369 let protocol = ipv4_packet[9];
371 let (src_port, _dst_port) = if protocol == 6 || protocol == 17 { if ipv4_packet.len() >= 24 {
373 let src_port = u16::from_be_bytes([ipv4_packet[20], ipv4_packet[21]]);
374 let dst_port = u16::from_be_bytes([ipv4_packet[22], ipv4_packet[23]]);
375 (src_port, dst_port)
376 } else {
377 (0, 0)
378 }
379 } else {
380 (0, 0)
381 };
382
383 let rule = &self.map_rules[0]; let src_ipv6 = self.calculate_ipv6_address(src_ipv4, rule)?;
386 let dst_ipv6 = self.calculate_ipv6_address(dst_ipv4, rule)?;
387
388 self.translation_table.insert((src_ipv4, src_port), (src_ipv6, src_port));
390
391 let payload_len = ipv4_packet.len() - 20; let mut ipv6_packet = Vec::with_capacity(40 + payload_len);
394
395 ipv6_packet.push(0x60); ipv6_packet.extend_from_slice(&[0x00, 0x00, 0x00]); ipv6_packet.extend_from_slice(&(payload_len as u16).to_be_bytes()); ipv6_packet.push(protocol); ipv6_packet.push(64); ipv6_packet.extend_from_slice(&src_ipv6.octets()); ipv6_packet.extend_from_slice(&dst_ipv6.octets()); ipv6_packet.extend_from_slice(&ipv4_packet[20..]);
406
407 Ok(ipv6_packet)
408 }
409
410 pub fn is_port_allowed(&self, port: u16) -> bool {
412 if let Some(ref port_set) = self.port_set {
413 port_set.available_ports.contains(&port)
414 } else {
415 false
416 }
417 }
418}
419
420#[async_trait]
421impl Tunnel for MapTunnel {
422 fn protocol(&self) -> TunnelProtocol {
423 match self.protocol_variant {
424 MapProtocol::MapE => TunnelProtocol::MapE,
425 MapProtocol::MapT => TunnelProtocol::MapT,
426 }
427 }
428
429 fn config(&self) -> &TunnelConfig {
430 &self.config
431 }
432
433 async fn state(&self) -> TunnelState {
434 self.state.clone()
435 }
436
437 async fn metrics(&self) -> TunnelMetrics {
438 self.metrics.clone()
439 }
440
441 async fn connect(&mut self) -> Result<()> {
442 info!("Connecting MAP tunnel: {:?}", self.protocol_variant);
443 self.state = TunnelState::Connecting;
444
445 if let Err(e) = self.initialize_map().await {
447 self.state = TunnelState::Failed(format!("MAP initialization failed: {}", e));
448 return Err(e);
449 }
450
451 if let Err(e) = self.create_socket().await {
453 self.state = TunnelState::Failed(format!("Socket creation failed: {}", e));
454 return Err(e);
455 }
456
457 self.state = TunnelState::Connected;
458 info!("MAP tunnel connected successfully: {:?}", self.protocol_variant);
459 Ok(())
460 }
461
462 async fn is_active(&self) -> bool {
463 matches!(self.state, TunnelState::Connected)
464 }
465
466 async fn disconnect(&mut self) -> Result<()> {
467 info!("Disconnecting MAP tunnel");
468
469 if let Some(socket) = self.socket.take() {
470 drop(socket);
471 }
472
473 self.state = TunnelState::Disconnected;
474 self.translation_table.clear();
475 info!("MAP tunnel disconnected");
476 Ok(())
477 }
478
479 async fn encapsulate(&self, ipv4_packet: &[u8]) -> Result<Vec<u8>> {
480 if !self.is_active().await {
481 return Err(P2PError::Network("MAP tunnel not connected".to_string()));
482 }
483
484 match self.protocol_variant {
485 MapProtocol::MapE => self.encapsulate_ipv4_in_ipv6(ipv4_packet),
486 MapProtocol::MapT => {
487 Err(P2PError::Transport("MAP-T encapsulation requires mutable access".to_string()))
489 }
490 }
491 }
492
493 async fn decapsulate(&self, packet: &[u8]) -> Result<Vec<u8>> {
494 if !self.is_active().await {
495 return Err(P2PError::Network("MAP tunnel not connected".to_string()));
496 }
497
498 match self.protocol_variant {
499 MapProtocol::MapE => {
500 if packet.len() < 40 {
502 return Err(P2PError::Transport("IPv6 packet too short".to_string()));
503 }
504 if packet[6] != 4 { return Err(P2PError::Transport("Not an IPv4-in-IPv6 packet".to_string()));
506 }
507 Ok(packet[40..].to_vec())
508 }
509 MapProtocol::MapT => {
510 Err(P2PError::Transport("MAP-T decapsulation not implemented in immutable context".to_string()))
512 }
513 }
514 }
515
516 async fn send(&mut self, packet: &[u8]) -> Result<()> {
517 let socket = self.socket.as_ref().ok_or_else(|| {
518 P2PError::Network("MAP socket not available".to_string())
519 })?;
520
521 let dest_addr = match self.protocol_variant {
523 MapProtocol::MapE => {
524 let br = self.border_relay.ok_or_else(|| {
526 P2PError::Config("Border relay not configured".to_string())
527 })?;
528 SocketAddr::new(IpAddr::V6(br), 0)
529 }
530 MapProtocol::MapT => {
531 return Err(P2PError::Transport("MAP-T send not implemented".to_string()));
533 }
534 };
535
536 socket.send_to(packet, dest_addr).await
537 .map_err(|e| P2PError::Network(format!("Failed to send MAP packet: {}", e)))?;
538
539 self.metrics.packets_sent += 1;
540 self.metrics.bytes_sent += packet.len() as u64;
541 Ok(())
542 }
543
544 async fn receive(&mut self) -> Result<Vec<u8>> {
545 let socket = self.socket.as_ref().ok_or_else(|| {
546 P2PError::Network("MAP socket not available".to_string())
547 })?;
548
549 let mut buffer = vec![0u8; 1500];
550 let (size, _) = socket.recv_from(&mut buffer).await
551 .map_err(|e| P2PError::Network(format!("Failed to receive MAP packet: {}", e)))?;
552
553 buffer.truncate(size);
554 self.metrics.packets_received += 1;
555 self.metrics.bytes_received += size as u64;
556 Ok(buffer)
557 }
558
559 async fn maintain(&mut self) -> Result<()> {
560 debug!("MAP tunnel maintenance: translation table size: {}",
562 self.translation_table.len());
563
564 if self.translation_table.len() > 10000 {
566 warn!("MAP translation table growing large, consider cleanup");
567 }
569
570 Ok(())
571 }
572
573 async fn local_ipv6_addr(&self) -> Result<Ipv6Addr> {
574 self.assigned_ipv6.ok_or_else(|| {
575 P2PError::Network("Local IPv6 address not available".to_string())
576 })
577 }
578
579 async fn local_ipv4_addr(&self) -> Result<Ipv4Addr> {
580 self.local_ipv4.ok_or_else(|| {
581 P2PError::Network("Local IPv4 address not available".to_string())
582 })
583 }
584
585 async fn ping(&mut self, _timeout: Duration) -> Result<Duration> {
586 let start = Instant::now();
588
589 match self.protocol_variant {
590 MapProtocol::MapE => {
591 if self.border_relay.is_none() {
592 return Err(P2PError::Network("No border relay configured for ping".to_string()));
593 }
594 }
596 MapProtocol::MapT => {
597 }
600 }
601
602 tokio::time::sleep(Duration::from_millis(20)).await;
604 Ok(start.elapsed())
605 }
606}
607