# barox Virtual Switch Simulator

A **management-plane simulator** for barox Ethernet switches. It lets
external tools — NMS systems, Genetec, Zabbix, PRTG, SNMP tools, custom
test harnesses — talk to a virtual barox switch over SNMP, a REST API and
(partially) the original WebStaX HTTP protocol, without any physical
hardware.

First supported device: **barox RY-LGSP38-28** (24× 1G PoE+ RJ45 + 4× 10G
SFP+), modeled from the vendor firmware and private MIB shipped alongside
this repository (see `docs/FIRMWARE_ANALYSIS.md` and `docs/MIB_SUPPORT.md`).

This is **not** an ASIC/dataplane emulator (§55 of the spec) — no real
packet forwarding, no VLAN/STP/LACP forwarding. It simulates the
**management plane**: port/PoE/SFP/DDMI/MAC/LLDP/cable-diagnostics state,
counters, SNMP, traps, and scripted failure scenarios, all backed by one
shared MySQL state so the Web UI, REST API, SNMP agent, and WebStaX
compatibility layer are always consistent with each other (§49).

## Requirements

- Ubuntu Server 24.04 LTS (or compatible)
- Apache2 + `mod_rewrite`
- PHP 8.3+ (`php-cli`, `php-mysql`; the `sockets` extension is required for
  the SNMP agent and trap sender)
- MySQL 8 or MariaDB 10.6+
- **No Composer, no PHP framework.** Pure PHP standard library + PDO +
  `ext-sockets` + `ext-pcntl`/`ext-posix`, a small hand-written
  PSR-4-ish autoloader (`app/bootstrap.php`).

## Installation

```bash
sudo scripts/install.sh
```

This installs the system packages, creates the database, imports
`sql/schema.sql` + `sql/seed.sql`, writes `config/local.php`, installs the
Apache vhost and the three systemd worker services, and starts everything.
See the script's final output for the generated admin password reminder,
demo switch details, and an SNMP test command.

Default login: **admin / ChangeMe!2026** — change this immediately.

### Manual installation

1. `cp config/local.example.php config/local.php` and edit DB credentials
   + `app.secret` (generate with `php -r "echo bin2hex(random_bytes(32));"`).
2. `mysql -u root -e "CREATE DATABASE barox_switch_sim CHARACTER SET utf8mb4"`
3. `mysql -u root barox_switch_sim < sql/schema.sql`
4. `mysql -u root barox_switch_sim < sql/seed.sql`
5. `sudo cp apache/barox-switch-simulator.conf /etc/apache2/sites-available/`
   → `a2enmod rewrite headers` → `a2ensite barox-switch-simulator` → reload.
6. `sudo cp systemd/barox-*.service /etc/systemd/system/` → `daemon-reload`
   → `enable --now barox-snmp barox-scenario barox-trap`.
7. `sudo scripts/permissions.sh`

## Configuration

All non-secret simulator tuning lives in `config/simulator.php` (traffic
profile rates, PoE class wattages, cable-diagnostics duration, reboot
duration, CPU/memory/temperature jitter amplitude). Per-installation
secrets/DB credentials live in `config/local.php` (never committed — see
`config/local.example.php`). Runtime-adjustable settings (login rate
limits, PoE restart delay, scenario tick interval) are in the `settings`
DB table, editable via `App\Models\Settings`.

## Creating a virtual switch

Log in → **Virtual Switches** → fill in name, model, a management IP. For
a single-server demo, `127.0.0.1` (with a non-privileged SNMP port like
`1161`) works out of the box. For a real multi-switch deployment, add the
IP to the host first:

```bash
sudo ip addr add 10.50.1.101/24 dev eth0
```

Apache and the SNMP agent both resolve which virtual switch a request is
for from the *destination IP* of that request (`SERVER_ADDR` in PHP, one
UDP socket per switch for SNMP) — see `docs/ARCHITECTURE.md` §5 for why
this scales to 100+ switches without per-switch Apache vhosts.

## REST API

Base: `/api/v1/`, auth via `Authorization: Bearer <key>` (create keys in
the Web UI under **API Keys**, admin only). Full reference with curl
examples: [`docs/API.md`](docs/API.md).

## SNMP

