#!/usr/local/bin/bash # set -euo pipefail IFS=$'\n\t' DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" function main { if [ "$1" = "start" ]; then shift 1 start_jail "${@}" elif [ "$1" = "stop" ]; then shift 1 stop_jail "${@}" else >&2 echo "Unrecognized command" exit 1 fi } function start_jail { host_interface_name="$1" bridge_name="bridge_${host_interface_name}" jail_interface_name="$2" ip_range="$3" assert_bridge "$host_interface_name" "$bridge_name" "$ip_range" bridge_link_name=$(detect_available_link "${bridge_name}") ngctl -d -f - </dev/null 2>&1 } function ng_bridge_get_num_hooks { ngctl show "${1}" | grep -oE 'Num hooks: [0-9]+' | sed 's/Num hooks: //g' } function detect_available_link { bridge_name="$1" linknum=1 while true; do link_name="link${linknum}" if ! ng_exists "${bridge_name}:${link_name}"; then echo "$link_name" return fi (>&2 echo "$link_name failed on $bridge_name") linknum=$((linknum + 1)) if [ "$linknum" -gt 90 ]; then (>&2 echo "No available links on bridge $bridge_name") exit 1 fi done } function wait_for_interface_to_exist { # Wait for a vnet interface to exist again as a jail is shutting # down. If you delete the netgraph node before the interface # device exists, then the interface device will persist in a # broken state. ifname="$1" max_wait_seconds="$2" start=$(date +%s) while true; do now=$(date +%s) if [ $((now - start)) -gt $max_wait_seconds ]; then (>&2 echo "Waited for at least $max_wait_seconds seconds but the interface $ifname did not appear.") return 1; fi if ifconfig "$ifname" >/dev/null 2>&1; then return 0; fi sleep 2 done } main "${@}"