Commit Graph

20 Commits

Author SHA1 Message Date
Red Bear OS 3101345fe6 review: NDP state corruption fix, port double-free fix, observer limits
CRITICAL/MEDIUM BUGS FIXED:

1. ethernet.rs send_ndp_solicit: state corruption via recursive call
   The function destructured self.ndp_state by value (target, tries,
   silent_until) at the start and wrote back at the end. But between
   destructuring and writing back, self.drop_waiting_packets_v6(target)
   could recursively call self.send_ndp_solicit(Instant::ZERO) for a
   different target. The recursive call updated self.ndp_state with the
   new target's state. When control returned to the original frame, the
   original write-back clobbered the recursive call's state, silently
   losing neighbor discovery for the new target.
   Fix: use scoped pattern matches to read target/tries/silent_until
   from the live state right before they are needed, so the recursive
   call's writes are preserved. This matches the pattern used by
   send_arp (which uses ref mut and is correct).

2. scheme/socket.rs on_close: port double-free
   close_file() was called before the refcount check, so the port was
   released on every close. For a dup'd socket, the second close
   tried to release the port again — double-free.
   Fix: compute the new refcount first, only call close_file and
   remove from socket_set when the count reaches 0 (last reference).

3. scheme/tcp.rs new_socket: port + socket leak on connect failure
   If get_port() succeeded but connect() later failed, the port was
   claimed and the socket was added to socket_set, but new_socket
   returned Err. The caller (open_inner) did not insert the file
   handle, so on_close was never called. Both the port and the socket
   slot leaked.
   Fix: when connect() fails, release the auto-allocated port before
   returning. Explicit user-provided ports are still released by
   on_close when the last file is dropped (preserves the existing
   on_close-based release).

4. observer.rs capture: per-packet size limit not enforced
   Vec::with_capacity only pre-allocates; extend_from_slice copies the
   full packet. The intended per-packet limit (MAX_CAPTURE_BYTES /
   max_packets = 256 bytes) was being bypassed, allowing a single
   1500-byte packet to consume the full capture buffer.
   Fix: truncate to per_packet_limit before extending.

5. observer.rs capture: short packets bypassed filter
   Packets < 20 bytes returned true (capture anyway) regardless of
   the user's filter. A filter like 'tcp port 80' would capture all
   short packets, including non-TCP.
   Fix: return false (no match) for short packets. Filter semantics
   are now consistent: if a packet can't be matched, it's not captured.

All 29 existing tests still pass.
2026-07-09 00:42:46 +03:00
Red Bear OS baea0e523b review: 4 critical fixes (ICMP queue, refcount, udp panic, vlan send)
CRITICAL BUGS FIXED:

1. router/mod.rs: ICMP errors for Unreachable/Prohibit went to rx_buffer
   (infinite loop back to input) instead of tx_buffer (sent to source).
   Combined Unreachable/Prohibit arms; both now use tx_buffer.

2. scheme/socket.rs dup(): refcount leak in update_with branch.
   OLD code: new_handle.socket_handle() got +2 when update_with was
   Some, but only decremented once on close. Net: SH1 over-counted (+1),
   SH2 (new listening socket from update_with) never tracked at all.
   FIX: in update_with branch, increment refcount of 'socket_handle'
   (the new SH), not new_handle.socket_handle(). The always-run
   increment at the bottom covers new_handle. Both increments serve
   different purposes and are now distinct.

3. scheme/udp.rs: 4 .expect() panic vectors in bind/send/recv.
   'Can't bind', 'Can't send', 'Can't receive', 'Can't recieve' all
   panicked the daemon. Now return EIO via ? operator.

4. link/vlan.rs (and vxlan/gre/ipip already partially fixed in R42):
   send() pushed tagged packets into self.recv_queue, creating a
   self-loop where packets were never delivered. Now drops packets
   with a debug log since no parent device reference exists.

