diff --git a/netstack/src/filter/table.rs b/netstack/src/filter/table.rs index 722bf3df7a..7ead7c842e 100644 --- a/netstack/src/filter/table.rs +++ b/netstack/src/filter/table.rs @@ -17,7 +17,7 @@ //! Examples: //! - `ACCEPT input -p tcp --dport 80` //! - `DROP input -s 10.0.0.0/8` -//! - `ACCEPT output -d 192.168.1.0/24 --sport 1024:65535` +//! - `ACCEPT output -d 192.168.1.0/24 --sport 1024` extern crate alloc; diff --git a/netstack/src/link/gre.rs b/netstack/src/link/gre.rs index 3970756478..293f506370 100644 --- a/netstack/src/link/gre.rs +++ b/netstack/src/link/gre.rs @@ -146,10 +146,9 @@ impl GreDevice { } impl LinkDevice for GreDevice { - fn send(&mut self, _next_hop: IpAddress, packet: &[u8], now: Instant) { - let encapsulated = self.build_encapsulated(packet).to_vec(); - self.push_received(encapsulated); - let _ = now; + fn send(&mut self, _next_hop: IpAddress, packet: &[u8], _now: Instant) { + // No parent device reference — drop rather than self-loop. + log::debug!("gre: dropping {} byte frame (no parent device)", packet.len()); } fn recv(&mut self, _now: Instant) -> Option<&[u8]> { diff --git a/netstack/src/link/ipip.rs b/netstack/src/link/ipip.rs index 7c9be17d8f..7c6b635bd4 100644 --- a/netstack/src/link/ipip.rs +++ b/netstack/src/link/ipip.rs @@ -80,10 +80,9 @@ impl IpipDevice { } impl LinkDevice for IpipDevice { - fn send(&mut self, _next_hop: IpAddress, packet: &[u8], now: Instant) { - let encapsulated = self.build_outer_header(packet).to_vec(); - self.push_received(encapsulated); - let _ = now; + fn send(&mut self, _next_hop: IpAddress, packet: &[u8], _now: Instant) { + // No parent device reference — drop rather than self-loop. + log::debug!("ipip: dropping {} byte frame (no parent device)", packet.len()); } fn recv(&mut self, _now: Instant) -> Option<&[u8]> { diff --git a/netstack/src/link/qdisc.rs b/netstack/src/link/qdisc.rs index edc78d0b82..dfe9864e8f 100644 --- a/netstack/src/link/qdisc.rs +++ b/netstack/src/link/qdisc.rs @@ -45,7 +45,11 @@ impl TokenBucket { pub fn consume(&mut self, bytes: u64, now: Instant) -> bool { let elapsed = now - self.last_update; if elapsed > Duration::ZERO { - let token_add = (self.rate * elapsed.total_millis() as u64) / 8000; + // Saturating mul: rate (bytes/s) * elapsed (ms) / 8000. + // saturating_mul prevents overflow on long elapsed durations. + let token_add = self.rate + .saturating_mul(elapsed.total_millis() as u64) + / 8000; self.tokens = (self.tokens + token_add).min(self.burst); self.last_update = now; } diff --git a/netstack/src/link/vlan.rs b/netstack/src/link/vlan.rs index c6824f26cd..3958712e85 100644 --- a/netstack/src/link/vlan.rs +++ b/netstack/src/link/vlan.rs @@ -117,10 +117,13 @@ impl VlanDevice { } impl LinkDevice for VlanDevice { - fn send(&mut self, next_hop: IpAddress, packet: &[u8], now: Instant) { - let tagged = self.insert_tag(packet).to_vec(); - self.push_received(tagged); - let _ = (next_hop, now); + fn send(&mut self, next_hop: IpAddress, packet: &[u8], _now: Instant) { + // The VLAN device has no parent device reference, so we cannot + // send the tagged frame out. Log and drop the packet rather than + // creating a self-loop (which would re-deliver the packet to + // recv() and never reach a real interface). + log::debug!("vlan: dropping {} byte frame (no parent device)", packet.len()); + let _ = next_hop; } fn recv(&mut self, _now: Instant) -> Option<&[u8]> { diff --git a/netstack/src/link/vxlan.rs b/netstack/src/link/vxlan.rs index 1383beb5a9..76f5007dac 100644 --- a/netstack/src/link/vxlan.rs +++ b/netstack/src/link/vxlan.rs @@ -176,10 +176,9 @@ impl VxlanDevice { } impl LinkDevice for VxlanDevice { - fn send(&mut self, _next_hop: IpAddress, packet: &[u8], now: Instant) { - let enc = self.build_encapsulated(packet).to_vec(); - self.push_received(enc); - let _ = now; + fn send(&mut self, _next_hop: IpAddress, packet: &[u8], _now: Instant) { + // No parent device reference — drop rather than self-loop. + log::debug!("vxlan: dropping {} byte frame (no parent device)", packet.len()); } fn recv(&mut self, _now: Instant) -> Option<&[u8]> { diff --git a/netstack/src/router/mod.rs b/netstack/src/router/mod.rs index 2a3eb21865..0936636d6e 100644 --- a/netstack/src/router/mod.rs +++ b/netstack/src/router/mod.rs @@ -135,16 +135,13 @@ impl Router { match route_type { RouteType::Blackhole => continue, - RouteType::Unreachable => { + RouteType::Unreachable | RouteType::Prohibit => { + // Build the ICMPv4 error and queue it for transmit + // back to the original sender. Using rx_buffer here + // would re-route the error back into the input path + // (infinite loop) and never reach the sender. if let Some(error_pkt) = icmp_error::build_icmpv4_port_unreachable(packet) { - let _ = self.rx_buffer.enqueue(error_pkt.len(), ()) - .map(|b| b.copy_from_slice(&error_pkt)); - } - continue; - } - RouteType::Prohibit => { - if let Some(error_pkt) = icmp_error::build_icmpv4_port_unreachable(packet) { - let _ = self.rx_buffer.enqueue(error_pkt.len(), ()) + let _ = self.tx_buffer.enqueue(error_pkt.len(), ()) .map(|b| b.copy_from_slice(&error_pkt)); } continue; diff --git a/netstack/src/scheme/socket.rs b/netstack/src/scheme/socket.rs index 2317288a3e..e73cb28777 100644 --- a/netstack/src/scheme/socket.rs +++ b/netstack/src/scheme/socket.rs @@ -834,22 +834,27 @@ where if let Some((socket_handle, data)) = update_with { if let SchemeFile::Socket(ref mut file) = *file { - // We replace the socket_handle pointed by file so update the ref_counts - // accordingly + // We replace the socket_handle pointed by file so update + // the ref_counts accordingly. self.ref_counts .entry(file.socket_handle) .and_modify(|e| *e = e.saturating_sub(1)) .or_insert(0); + // Increment refcount of the NEW socket (socket_handle) + // that the file is being updated to point at. *self .ref_counts - .entry(new_handle.socket_handle()) + .entry(socket_handle) .or_insert(0) += 1; file.socket_handle = socket_handle; file.data = data; } } + // Increment refcount for the new_handle fd being inserted. + // This is always done (regardless of update_with) because + // new_handle represents a new fd in the handle table. *self .ref_counts .entry(new_handle.socket_handle()) diff --git a/netstack/src/scheme/udp.rs b/netstack/src/scheme/udp.rs index d162d563a9..36e7b32074 100644 --- a/netstack/src/scheme/udp.rs +++ b/netstack/src/scheme/udp.rs @@ -178,7 +178,7 @@ impl<'a> SchemeSocket for UdpSocket<'a> { udp_socket .bind(local_endpoint) - .expect("Can't bind udp socket to local endpoint"); + .map_err(|_| SyscallError::new(syscall::EIO))?; Ok((socket_handle, remote_endpoint)) } @@ -213,7 +213,7 @@ impl<'a> SchemeSocket for UdpSocket<'a> { .expect("If we can send, this should be specified"), endpoint.port, ); - self.send_slice(buf, endpoint).expect("Can't send slice"); + self.send_slice(buf, endpoint).map_err(|_| SyscallError::new(syscall::EIO))?; Ok(buf.len()) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { Err(SyscallError::new(syscall::EAGAIN)) @@ -230,7 +230,7 @@ impl<'a> SchemeSocket for UdpSocket<'a> { if !file.read_enabled { Ok(0) } else if self.can_recv(&file.data) { - let (length, _) = self.recv_slice(buf).expect("Can't receive slice"); + let (length, _) = self.recv_slice(buf).map_err(|_| SyscallError::new(syscall::EIO))?; Ok(length) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { Err(SyscallError::new(syscall::EAGAIN)) @@ -358,7 +358,7 @@ impl<'a> SchemeSocket for UdpSocket<'a> { let mut payload_tmp = vec![0u8; prepared_whole_iov_size]; let (length, address) = self .recv_slice(&mut payload_tmp) - .expect("Can't recieve slice"); + .map_err(|_| SyscallError::new(syscall::EIO))?; //Address Handling let address_formatted = if prepared_name_len > 0 {