SNMPv2c, `GET`/`GETNEXT`/`GETBULK`/`SET`, hand-written BER codec (no
net-snmp bindings). Full reference: [`docs/SNMP.md`](docs/SNMP.md),
per-OID private-MIB coverage: [`docs/MIB_SUPPORT.md`](docs/MIB_SUPPORT.md).

```bash
snmpwalk -v2c -c public -p 1161 127.0.0.1
snmpset  -v2c -c private -p 1161 127.0.0.1 1.3.6.1.2.1.2.2.1.7.7 i 2   # admin-disable port 7
```

## Architecture

See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the full picture;
in short:

```
Web UI · REST API · SNMP Agent · WebStaX-compat
                 \      |      /
              SimulatorStateService (App\Services\*)
                        |
                  App\Models\* (PDO)
                        |
                      MySQL
```

Every protocol facade calls the same Service classes — an SNMP SET is
visible in the Web UI on the next page load, a REST `PUT` is visible via
`snmpwalk`, etc. Traffic counters and CPU/memory/temperature are computed
on read from a stored rate/baseline + timestamp rather than written by a
per-second background loop, so the design scales to ~100 switches × 28
ports without excessive database writes (§36).

## Testing

No PHPUnit/Composer — plain scripts under `tests/`:

```bash
php tests/test-database.php            # schema/seed sanity check
tests/test-api.sh <API_KEY>            # REST API smoke test (curl)
tests/test-snmp.sh                     # SNMP smoke test (snmpget/snmpwalk/snmpset)
php tests/test-scenario.php            # runs a full scenario end-to-end
```

## Troubleshooting

- **500 error, blank page**: check `/var/log/barox-switch-simulator/app.log`
  (never displayed to the browser — `config/local.php` → `app.env` gates
  that, and it's always off in `production`).
- **SNMP agent won't bind port 161**: `systemctl status barox-snmp` — if it
  lacks `CAP_NET_BIND_SERVICE`, re-check `systemd/barox-snmp.service` was
  installed and `daemon-reload` ran; or use a switch with a non-privileged
  `snmp_port` (e.g. `1161`) for development.
- **New switch's IP not reachable**: confirm `ip addr add ...` was run for
  that IP on the host, and that no other Apache vhost's `ServerName` is
  intercepting it (see the warning at the bottom of
  `apache/barox-switch-simulator.conf` about shared hosts).
- **Traps not arriving**: check `barox-trap.service` is running and the
  trap target's IP/port/community are correct; `tail -f
  /var/log/barox-switch-simulator/trap.log`.

## Security

PDO prepared statements everywhere; `password_hash()`/`password_verify()`
for user passwords; API keys stored only as SHA-256 hashes; CSRF tokens on
every state-changing Web UI form; output escaped with `htmlspecialchars()`;
security headers (CSP, X-Frame-Options, X-Content-Type-Options,
Referrer-Policy); session cookies `HttpOnly`+ `SameSite=Lax` (+`Secure`
when served over HTTPS); session ID regenerated on login; login rate
limiting with account lockout (`settings.login_max_attempts` /
`login_lockout_minutes`). See `docs/ARCHITECTURE.md` §10 for details.

## Project status / scope

Implemented and functional end-to-end: user management & RBAC, virtual
switch CRUD + clone, all 28-port simulation (link/admin/speed/duplex/
flow-control), PoE state machine with restart delay, SFP/DDMI with
threshold alarms, MAC table, LLDP, cable diagnostics, traffic counters +
generator, REST API v1, SNMPv2c agent (GET/GETNEXT/GETBULK/SET) against
both a hand-maintained SNMPv2-MIB/IF-MIB subset and 30 wired private-MIB
objects, SNMPv2c traps, the Scenario Engine (7 built-in scenarios), event
log, audit log, save/startup config + simulated reboot + factory reset.

Deliberately out of scope / partial, and documented as such rather than
faked: the vast majority of the private MIB (VLAN/STP/QoS/TSN/RADIUS/…,
see `docs/MIB_SUPPORT.md`), the WebStaX HTML/JS frontend itself (only 6
backend text-protocol endpoints are replicated, see
`docs/FIRMWARE_ANALYSIS.md`), real ASIC packet forwarding, SNMPv3.