5. link/qdisc.rs: TokenBucket token_add could overflow u64 on long
   elapsed durations. Changed to saturating_mul.

DOC FIX:
6. filter/table.rs docstring example used --sport 1024:65535 (port
   range) but parse_port only accepts single port. Changed example to
   use single port value. Range support is a future enhancement.

All 29 existing tests still pass.
2026-07-09 00:29:46 +03:00
Red Bear OS efa24228e3 review: fix 5 panic/crash bugs + 1 off-by-2 + add 6 regression tests
CRITICAL BUGS FIXED:

1. STP build_bpdu runtime panic (link/stp.rs:121-123)
   - Duration::total_millis() returns i64, to_be_bytes() = [u8; 8]
   - But destination buffers (buf[29..31], buf[31..33], buf[33..35]) are 2 bytes
   - copy_from_slice panics on length mismatch
   - Triggered by every root bridge hello BPDU — daemon crash
   - Fix: convert to ticks (1s = 256 ticks per IEEE 802.1D) as u16

2. SLAAC PIO off-by-2 byte parsing (slaac.rs:155-180)
   - parse_router_advertisement used opt_data[2] for prefix length
   - After pos += 2 consumed type+length, opt_data[0] is the prefix length
   - All PIO fields were off by 2 — SLAAC got wrong prefix length, flags,
     valid_lifetime (read Preferred Lifetime), preferred_lifetime (read Reserved2)
   - Fix: use opt_data[0] for prefix length, [1] for flags, [2..6] for valid,
     [6..10] for preferred, [14..30] for prefix bytes

3. ICMPv4 error wrong IHL extraction (icmp_error.rs:25, 62)
   - (ipv4.version() & 0x0f) * 4 always computed 16
   - smoltcp's version() returns 4 (version), not combined byte
   - Fix: use ipv4.header_len()

4. UDP can_recv panic on port-only endpoint (scheme/udp.rs:54)
   - data.addr.unwrap() panics if addr is None (e.g. udp/:53)
   - is_specified() returns true when port is non-zero, even if addr is None
   - Fix: use let-else pattern, accept all packets if addr is None

5. TCP .expect() calls crash daemon (scheme/tcp.rs)
   - 5 .expect() calls in connect/listen/send/recv paths
   - Any socket error panics the entire netstack daemon
   - Fix: replace with .map_err() returning EIO

6. ICMP .unwrap() on malformed packets (scheme/icmp.rs:217-220)
   - recv().expect() panics, Icmpv4Repr::parse().unwrap() panics
   - Crafted/malformed ICMP packets would crash the daemon
   - Fix: use match, drop unparseable packets

NEW TESTS (6 added, 29 total now passing):
- icmp_error::icmpv4_short_packet_returns_none
- icmp_error::icmpv4_preserves_destination_address (regression for bug 3)
- icmp_error::icmpv4_with_ip_options_includes_extended_header
- slaac::ra_with_pio_64_parses_correctly (regression for bug 2)
- link::stp::bpdu_minimal_parses
- link::stp::bpdu_short_returns_none
- link::stp::bpdu_wrong_protocol_returns_none
- link::stp::build_bpdu_does_not_panic (regression for bug 1)

The SLAAC test would have failed before the off-by-2 fix.
The STP build_bpdu test would have panicked before the ticks fix.
The ICMP tests verify the full IP header (incl. IHL=6 options) is preserved.
2026-07-08 23:41:42 +03:00
Red Bear OS 596e73a92e bridge: 5 unit tests for FDB learn/age/lookup
Bridge MAC learning tests:
- learn_stores_unicast_mapping: stored MAC resolves on correct port
- learn_ignores_multicast: broadcast/multicast never enters FDB
- learn_replaces_existing_entry_on_new_port: MAC moves update port
- age_entries_removes_expired_macs: 300s timeout respected
- lookup_returns_none_for_unknown_mac: unknown MAC returns None

