From 5eaebacbab22fed1135ce9f2aac6b14bb253cb21 Mon Sep 17 00:00:00 2001 From: zach Date: Fri, 10 Jul 2026 15:00:02 +0200 Subject: [PATCH] remove unrelated directory --- .gitignore | 1 + assets/logo.png | Bin 0 -> 32604 bytes network-dev/wifi-sim.sh | 310 ---------------------------------------- 3 files changed, 1 insertion(+), 310 deletions(-) create mode 100644 assets/logo.png delete mode 100755 network-dev/wifi-sim.sh diff --git a/.gitignore b/.gitignore index 39a44e6..c18220d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ dist/ **/target/ **/test-plugins/ **/Charts/ +network-dev/ diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ec06df142868b1be12c0e117befec9175b71034f GIT binary patch literal 32604 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 - exit 1 -} -info() { echo "[*] $*"; } -ok() { echo "[+] $*"; } - -require_cmds() { - local missing=() - for cmd in "$@"; do - command -v "$cmd" &>/dev/null || missing+=("$cmd") - done - if [[ ${#missing[@]} -gt 0 ]]; then - die "Missing required tools: ${missing[*]} - Install with: sudo apt install hostapd wpasupplicant iw" - fi -} - -get_phy_for_iface() { - iw dev "$1" info | awk '/wiphy/{print "phy"$2}' -} - -# --- Start ------------------------------------------------------------------- - -cmd_start() { - [[ $EUID -ne 0 ]] && die "Please run as root: sudo $0 start" - require_cmds hostapd iw ip - - if [[ -d "$RUN_DIR" && -f "$RUN_DIR/interfaces" ]]; then - die "wifi-sim appears to already be running. Run 'sudo $0 stop' first." - fi - mkdir -p "$RUN_DIR" - - # Snapshot existing wlan interfaces so we can identify the new ones - info "Snapshotting existing interfaces..." - BEFORE=($(iw dev 2>/dev/null | awk '/Interface/{print $2}' | grep -v '^hwsim' || true)) - - # Load the kernel module with 4 radios (3 APs + 1 client) - info "Loading mac80211_hwsim (4 radios)..." - if lsmod | grep -q mac80211_hwsim; then - die "mac80211_hwsim is already loaded. Run 'sudo $0 stop' or 'sudo rmmod mac80211_hwsim' first." - fi - modprobe mac80211_hwsim radios=4 - sleep 1 # Give the kernel a moment to register all interfaces - - # Find the interfaces created by our modprobe - AFTER=($(iw dev 2>/dev/null | awk '/Interface/{print $2}' | grep -v '^hwsim')) - NEW_IFACES=() - for iface in "${AFTER[@]}"; do - [[ ! " ${BEFORE[*]:-} " =~ " $iface " ]] && NEW_IFACES+=("$iface") - done - - if [[ ${#NEW_IFACES[@]} -lt 4 ]]; then - rmmod mac80211_hwsim 2>/dev/null || true - die "Expected 4 new wlan interfaces, found ${#NEW_IFACES[@]}. Check 'dmesg' for errors." - fi - - AP1="${NEW_IFACES[0]}" # Will host SSID_STRONG - AP2="${NEW_IFACES[1]}" # Will host SSID_MEDIUM - AP3="${NEW_IFACES[2]}" # Will host SSID_SECURE - CLIENT="${NEW_IFACES[3]}" # Client-side interface for your code to use - - info "Interfaces assigned: AP1=$AP1 AP2=$AP2 AP3=$AP3 Client=$CLIENT" - echo "$AP1 $AP2 $AP3 $CLIENT" >"$RUN_DIR/interfaces" - - # Prevent NetworkManager from fighting us over these interfaces - if command -v nmcli &>/dev/null && nmcli general status &>/dev/null 2>&1; then - info "Marking interfaces as unmanaged in NetworkManager..." - for iface in "$AP1" "$AP2" "$AP3"; do - nmcli device set "$iface" managed no 2>/dev/null || true - done - - nmcli device set "$CLIENT" managed yes - fi - - # Set TX power on each physical radio to simulate signal strength differences. - # mac80211_hwsim factors TX power into the RSSI reported to scanning clients. - # Note: for precise RSSI control, consider 'wmediumd' (a wireless medium daemon). - info "Setting TX power levels for signal strength simulation..." - PHY1=$(get_phy_for_iface "$AP1") - PHY2=$(get_phy_for_iface "$AP2") - PHY3=$(get_phy_for_iface "$AP3") - - iw phy "$PHY1" set txpower fixed $TXPOWER_STRONG - iw phy "$PHY2" set txpower fixed $TXPOWER_MEDIUM - iw phy "$PHY3" set txpower fixed $TXPOWER_WEAK - - # --- hostapd config: AP1 (open, strong, channel 1) ----------------------- - cat >"$RUN_DIR/ap1.conf" <"$RUN_DIR/ap2.conf" <"$RUN_DIR/ap3.conf" <"$RUN_DIR/ap1.log" 2>&1 || - { - cat "$RUN_DIR/ap1.log" - die "hostapd failed for AP1. See log above." - } - - hostapd -B -P "$RUN_DIR/ap2.pid" "$RUN_DIR/ap2.conf" \ - >"$RUN_DIR/ap2.log" 2>&1 || - { - cat "$RUN_DIR/ap2.log" - die "hostapd failed for AP2. See log above." - } - - hostapd -B -P "$RUN_DIR/ap3.pid" "$RUN_DIR/ap3.conf" \ - >"$RUN_DIR/ap3.log" 2>&1 || - { - cat "$RUN_DIR/ap3.log" - die "hostapd failed for AP3. See log above." - } - - # Bring up the client interface so it's ready to scan/connect - ip link set "$CLIENT" up - - # --- Summary ------------------------------------------------------------- - ok "Virtual WiFi environment is up!" - echo "" - echo " Networks:" - echo " ┌──────────────────┬──────────┬────────┬─────────────┐" - echo " │ SSID │ Security │ Signal │ Interface │" - echo " ├──────────────────┼──────────┼────────┼─────────────┤" - printf " │ %-16s │ %-8s │ %-6s │ %-11s │\n" "$SSID_STRONG" "Open" "Strong" "$AP1" - printf " │ %-16s │ %-8s │ %-6s │ %-11s │\n" "$SSID_MEDIUM" "Open" "Medium" "$AP2" - printf " │ %-16s │ %-8s │ %-6s │ %-11s │\n" "$SSID_SECURE" "WPA2" "Weak" "$AP3" - echo " └──────────────────┴──────────┴────────┴─────────────┘" - echo "" - echo " WPA2 password : $WIFI_PASSWORD" - echo " Client iface : $CLIENT (use this in your code)" - echo "" - echo " Useful commands:" - echo " Scan for networks : sudo iw dev $CLIENT scan | grep -E 'SSID|signal'" - echo " Connect (open) : sudo iw dev $CLIENT connect \"$SSID_STRONG\"" - echo " Connect (WPA2) : sudo wpa_supplicant -Dnl80211 -i$CLIENT \\" - echo " -c <(wpa_passphrase \"$SSID_SECURE\" \"$WIFI_PASSWORD\")" - echo " Stop simulation : sudo $0 stop" - echo "" - echo " Logs: $RUN_DIR/ap{1,2,3}.log" -} - -# --- Stop -------------------------------------------------------------------- - -cmd_stop() { - [[ $EUID -ne 0 ]] && die "Please run as root: sudo $0 stop" - - info "Stopping virtual WiFi environment..." - local had_something=false - - # Kill hostapd processes via PID files - for ap in ap1 ap2 ap3; do - PID_FILE="$RUN_DIR/$ap.pid" - if [[ -f "$PID_FILE" ]]; then - PID=$(cat "$PID_FILE") - if kill "$PID" 2>/dev/null; then - info "Stopped hostapd for $ap (PID $PID)" - fi - rm -f "$PID_FILE" - had_something=true - fi - done - - # Re-enable NetworkManager management for these interfaces - if [[ -f "$RUN_DIR/interfaces" ]]; then - read -r AP1 AP2 AP3 CLIENT <"$RUN_DIR/interfaces" - if command -v nmcli &>/dev/null; then - for iface in "$AP1" "$AP2" "$AP3" "$CLIENT"; do - nmcli device set "$iface" managed yes 2>/dev/null || true - done - fi - fi - - # Unload the kernel module (also destroys all virtual interfaces) - if lsmod | grep -q mac80211_hwsim; then - info "Unloading mac80211_hwsim..." - rmmod mac80211_hwsim && had_something=true - fi - - # Clean up runtime directory - rm -rf "$RUN_DIR" - - if $had_something; then - ok "Virtual WiFi environment stopped." - else - echo "Nothing was running." - fi -} - -# --- Status ------------------------------------------------------------------ - -cmd_status() { - if [[ ! -f "$RUN_DIR/interfaces" ]]; then - echo "wifi-sim is not running." - return - fi - - read -r AP1 AP2 AP3 CLIENT <"$RUN_DIR/interfaces" - echo "wifi-sim is running." - echo "" - echo " Interfaces:" - for iface in "$AP1" "$AP2" "$AP3" "$CLIENT"; do - STATE=$(ip link show "$iface" 2>/dev/null | awk '/state/{print $9}' || echo "unknown") - CHANNEL=$(iw dev "$iface" info 2>/dev/null | awk '/channel/{print $2}' || echo "?") - printf " %-10s state=%-4s channel=%s\n" "$iface" "$STATE" "$CHANNEL" - done - echo "" - echo " Processes:" - for ap in ap1 ap2 ap3; do - PID_FILE="$RUN_DIR/$ap.pid" - if [[ -f "$PID_FILE" ]]; then - PID=$(cat "$PID_FILE") - if kill -0 "$PID" 2>/dev/null; then - echo " hostapd ($ap) PID=$PID running" - else - echo " hostapd ($ap) PID=$PID DEAD (check $RUN_DIR/$ap.log)" - fi - fi - done -} - -# --- Entry point ------------------------------------------------------------- - -case "${1:-help}" in -start) cmd_start ;; -stop) cmd_stop ;; -status) cmd_status ;; -*) - echo "Usage: sudo $0 {start|stop|status}" - echo "" - echo " start Load mac80211_hwsim and bring up 3 virtual APs" - echo " stop Tear down all virtual interfaces and unload module" - echo " status Show current state of interfaces and processes" - echo "" - echo "Networks created on start:" - printf " %-16s open, strong signal\n" "$SSID_STRONG" - printf " %-16s open, medium signal\n" "$SSID_MEDIUM" - printf " %-16s WPA2, weak signal (password: $WIFI_PASSWORD)\n" "$SSID_SECURE" - ;; -esac