#!/bin/bash

set -e

usage() {
    echo "Usage: $0 [start|stop] container-name"
    echo
    echo "Start or stop firewalling for the given docker container"
}

get_ipv4() {
    local CONTAINER=$1
    docker inspect -f \
        '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
        "$CONTAINER"
}

get_ipv6() {
    local CONTAINER=$1
    docker inspect -f \
        '{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' \
        "$CONTAINER"
}

start_firewall() {
    local CONTAINER=$1
    local CONFIG="/etc/ark/docker/$CONTAINER.iptables"

    if [ ! -f "$CONFIG" ]; then
        echo "Missing iptables configuration file $CONFIG"
        exit 1
    fi

    # remove any old firewall rules, if the exist, they might be out of date
    if iptables --list DOCKER-USER -n | grep "ARK-DOCKER-${CONTAINER^^}"; then
        stop_firewall "$CONTAINER"
    fi

    IPV4=$(get_ipv4 "$CONTAINER")
    iptables-restore --noflush \
        <(sed "s/@CONTAINER_ADDRESS@/$IPV4/" "$CONFIG")

    IPV6=$(get_ipv6 "$CONTAINER")
    ip6tables-restore --noflush \
        <(sed "s/@CONTAINER_ADDRESS@/$IPV6/" "$CONFIG")
}

stop_firewall() {
    local CONTAINER=$1

    # the specific address of the container is dynamic, so we can't just
    # delete the container specific jump rule directly
    iptables --list DOCKER-USER -n --line-numbers \
        | grep "ARK-DOCKER-${CONTAINER^^}" \
        | awk '{print $1}' \
        | sort -r \
        | xargs -I {} iptables --delete DOCKER-USER {}

    # flush the container specific chain, and delete it
    /usr/sbin/iptables --flush "ARK-DOCKER-${CONTAINER^^}"
    /usr/sbin/iptables --delete-chain "ARK-DOCKER-${CONTAINER^^}"

    ip6tables --list DOCKER-USER -n --line-numbers \
        | grep "ARK-DOCKER-${CONTAINER^^}" \
        | awk '{print $1}' \
        | sort -r \
        | xargs -I {} ip6tables --delete DOCKER-USER {}

    /usr/sbin/ip6tables --flush "ARK-DOCKER-${CONTAINER^^}"
    /usr/sbin/ip6tables --delete-chain "ARK-DOCKER-${CONTAINER^^}"
}

if [ $# != 2 ]; then
    usage
    exit 2
fi

case "$1" in
    "--help" | "-h")
        usage
        exit 0
        ;;
    "start")
        start_firewall "$2"
        exit 0
        ;;
    "stop")
        stop_firewall "$2"
        exit 0
        ;;
    *)
        usage
        exit 2
        ;;
esac
