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