Total tests across netstack: 20 (5 table + 4 conntrack + 6 nat + 5 bridge)
All passing.
2026-07-08 21:20:32 +03:00
Red Bear OS 19199096c5 promiscuous: per-interface toggle via netcfg (ip link set promisc)
LinkDevice trait gains is_promiscuous() and set_promiscuous().
EthernetLink stores promiscuous flag (default: false).
Receive path bypasses MAC check when promiscuous enabled —
captures all frames regardless of destination MAC.

netcfg/ifaces/eth0/promiscuous rw:
  cat /scheme/netcfg/ifaces/eth0/promiscuous  →  'off' or 'on'
  echo on  > .../promiscuous  →  enable promiscuous mode
  echo off > .../promiscuous  →  disable

Accepts: on/off/1/0/yes/no/true/false.

Mirrors Linux 'ip link set dev promisc on/off'.
Required for packet capture tools that need to see all traffic.
2026-07-08 19:03:53 +03:00
Red Bear OS c899b42d36 arp: static ARP entry add/delete via netcfg (ip neigh add/del)
LinkDevice trait gains:
- add_static_neighbor(ip, mac) → Result<(), String>
- remove_neighbor(ip) → bool (true if removed)

EthernetLink implements both with permanent entries (expires_at = i64::MAX/2).

netcfg/ifaces/eth0/arp/ is now:
  list      → read (existing)
  stats     → read (existing)
  flush     → write (existing)
  add       → write  NEW
  del       → write  NEW

Usage:
  echo '192.168.1.1 00:11:22:33:44:55' > /scheme/netcfg/ifaces/eth0/arp/add
  echo '192.168.1.1' > /scheme/netcfg/ifaces/eth0/arp/del
  echo '10.0.0.0/24 gateway-01 11:22:33:44:55:66' > /scheme/netcfg/ifaces/eth0/arp/add

Mirrors Linux 'ip neigh add' / 'ip neigh del'.
MAC format accepts both colon (00:11:22:33:44:55) and dash (00-11-22-33-44-55).
Unicast MAC validation rejects broadcast/multicast addresses.
2026-07-08 18:49:40 +03:00
Red Bear OS 649ba27669 stats: track rx_errors (malformed ARP/frame) + tx_errors (network write fail)
All 4 RFC 1213 counters now wired to real events:
- rx_errors: malformed Ethernet frame or ARP packet
- tx_errors: network_file.write_all() failed
- rx_dropped: ARP/NDP neighbor resolution failed or queue full
- tx_dropped: qdisc returned None (rate-limit kicked in)

Stats output now reflects actual error/drop conditions.
Mirrors Linux's ifconfig/sar 'errors' and 'dropped' fields.
2026-07-08 18:42:57 +03:00
Red Bear OS 22d05e5f89 stats: actually track rx_dropped on neighbor-resolution failures
The new rx_dropped counter is now incremented in real drop paths:
- drop_waiting_packets_v4: ARP/NDP failed after MAX_TRIES, packets dropped
- drop_waiting_packets_v6: same for IPv6 neighbor discovery
- handle_missing_neighbor: waiting queue full, incoming packet dropped

Net effect: stats now reflect actual packet loss conditions visible
via /scheme/netcfg/ifaces/eth0/stats:
  rx_dropped=N  (was always 0 before)

tx_dropped was already incremented by qdisc drops (R24).
2026-07-08 18:39:28 +03:00
Red Bear OS 82d8a049cc stats: add rx_errors, tx_errors, rx_dropped, tx_dropped counters
Stats struct gains 4 new u64 fields per RFC 1213 (MIB-II):
- rx_errors: incoming packets with errors
- tx_errors: outgoing packets with errors
- rx_dropped: incoming packets dropped (buffer full, etc.)
- tx_dropped: outgoing packets dropped (qdisc dropped, buffer full)

EthernetLink tx path now increments tx_dropped when qdisc returns None
(qdisc decided to drop the packet, e.g., TokenBucket rate exceeded).

