#!/usr/bin/bash

if [ $# -eq 0 ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
	echo "usage: $(basename $0) up|down NETWORK:TABLE_ID"
	exit 0
fi

if [ "$1" != "up" ] && [ "$1" != "down" ]; then
	echo "invalid command: $1" >&2
	exit 1
fi

if [ $# -lt 2 ]; then
	echo "missing argument" >&2
	exit 1
fi

if ! [[ $2 =~ : ]]; then
	echo "invalid argument: $2" >&2
	exit 1
fi

if [ $UID -ne 0 ]; then
	echo "must be run as root" >&2
	exit 2
fi

if ! which zerotier-cli &> /dev/null; then
	echo "zerotier-cli not found" >&2
	exit 3
fi

[ "$1" = "up" ] && CMD=add || CMD=del

NAME=${2%:*}
NUM=${2#*:}

if ! [[ $NUM =~ ^[0-9]+$ ]]; then
	echo "invalid argument: $2" >&2
	exit 1
fi

TABLE="table $NUM"

if [ "$1" = "up" ] && [ -n "$(ip rule list $TABLE)" ]; then
	echo "$TABLE already configured" >&2
	exit 4
fi

PRIVATE_ROUTES="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 100.64.0.0/10"

readarray -t NETWORKS < <(zerotier-cli listnetworks -j | jq -c '.[]')

for NETWORK in "${NETWORKS[@]}"; do
	[ "$(echo "$NETWORK" | jq -r '.name')" != "$NAME" ] && continue
	DEVICE=$(echo "$NETWORK" | jq -r '.portDeviceName')
	DEV="dev $DEVICE"
	readarray -t ROUTES < <(echo "$NETWORK" | jq -r '.routes[] | tostring')
	ip rule $CMD lookup $NUM priority $((NUM*100))
	for ROUTE in "${ROUTES[@]}"; do
		TARGET=$(echo "$ROUTE" | jq -r '.target')
		TO="to $TARGET"
		VIA=$(echo "$ROUTE" | jq -r '.via')
		[ "$VIA" = "null" ] || GATEWAY="via $VIA"
		ip route $CMD $TO $GATEWAY $DEV $TABLE
	done
	for PRIVATE_ROUTE in $PRIVATE_ROUTES; do
		ip route $CMD to throw $PRIVATE_ROUTE $TABLE
	done
	exit 0
done

echo network $NAME not found
