#!/bin/sh set -o pipefail MAIN=/usr/share/firewall4/main.uc LOCK=/var/run/fw4.lock STATE=/var/run/fw4.state VERBOSE= [ -e /dev/stdin ] && STDIN=/dev/stdin || STDIN=/proc/self/fd/0 [ -t 2 ] && export TTY=1 die() { [ -n "$QUIET" ] || echo "$@" >&2 exit 1 } start() { { flock -x 1000 case "$1" in start) [ -f $STATE ] && die "The fw4 firewall appears to be already loaded." ;; reload) [ ! -f $STATE ] && die "The fw4 firewall does not appear to be loaded." # Delete state to force reloading ubus state rm -f $STATE ;; esac ACTION=start \ utpl -S $MAIN | nft $VERBOSE -f $STDIN ACTION=includes \ utpl -S $MAIN } 1000>$LOCK } print() { ACTION=print \ utpl -S $MAIN } stop() { { flock -x 1000 if nft list tables inet | grep -sq "table inet fw4"; then nft delete table inet fw4 rm -f $STATE else return 1 fi } 1000>$LOCK } flush() { { flock -x 1000 local dummy family table nft list tables | while read dummy family table; do nft delete table "$family" "$table" done rm -f $STATE } 1000>$LOCK } reload_sets() { ACTION=reload-sets \ flock -x $LOCK utpl -S $MAIN | nft $VERBOSE -f $STDIN } lookup() { ACTION=$1 OBJECT=$2 DEVICE=$3 \ flock -x $LOCK utpl -S $MAIN } while [ -n "$1" ]; do case "$1" in -q) export QUIET=1 shift ;; -v) export VERBOSE=-e shift ;; *) break ;; esac done case "$1" in start|reload) start "$1" ;; stop) stop || die "The fw4 firewall does not appear to be loaded, try fw4 flush to delete all rules." ;; flush) flush ;; restart) QUIET=1 print | nft ${VERBOSE} -c -f $STDIN || die "The rendered ruleset contains errors, not doing firewall restart." stop || rm -f $STATE start ;; check) if [ -n "$QUIET" ]; then exec 1>/dev/null exec 2>/dev/null fi print | nft ${VERBOSE} -c -f $STDIN && echo "Ruleset passes nftables check." ;; print) print ;; reload-sets) reload_sets ;; network|device|zone) lookup "$@" ;; *) cat <