#!/bin/bash
set -e

DEST_IP="54.37.137.197"
DEST_PORT="9935"
WATCH_PORT="9930"

MIRROR="/usr/local/sbin/sondemap-mirror.py"
SERVICE="/etc/systemd/system/sondemap-mirror.service"

echo "=========================================="
echo "       SondeMap UDP Mirror Installer"
echo "=========================================="
echo
echo "Podsłuch: wychodzący UDP -> :${WATCH_PORT}"
echo "Kopia:    ${DEST_IP}:${DEST_PORT}"
echo

if [ "$(id -u)" -ne 0 ]; then
    echo "BLAD: uruchom instalator przez sudo:"
    echo "sudo ./install-sondemap-mirror.sh"
    exit 1
fi

echo "[1/5] Sprawdzanie Python 3..."
if ! command -v python3 >/dev/null 2>&1; then
    echo "Instalowanie Python 3..."
    apt-get update
    apt-get install -y python3
fi
echo "OK - Python 3"

echo "[2/5] Tworzenie SondeMap Mirror..."

cat > "$MIRROR" <<'PYTHON'
#!/usr/bin/env python3
import socket
import struct
import sys
import time

DEST_IP = "54.37.137.197"
DEST_PORT = 9935
WATCH_PORT = 9930

ETH_P_ALL = 0x0003
PACKET_OUTGOING = 4
VLAN_TYPES = {0x8100, 0x88A8}

def log(message):
    print(message, flush=True)

def get_ipv4_offset(packet):
    if len(packet) < 14:
        return None

    eth_type = struct.unpack("!H", packet[12:14])[0]
    offset = 14

    while eth_type in VLAN_TYPES:
        if len(packet) < offset + 4:
            return None
        eth_type = struct.unpack("!H", packet[offset + 2:offset + 4])[0]
        offset += 4

    if eth_type != 0x0800:
        return None

    return offset

def main():
    log("SondeMap UDP Mirror")
    log(f"Podsłuch: outgoing UDP -> :{WATCH_PORT}")
    log(f"Kopia: {DEST_IP}:{DEST_PORT}")

    try:
        sniffer = socket.socket(
            socket.AF_PACKET,
            socket.SOCK_RAW,
            socket.htons(ETH_P_ALL)
        )
    except PermissionError:
        log("BLAD: brak uprawnien do AF_PACKET.")
        sys.exit(1)

    sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    count = 0

    while True:
        try:
            packet, address = sniffer.recvfrom(65535)

            if len(address) < 3 or address[2] != PACKET_OUTGOING:
                continue

            ip_start = get_ipv4_offset(packet)
            if ip_start is None or len(packet) < ip_start + 20:
                continue

            version_ihl = packet[ip_start]
            if version_ihl >> 4 != 4:
                continue

            ihl = (version_ihl & 0x0F) * 4
            if ihl < 20 or len(packet) < ip_start + ihl + 8:
                continue

            frag = struct.unpack("!H", packet[ip_start + 6:ip_start + 8])[0]
            if (frag & 0x1FFF) != 0:
                continue

            if packet[ip_start + 9] != 17:
                continue

            udp_start = ip_start + ihl
            src_port, dst_port, udp_length, _ = struct.unpack(
                "!HHHH", packet[udp_start:udp_start + 8]
            )

            if dst_port != WATCH_PORT or udp_length < 8:
                continue

            payload_start = udp_start + 8
            payload_end = payload_start + udp_length - 8

            if payload_end > len(packet):
                continue

            payload = packet[payload_start:payload_end]
            if not payload:
                continue

            sender.sendto(payload, (DEST_IP, DEST_PORT))
            count += 1
            log(
                f"MIRROR #{count}: {len(payload)} B "
                f":{src_port} -> :{WATCH_PORT} => {DEST_IP}:{DEST_PORT}"
            )

        except KeyboardInterrupt:
            break
        except Exception as error:
            log(f"ERROR: {error}")
            time.sleep(1)

if __name__ == "__main__":
    main()
PYTHON

chmod 755 "$MIRROR"

echo "[3/5] Sprawdzanie składni..."
python3 -m py_compile "$MIRROR"
echo "OK - składnia Python poprawna"

echo "[4/5] Tworzenie usługi systemd..."

cat > "$SERVICE" <<'SERVICE'
[Unit]
Description=SondeMap UDP 9930 Mirror
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
ExecStart=/usr/bin/python3 /usr/local/sbin/sondemap-mirror.py
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
SERVICE

systemctl daemon-reload
systemctl stop sondemap-mirror.service 2>/dev/null || true
systemctl enable sondemap-mirror.service
systemctl start sondemap-mirror.service

sleep 2

echo "[5/5] Sprawdzanie usługi..."

if systemctl is-active --quiet sondemap-mirror.service; then
    echo
    echo "=========================================="
    echo " INSTALACJA ZAKONCZONA POMYSLNIE"
    echo "=========================================="
    echo "SondeMod nie został zmodyfikowany."
    echo "Podsłuch: UDP -> :${WATCH_PORT}"
    echo "Kopia: ${DEST_IP}:${DEST_PORT}"
    echo "Usługa: sondemap-mirror.service"
    echo "Status: ACTIVE"
    echo
    echo "Log:"
    echo "sudo journalctl -u sondemap-mirror.service -f"
else
    echo
    echo "BLAD URUCHOMIENIA USLUGI"
    journalctl -u sondemap-mirror.service -n 30 --no-pager
    exit 1
fi