netcfg stats output now exposes all 8 counters:
  rx_bytes=N rx_packets=N tx_bytes=N tx_packets=N
  rx_errors=N tx_errors=N rx_dropped=N tx_dropped=N
  mtu=N link=up

Aggregate fields work for bridge/bond via existing sum logic.
2026-07-08 18:35:22 +03:00
Red Bear OS f3c18f410c qdisc: configure traffic shaping type via netcfg
LinkDevice trait gains set_qdisc(kind) — Result<(), String>.
EthernetLink supports three kinds:
  'none' / unset → QdiscConfig::None
  'token_bucket' / 'tbf' → 1 Mbps rate, 1500 byte burst
  'priority_queue' / 'pfifo_fast' → 1000 packet max

netcfg/ifaces/eth0/qdisc becomes rw:
  cat /scheme/netcfg/ifaces/eth0/qdisc    # current config
  echo token_bucket  > .../qdisc
  echo priority_queue > .../qdisc
  echo none > .../qdisc  (default)

Mirrors Linux 'tc qdisc add/replace' for basic shaping.
TokenBucket rate/burst defaults applied on creation;
set via tb.set_rate() / tb.set_burst() (already in qdisc.rs).
2026-07-08 18:26:47 +03:00
Red Bear OS 9bab466704 netcfg: interface enable/disable control (ip link set eth0 down/up)
LinkDevice trait gains is_enabled() and set_enabled() with defaults.
EthernetLink stores enabled flag (default: true). When disabled,
link_state() reports 'down' regardless of hardware_address presence.

netcfg/ifaces/eth0/enabled is rw:
  cat /scheme/netcfg/ifaces/eth0/enabled  →  'up' or 'down'
  echo up   > .../enabled  →  bring interface up
  echo down > .../enabled  →  bring interface down
  echo on/off/1/0/yes/no  →  also accepted

Mirrors Linux 'ip link set dev <state>'.

Pre-existing link state (hardware_address Some/None) unchanged;
the enabled flag adds a software override layer that can be
toggled without restarting the netstack.
2026-07-08 18:24:02 +03:00
Red Bear OS c015a375b1 mtu: per-interface MTU configuration via netcfg
LinkDevice trait gains set_mtu(mtu) with default no-op.
EthernetLink stores mtu in field, clamped to 576-9000 (RFC 791 min/max).

netcfg/ifaces/eth0/mtu becomes rw:
  cat /scheme/netcfg/ifaces/eth0/mtu  →  '1500' (default)
  echo 1400 > .../mtu  →  VPN MTU
  echo 9000 > .../mtu  →  jumbo frames

Clamped to [576, 9000]:
- 576: minimum for IPv4 (RFC 791)
- 9000: standard jumbo frame MTU

Useful for VPNs (MTU 1400 to avoid fragmentation through tunnel overhead),
jumbo frames (MTU 9000 on datacenter networks), and constrained paths.
2026-07-08 17:57:16 +03:00
Red Bear OS c1cfee3bea qdisc: expose traffic shaping info via netcfg and LinkDevice trait
LinkDevice gains qdisc_info() → String defaulting to 'none'.
EthernetLink reports current qdisc configuration:
  none  /  token_bucket rate=N burst=N tokens=N  /  priority_queue len=N max=N

TokenBucket and PriorityQueue gain public accessor methods:
  rate(), burst(), tokens() / max_len()

netcfg exposes at /scheme/netcfg/ifaces/eth0/qdisc:
  cat /scheme/netcfg/ifaces/eth0/qdisc  →  'none' (default)

Enables monitoring tools to discover current traffic shaping.
Future: wo node for configuring qdisc type + parameters.
2026-07-08 17:50:31 +03:00
Red Bear OS 998593f243 stats: add statistics() to bridge, bond, and tun devices
Bridge: statistics() aggregates rx/tx bytes+packets from all member ports.
arp_stats() delegates to each port, showing per-port breakdown.

