#!/bin/sh
# x86 ingress-only routing. Never capture locally originated management traffic.
set -eu
PATH=/usr/sbin:/usr/bin:/sbin:/bin
refresh_return() {
    ip link show mihomo0 >/dev/null 2>&1 || return 0
    ip -4 route replace 192.168.32.0/24 via 192.168.32.1 dev enp2s0 onlink table 20221
    ip -6 route replace fda2:a01e:2cb2::/64 via fda2:a01e:2cb2::1 dev enp2s0 onlink table 20221
}
cleanup() {
    for family in -4 -6; do
        for pref in 18990 19000 19010 19011; do
            while ip "$family" rule del pref "$pref" 2>/dev/null; do :; done
        done
        ip "$family" route flush table 20220 2>/dev/null || true
        ip "$family" route flush table 20221 2>/dev/null || true
    done
    for tool in iptables ip6tables; do
        for pair in 'enp2s0 mihomo0' 'mihomo0 enp2s0' 'tailscale0 mihomo0' 'mihomo0 tailscale0'; do
            set -- $pair
            while "$tool" -w -D FORWARD -i "$1" -o "$2" -m comment --comment mihomo-gateway -j ACCEPT 2>/dev/null; do :; done
        done
    done
    nft delete table inet mihomo_exit_dns 2>/dev/null || true
}
case "${1:-}" in
refresh-return) refresh_return ;;
down) cleanup ;;
up)
    cleanup
    sysctl -qw net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1
    sysctl -qw net.ipv4.conf.all.send_redirects=0 net.ipv4.conf.enp2s0.send_redirects=0
    # NetworkManager owns the static ::2 and RA; do not override kernel accept_ra.
    count=0
    until ip link show mihomo0 >/dev/null 2>&1; do
        count=$((count+1)); [ "$count" -lt 30 ] || exit 1; sleep 1
    done
    for tool in iptables ip6tables; do
        for pair in 'enp2s0 mihomo0' 'mihomo0 enp2s0' 'tailscale0 mihomo0' 'mihomo0 tailscale0'; do
            set -- $pair
            # Before ts-forward marking/MASQUERADE: preserve source devices into TUN.
            "$tool" -w -I FORWARD 1 -i "$1" -o "$2" -m comment --comment mihomo-gateway -j ACCEPT
        done
    done
    refresh_return
    for family in -4 -6; do
        ip "$family" rule add pref 18990 iif mihomo0 lookup 20221
        ip "$family" route replace default dev mihomo0 table 20220
        for ingress in enp2s0 tailscale0; do
            ip "$family" rule add pref 19000 iif "$ingress" lookup main suppress_prefixlength 0
            ip "$family" rule add pref 19010 iif "$ingress" ipproto tcp lookup 20220
            ip "$family" rule add pref 19011 iif "$ingress" ipproto udp lookup 20220
        done
    done
    nft -f - <<'EOF'
table inet mihomo_exit_dns {
    chain prerouting {
        type nat hook prerouting priority -102; policy accept;
        iifname "tailscale0" meta l4proto { tcp, udp } th dport 53 counter redirect to :53
    }
}
EOF
    ;;
*) exit 2 ;;
esac
