webrtc_util/vnet/
net.rs

1#[cfg(test)]
2mod net_test;
3
4use std::collections::HashMap;
5use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
6use std::str::FromStr;
7use std::sync::atomic::Ordering;
8use std::sync::Arc;
9
10use async_trait::async_trait;
11use ipnet::IpNet;
12use portable_atomic::AtomicU64;
13use tokio::net::UdpSocket;
14use tokio::sync::Mutex;
15
16use super::conn_map::*;
17use super::interface::*;
18use crate::error::*;
19use crate::vnet::chunk::Chunk;
20use crate::vnet::conn::{ConnObserver, UdpConn};
21use crate::vnet::router::*;
22use crate::{conn, ifaces, Conn};
23
24pub(crate) const LO0_STR: &str = "lo0";
25pub(crate) const UDP_STR: &str = "udp";
26
27lazy_static! {
28    pub static ref MAC_ADDR_COUNTER: AtomicU64 = AtomicU64::new(0xBEEFED910200);
29}
30
31pub(crate) type HardwareAddr = Vec<u8>;
32
33pub(crate) fn new_mac_address() -> HardwareAddr {
34    let b = MAC_ADDR_COUNTER
35        .fetch_add(1, Ordering::SeqCst)
36        .to_be_bytes();
37    b[2..].to_vec()
38}
39
40#[derive(Default)]
41pub(crate) struct VNetInternal {
42    pub(crate) interfaces: Vec<Interface>,         // read-only
43    pub(crate) router: Option<Arc<Mutex<Router>>>, // read-only
44    pub(crate) udp_conns: UdpConnMap,              // read-only
45}
46
47impl VNetInternal {
48    fn get_interface(&self, ifc_name: &str) -> Option<&Interface> {
49        self.interfaces.iter().find(|ifc| ifc.name == ifc_name)
50    }
51}
52
53#[async_trait]
54impl ConnObserver for VNetInternal {
55    async fn write(&self, c: Box<dyn Chunk + Send + Sync>) -> Result<()> {
56        if c.network() == UDP_STR && c.get_destination_ip().is_loopback() {
57            if let Some(conn) = self.udp_conns.find(&c.destination_addr()).await {
58                let read_ch_tx = conn.get_inbound_ch();
59                let ch_tx = read_ch_tx.lock().await;
60                if let Some(tx) = &*ch_tx {
61                    let _ = tx.send(c).await;
62                }
63            }
64            return Ok(());
65        }
66
67        if let Some(r) = &self.router {
68            let p = r.lock().await;
69            p.push(c).await;
70            Ok(())
71        } else {
72            Err(Error::ErrNoRouterLinked)
73        }
74    }
75
76    async fn on_closed(&self, addr: SocketAddr) {
77        let _ = self.udp_conns.delete(&addr).await;
78    }
79
80    // This method determines the srcIP based on the dstIP when locIP
81    // is any IP address ("0.0.0.0" or "::"). If locIP is a non-any addr,
82    // this method simply returns locIP.
83    // caller must hold the mutex
84    fn determine_source_ip(&self, loc_ip: IpAddr, dst_ip: IpAddr) -> Option<IpAddr> {
85        if !loc_ip.is_unspecified() {
86            return Some(loc_ip);
87        }
88
89        if dst_ip.is_loopback() {
90            let src_ip = if let Ok(src_ip) = IpAddr::from_str("127.0.0.1") {
91                Some(src_ip)
92            } else {
93                None
94            };
95            return src_ip;
96        }
97
98        if let Some(ifc) = self.get_interface("eth0") {
99            for ipnet in ifc.addrs() {
100                if (ipnet.addr().is_ipv4() && loc_ip.is_ipv4())
101                    || (ipnet.addr().is_ipv6() && loc_ip.is_ipv6())
102                {
103                    return Some(ipnet.addr());
104                }
105            }
106        }
107
108        None
109    }
110}
111
112#[derive(Default)]
113pub struct VNet {
114    pub(crate) interfaces: Vec<Interface>, // read-only
115    pub(crate) static_ips: Vec<IpAddr>,    // read-only
116    pub(crate) vi: Arc<Mutex<VNetInternal>>,
117}
118
119#[async_trait]
120impl Nic for VNet {
121    async fn get_interface(&self, ifc_name: &str) -> Option<Interface> {
122        for ifc in &self.interfaces {
123            if ifc.name == ifc_name {
124                return Some(ifc.clone());
125            }
126        }
127        None
128    }
129
130    async fn add_addrs_to_interface(&mut self, ifc_name: &str, addrs: &[IpNet]) -> Result<()> {
131        {
132            let mut vi = self.vi.lock().await;
133            for ifc in &mut vi.interfaces {
134                if ifc.name == ifc_name {
135                    for addr in addrs {
136                        ifc.add_addr(*addr);
137                    }
138                    break;
139                }
140            }
141        }
142
143        for ifc in &mut self.interfaces {
144            if ifc.name == ifc_name {
145                for addr in addrs {
146                    ifc.add_addr(*addr);
147                }
148                return Ok(());
149            }
150        }
151
152        Err(Error::ErrNotFound)
153    }
154
155    async fn set_router(&self, r: Arc<Mutex<Router>>) -> Result<()> {
156        let mut vi = self.vi.lock().await;
157        vi.router = Some(r);
158
159        Ok(())
160    }
161
162    async fn on_inbound_chunk(&self, c: Box<dyn Chunk + Send + Sync>) {
163        if c.network() == UDP_STR {
164            let vi = self.vi.lock().await;
165            if let Some(conn) = vi.udp_conns.find(&c.destination_addr()).await {
166                let read_ch_tx = conn.get_inbound_ch();
167                let ch_tx = read_ch_tx.lock().await;
168                if let Some(tx) = &*ch_tx {
169                    let _ = tx.send(c).await;
170                }
171            }
172        }
173    }
174
175    async fn get_static_ips(&self) -> Vec<IpAddr> {
176        self.static_ips.clone()
177    }
178}
179
180impl VNet {
181    pub(crate) fn get_interfaces(&self) -> &[Interface] {
182        &self.interfaces
183    }
184
185    // caller must hold the mutex
186    pub(crate) fn get_all_ipaddrs(&self, ipv6: bool) -> Vec<IpAddr> {
187        let mut ips = vec![];
188
189        for ifc in &self.interfaces {
190            for ipnet in ifc.addrs() {
191                if (ipv6 && ipnet.addr().is_ipv6()) || (!ipv6 && ipnet.addr().is_ipv4()) {
192                    ips.push(ipnet.addr());
193                }
194            }
195        }
196
197        ips
198    }
199
200    // caller must hold the mutex
201    pub(crate) fn has_ipaddr(&self, ip: IpAddr) -> bool {
202        for ifc in &self.interfaces {
203            for ipnet in ifc.addrs() {
204                let loc_ip = ipnet.addr();
205
206                match ip.to_string().as_str() {
207                    "0.0.0.0" => {
208                        if loc_ip.is_ipv4() {
209                            return true;
210                        }
211                    }
212                    "::" => {
213                        if loc_ip.is_ipv6() {
214                            return true;
215                        }
216                    }
217                    _ => {
218                        if loc_ip == ip {
219                            return true;
220                        }
221                    }
222                }
223            }
224        }
225
226        false
227    }
228
229    // caller must hold the mutex
230    pub(crate) async fn allocate_local_addr(&self, ip: IpAddr, port: u16) -> Result<()> {
231        // gather local IP addresses to bind
232        let mut ips = vec![];
233        if ip.is_unspecified() {
234            ips = self.get_all_ipaddrs(ip.is_ipv6());
235        } else if self.has_ipaddr(ip) {
236            ips.push(ip);
237        }
238
239        if ips.is_empty() {
240            return Err(Error::ErrBindFailed);
241        }
242
243        // check if all these transport addresses are not in use
244        for ip2 in ips {
245            let addr = SocketAddr::new(ip2, port);
246            let vi = self.vi.lock().await;
247            if vi.udp_conns.find(&addr).await.is_some() {
248                return Err(Error::ErrAddressAlreadyInUse);
249            }
250        }
251
252        Ok(())
253    }
254
255    // caller must hold the mutex
256    pub(crate) async fn assign_port(&self, ip: IpAddr, start: u16, end: u16) -> Result<u16> {
257        // choose randomly from the range between start and end (inclusive)
258        if end < start {
259            return Err(Error::ErrEndPortLessThanStart);
260        }
261
262        let space = end + 1 - start;
263        let offset = rand::random::<u16>() % space;
264        for i in 0..space {
265            let port = ((offset + i) % space) + start;
266            let result = self.allocate_local_addr(ip, port).await;
267            if result.is_ok() {
268                return Ok(port);
269            }
270        }
271
272        Err(Error::ErrPortSpaceExhausted)
273    }
274
275    pub(crate) async fn resolve_addr(&self, use_ipv4: bool, address: &str) -> Result<SocketAddr> {
276        let v: Vec<&str> = address.splitn(2, ':').collect();
277        if v.len() != 2 {
278            return Err(Error::ErrAddrNotUdpAddr);
279        }
280        let (host, port) = (v[0], v[1]);
281
282        // Check if host is a domain name
283        let ip: IpAddr = match host.parse() {
284            Ok(ip) => ip,
285            Err(_) => {
286                let host = host.to_lowercase();
287                if host == "localhost" {
288                    if use_ipv4 {
289                        Ipv4Addr::new(127, 0, 0, 1).into()
290                    } else {
291                        Ipv6Addr::from_str("::1")?.into()
292                    }
293                } else {
294                    // host is a domain name. resolve IP address by the name
295                    let vi = self.vi.lock().await;
296                    if let Some(router) = &vi.router {
297                        let r = router.lock().await;
298                        let resolver = r.resolver.lock().await;
299                        if let Some(ip) = resolver.lookup(host).await {
300                            ip
301                        } else {
302                            return Err(Error::ErrNotFound);
303                        }
304                    } else {
305                        return Err(Error::ErrNoRouterLinked);
306                    }
307                }
308            }
309        };
310
311        let port: u16 = port.parse()?;
312
313        let remote_addr = SocketAddr::new(ip, port);
314        if (use_ipv4 && remote_addr.is_ipv4()) || (!use_ipv4 && remote_addr.is_ipv6()) {
315            Ok(remote_addr)
316        } else {
317            Err(Error::Other(format!(
318                "No available {} IP address found!",
319                if use_ipv4 { "ipv4" } else { "ipv6" },
320            )))
321        }
322    }
323
324    // caller must hold the mutex
325    pub(crate) async fn bind(
326        &self,
327        mut local_addr: SocketAddr,
328    ) -> Result<Arc<dyn Conn + Send + Sync>> {
329        // validate address. do we have that address?
330        if !self.has_ipaddr(local_addr.ip()) {
331            return Err(Error::ErrCantAssignRequestedAddr);
332        }
333
334        if local_addr.port() == 0 {
335            // choose randomly from the range between 5000 and 5999
336            local_addr.set_port(self.assign_port(local_addr.ip(), 5000, 5999).await?);
337        } else {
338            let vi = self.vi.lock().await;
339            if vi.udp_conns.find(&local_addr).await.is_some() {
340                return Err(Error::ErrAddressAlreadyInUse);
341            }
342        }
343
344        let v = Arc::clone(&self.vi) as Arc<Mutex<dyn ConnObserver + Send + Sync>>;
345        let conn = Arc::new(UdpConn::new(local_addr, None, v));
346
347        {
348            let vi = self.vi.lock().await;
349            vi.udp_conns.insert(Arc::clone(&conn)).await?;
350        }
351
352        Ok(conn)
353    }
354
355    pub(crate) async fn dail(
356        &self,
357        use_ipv4: bool,
358        remote_addr: &str,
359    ) -> Result<Arc<dyn Conn + Send + Sync>> {
360        let rem_addr = self.resolve_addr(use_ipv4, remote_addr).await?;
361
362        // Determine source address
363        let src_ip = {
364            let vi = self.vi.lock().await;
365            let any_ip = if use_ipv4 {
366                Ipv4Addr::new(0, 0, 0, 0).into()
367            } else {
368                Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into()
369            };
370            if let Some(src_ip) = vi.determine_source_ip(any_ip, rem_addr.ip()) {
371                src_ip
372            } else {
373                any_ip
374            }
375        };
376
377        let loc_addr = SocketAddr::new(src_ip, 0);
378
379        let conn = self.bind(loc_addr).await?;
380        conn.connect(rem_addr).await?;
381
382        Ok(conn)
383    }
384}
385
386// NetConfig is a bag of configuration parameters passed to NewNet().
387#[derive(Debug, Default)]
388pub struct NetConfig {
389    // static_ips is an array of static IP addresses to be assigned for this Net.
390    // If no static IP address is given, the router will automatically assign
391    // an IP address.
392    pub static_ips: Vec<String>,
393
394    // static_ip is deprecated. Use static_ips.
395    pub static_ip: String,
396}
397
398// Net represents a local network stack equivalent to a set of layers from NIC
399// up to the transport (UDP / TCP) layer.
400pub enum Net {
401    VNet(Arc<Mutex<VNet>>),
402    Ifs(Vec<Interface>),
403}
404
405impl Net {
406    // NewNet creates an instance of Net.
407    // If config is nil, the virtual network is disabled. (uses corresponding
408    // net.Xxxx() operations.
409    // By design, it always have lo0 and eth0 interfaces.
410    // The lo0 has the address 127.0.0.1 assigned by default.
411    // IP address for eth0 will be assigned when this Net is added to a router.
412    pub fn new(config: Option<NetConfig>) -> Self {
413        if let Some(config) = config {
414            let mut lo0 = Interface::new(LO0_STR.to_owned(), vec![]);
415            if let Ok(ipnet) = Interface::convert(
416                SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 0),
417                Some(SocketAddr::new(Ipv4Addr::new(255, 0, 0, 0).into(), 0)),
418            ) {
419                lo0.add_addr(ipnet);
420            }
421
422            let eth0 = Interface::new("eth0".to_owned(), vec![]);
423
424            let mut static_ips = vec![];
425            for ip_str in &config.static_ips {
426                if let Ok(ip) = IpAddr::from_str(ip_str) {
427                    static_ips.push(ip);
428                }
429            }
430            if !config.static_ip.is_empty() {
431                if let Ok(ip) = IpAddr::from_str(&config.static_ip) {
432                    static_ips.push(ip);
433                }
434            }
435
436            let vnet = VNet {
437                interfaces: vec![lo0.clone(), eth0.clone()],
438                static_ips,
439                vi: Arc::new(Mutex::new(VNetInternal {
440                    interfaces: vec![lo0, eth0],
441                    router: None,
442                    udp_conns: UdpConnMap::new(),
443                })),
444            };
445
446            Net::VNet(Arc::new(Mutex::new(vnet)))
447        } else {
448            let interfaces = ifaces::ifaces().unwrap_or_default();
449
450            let mut m: HashMap<String, Vec<IpNet>> = HashMap::new();
451            for iface in interfaces {
452                if let Some(addrs) = m.get_mut(&iface.name) {
453                    if let Some(addr) = iface.addr {
454                        if let Ok(inet) = Interface::convert(addr, iface.mask) {
455                            addrs.push(inet);
456                        }
457                    }
458                } else if let Some(addr) = iface.addr {
459                    if let Ok(inet) = Interface::convert(addr, iface.mask) {
460                        m.insert(iface.name, vec![inet]);
461                    }
462                }
463            }
464
465            let mut ifs = vec![];
466            for (name, addrs) in m.into_iter() {
467                ifs.push(Interface::new(name, addrs));
468            }
469
470            Net::Ifs(ifs)
471        }
472    }
473
474    // Interfaces returns a list of the system's network interfaces.
475    pub async fn get_interfaces(&self) -> Vec<Interface> {
476        match self {
477            Net::VNet(vnet) => {
478                let net = vnet.lock().await;
479                net.get_interfaces().to_vec()
480            }
481            Net::Ifs(ifs) => ifs.clone(),
482        }
483    }
484
485    // InterfaceByName returns the interface specified by name.
486    pub async fn get_interface(&self, ifc_name: &str) -> Option<Interface> {
487        match self {
488            Net::VNet(vnet) => {
489                let net = vnet.lock().await;
490                net.get_interface(ifc_name).await
491            }
492            Net::Ifs(ifs) => {
493                for ifc in ifs {
494                    if ifc.name == ifc_name {
495                        return Some(ifc.clone());
496                    }
497                }
498                None
499            }
500        }
501    }
502
503    // IsVirtual tests if the virtual network is enabled.
504    pub fn is_virtual(&self) -> bool {
505        match self {
506            Net::VNet(_) => true,
507            Net::Ifs(_) => false,
508        }
509    }
510
511    pub async fn resolve_addr(&self, use_ipv4: bool, address: &str) -> Result<SocketAddr> {
512        match self {
513            Net::VNet(vnet) => {
514                let net = vnet.lock().await;
515                net.resolve_addr(use_ipv4, address).await
516            }
517            Net::Ifs(_) => Ok(conn::lookup_host(use_ipv4, address).await?),
518        }
519    }
520
521    pub async fn bind(&self, addr: SocketAddr) -> Result<Arc<dyn Conn + Send + Sync>> {
522        match self {
523            Net::VNet(vnet) => {
524                let net = vnet.lock().await;
525                net.bind(addr).await
526            }
527            Net::Ifs(_) => Ok(Arc::new(UdpSocket::bind(addr).await?)),
528        }
529    }
530
531    pub async fn dail(
532        &self,
533        use_ipv4: bool,
534        remote_addr: &str,
535    ) -> Result<Arc<dyn Conn + Send + Sync>> {
536        match self {
537            Net::VNet(vnet) => {
538                let net = vnet.lock().await;
539                net.dail(use_ipv4, remote_addr).await
540            }
541            Net::Ifs(_) => {
542                let any_ip = if use_ipv4 {
543                    Ipv4Addr::new(0, 0, 0, 0).into()
544                } else {
545                    Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).into()
546                };
547                let local_addr = SocketAddr::new(any_ip, 0);
548
549                let conn = UdpSocket::bind(local_addr).await?;
550                conn.connect(remote_addr).await?;
551
552                Ok(Arc::new(conn))
553            }
554        }
555    }
556
557    pub fn get_nic(&self) -> Result<Arc<Mutex<dyn Nic + Send + Sync>>> {
558        match self {
559            Net::VNet(vnet) => Ok(Arc::clone(vnet) as Arc<Mutex<dyn Nic + Send + Sync>>),
560            Net::Ifs(_) => Err(Error::ErrVnetDisabled),
561        }
562    }
563}