#!/bin/sh
NFTABLES=false
[ -x /sbin/fw4 ] && NFTABLES=true

IPTABLES_FILE=/var/run/zerotier/nat.iptables

iptables_w() {
    echo iptables -w 1 "$@" >>$IPTABLES_FILE
}

case "x${1}" in
    xinit)
        if $NFTABLES; then
            [ -f /var/run/zerotier/nat.enabled ] || exit 0
            nft -f- >/var/run/zerotier/nat.log 2>&1 <<-EOF
flush chain inet fw4 zerotier_forward
flush chain inet fw4 zerotier_input
flush chain inet fw4 zerotier_postrouting
table inet fw4 {
    chain zerotier_input {
        iifname "zt*" accept
    }
    chain zerotier_forward {
        iifname "zt*" accept
        oifname "zt*" accept
    }
    chain zerotier_postrouting {
        iifname "zt*" masquerade
        oifname "zt*" masquerade
    }
}
EOF
            exit 0
        fi
        iptables -w 1 -t nat -L postrouting_rule | grep -Fq zerotier_nat && exit 0
        iptables -w 1 -N zerotier_forward
        iptables -w 1 -I forwarding_rule -i zt+ -j zerotier_forward
        iptables -w 1 -I forwarding_rule -o zt+ -j zerotier_forward
        iptables -w 1 -t nat -N zerotier_nat
        iptables -w 1 -t nat -I postrouting_rule -j zerotier_nat
        exit 0
    ;;
    xdeinit)
        if $NFTABLES; then
            nft -f- 2>/dev/null <<-EOF
flush chain inet fw4 zerotier_forward
flush chain inet fw4 zerotier_input
flush chain inet fw4 zerotier_postrouting
EOF
        fi
        iptables -w 1 -D forwarding_rule -i zt+ -j zerotier_forward 2>/dev/null
        iptables -w 1 -D forwarding_rule -o zt+ -j zerotier_forward 2>/dev/null
        iptables -w 1 -t nat -D postrouting_rule -j zerotier_nat 2>/dev/null
        iptables -w 1 -F zerotier_forward 2>/dev/null
        iptables -w 1 -X zerotier_forward 2>/dev/null
        iptables -w 1 -t nat -F zerotier_nat 2>/dev/null
        iptables -w 1 -t nat -X zerotier_nat 2>/dev/null
        exit 0
    ;;
esac

if $NFTABLES; then
    exit 0
fi

while :; do
    [ -f /var/run/zerotier/nat.enabled ] || exit 0
    sleep 3
    [ -f /var/run/zerotier/nat.enabled ] || exit 0
    [ -f /var/run/zerotier/netchanged ] || continue
    netchanged=$(date '+%s' -r /var/run/zerotier/netchanged)
    now=$(date '+%s')
    [ "$netchanged" -lt "$now" ] || continue
    iptables_before=$(md5sum $IPTABLES_FILE 2>/dev/null || echo "empty" | cut -d ' ' -f 1)
    >$IPTABLES_FILE
    iptables_w -F zerotier_forward
    iptables_w -t nat -F zerotier_nat
    zt0="$(ls /sys/class/net/ | grep -E '^zt[0-9a-z]{8}$' | awk '{print $1}')"
    for i in ${zt0}
    do
        iptables_w -I zerotier_forward -i "$i" -j ACCEPT
        iptables_w -I zerotier_forward -o "$i" -j ACCEPT
        iptables_w -t nat -I zerotier_nat -o "$i" -j MASQUERADE
        ip_segment="$(ip route | grep "dev $i proto kernel" | awk '{print $1}')"
        [ -z "$ip_segment" ] || iptables_w -t nat -I zerotier_nat -s "${ip_segment}" -j MASQUERADE
    done
    iptables_after=$(md5sum $IPTABLES_FILE 2>/dev/null || echo "empty" | cut -d ' ' -f 1)
    [ "$iptables_before" = "$iptables_after" ] && continue
    . $IPTABLES_FILE >/var/run/zerotier/nat.log
done