Bond: statistics() aggregates from all slaves (active+standby).
arp_stats() delegates to each slave.

TUN: statistics() now returns live counters tracked during send()/recv().
rx_bytes, rx_packets, tx_bytes, tx_packets increment per-packet.

Previously these devices returned Stats::default() (all zeros).
Now netcfg /ifaces/*/stats shows real data for bridge, bond, tun.
2026-07-08 16:00:26 +03:00
Red Bear OS 27f8e351e6 arp: add statistics counters and netcfg exposure
EthernetLink gains per-interface ARP counters:
- arp_requests: ARP requests sent (incremented in send_arp)
- arp_replies: ARP replies received (incremented on cache insert)
- arp_cache_hits: successful neighbor cache lookups
- arp_cache_misses: cache misses (vacant or expired entries)

LinkDevice trait gains arp_stats() → String method.
EthernetLink implementation: 'requests=N replies=N hits=N misses=N entries=N'

netcfg exposes at /scheme/netcfg/ifaces/eth0/arp/stats:
  echo /scheme/netcfg/ifaces/eth0/arp/stats
  → requests=5 replies=3 hits=142 misses=8 entries=4

Existing arp/list (MAC→IP) and arp/flush (clear) are unchanged.
Useful for monitoring ARP churn, detecting ARP storms, and debugging
neighbor discovery issues.
2026-07-08 15:38:49 +03:00
Red Bear OS 107e3b6851 stp: enforce blocking on unicast send + enhanced stats display
BridgeDevice STP hardening:
- send(): check STP blocking before unicast forwarding (host-originated)
- recv(): check STP blocking before unicast forwarding (switched frames)
- Previously only flood() checked STP; unicast forwarding bypassed it.
  A blocked port must never forward any traffic — STP semantics now correct.

netcfg stats enhancement:
- Per-interface stats now include mtu= and link= fields alongside counters
- Applies to both eth0 and loopback
- Enables bandwidth monitoring tools to self-discover MTU/link state
2026-07-08 14:53:08 +03:00
Red Bear OS 30db94c970 stp: integrate 802.1D Spanning Tree Protocol into BridgeDevice
Adds loop prevention to Ethernet bridges:
- BridgeDevice gains stp: Option<StpState> field
- enable_stp(priority, mac) method initializes STP per-bridge
- BPDU frames (dst 01:80:c2:00:00:00) intercepted in recv(),
  processed locally, never forwarded
- STP hello timer sends periodic BPDUs on all ports (root bridge)
- flood() skips STP-blocked ports
- build_bpdu() made public for bridge integration
- stp module declared in link/mod.rs

The recv() flow now: age MACs → check STP hello timer →
poll ports → detect BPDU (absorb) → normal frame (learn + forward).

Reference: Linux 7.1 net/bridge/br_stp.c, br_stp_bpdu.c, br_stp_timer.c
2026-07-08 13:38:38 +03:00
Red Bear OS bb3e36e4e0 restore: networking stack files from reflog (Phases 1-6)
Recovered from reflog commits 1c80937e and d0ecc067 after force-push data loss.
Includes: filter/, icmp_error.rs, slaac.rs, bond.rs, bridge.rs, gre.rs, ipip.rs,
qdisc.rs, tun.rs, vlan.rs, vxlan.rs, netfilter.rs, tun.rs, conntrack.rs, nat.rs,
rule.rs, table.rs, redbear-ufw/, dhcpv6d/, netdiag/ — 39 files total.
2026-07-08 13:27:49 +03:00
Red Bear OS 4506bfe02a stp: add IEEE 802.1D Spanning Tree Protocol for bridge loop prevention 2026-07-08 13:26:39 +03:00
Red Bear OS dd08b76a39 Red Bear OS base baseline from 0.1.0 pre-patched archive 2026-06-27 09:21:43 +03:00