17879db76SDevin Teske#!/bin/sh 27879db76SDevin Teske#- 37879db76SDevin Teske# Copyright (c) 2016 Devin Teske 47879db76SDevin Teske# All rights reserved. 57879db76SDevin Teske# 67879db76SDevin Teske# Redistribution and use in source and binary forms, with or without 77879db76SDevin Teske# modification, are permitted provided that the following conditions 87879db76SDevin Teske# are met: 97879db76SDevin Teske# 1. Redistributions of source code must retain the above copyright 107879db76SDevin Teske# notice, this list of conditions and the following disclaimer. 117879db76SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright 127879db76SDevin Teske# notice, this list of conditions and the following disclaimer in the 137879db76SDevin Teske# documentation and/or other materials provided with the distribution. 147879db76SDevin Teske# 157879db76SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 167879db76SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 177879db76SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 187879db76SDevin Teske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 197879db76SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 207879db76SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 217879db76SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 227879db76SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 237879db76SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 247879db76SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 257879db76SDevin Teske# SUCH DAMAGE. 267879db76SDevin Teske# 277879db76SDevin Teske# 287879db76SDevin Teske############################################################ IDENT(1) 297879db76SDevin Teske# 307879db76SDevin Teske# $Title: if_bridge(4) management script for vnet jails $ 317879db76SDevin Teske# 327879db76SDevin Teske############################################################ INFORMATION 337879db76SDevin Teske# 347879db76SDevin Teske# Use this tool with jail.conf(5) (or rc.conf(5) ``legacy'' configuration) to 35626ddc51SDevin Teske# manage `vnet' interfaces for jails. Designed to automate the creation of vnet 36626ddc51SDevin Teske# interface(s) during jail `prestart' and destroy said interface(s) during jail 37626ddc51SDevin Teske# `poststop'. 38626ddc51SDevin Teske# 39626ddc51SDevin Teske# In jail.conf(5) format: 407879db76SDevin Teske# 417879db76SDevin Teske# ### BEGIN EXCERPT ### 427879db76SDevin Teske# 437879db76SDevin Teske# xxx { 447879db76SDevin Teske# host.hostname = "xxx.yyy"; 457879db76SDevin Teske# path = "/vm/xxx"; 467879db76SDevin Teske# 477879db76SDevin Teske# # 487879db76SDevin Teske# # NB: Below 2-lines required 497879db76SDevin Teske# # NB: The number of eNb_xxx interfaces should match the number of 507879db76SDevin Teske# # arguments given to `jib addm xxx' in exec.prestart value. 517879db76SDevin Teske# # 527879db76SDevin Teske# vnet; 5330482552SDevin Teske# vnet.interface = e0b_xxx, e1b_xxx, ...; 547879db76SDevin Teske# 557879db76SDevin Teske# exec.clean; 567879db76SDevin Teske# exec.system_user = "root"; 577879db76SDevin Teske# exec.jail_user = "root"; 587879db76SDevin Teske# 597879db76SDevin Teske# # 607879db76SDevin Teske# # NB: Below 2-lines required 617879db76SDevin Teske# # NB: The number of arguments after `jib addm xxx' should match 627879db76SDevin Teske# # the number of eNb_xxx arguments in vnet.interface value. 637879db76SDevin Teske# # 647879db76SDevin Teske# exec.prestart += "jib addm xxx em0 em1 ..."; 657879db76SDevin Teske# exec.poststop += "jib destroy xxx"; 667879db76SDevin Teske# 677879db76SDevin Teske# # Standard recipe 687879db76SDevin Teske# exec.start += "/bin/sh /etc/rc"; 69*5fda0d60SAndriy Gapon# exec.stop = "/bin/sh /etc/rc.shutdown jail"; 707879db76SDevin Teske# exec.consolelog = "/var/log/jail_xxx_console.log"; 717879db76SDevin Teske# mount.devfs; 727879db76SDevin Teske# 737879db76SDevin Teske# # Optional (default off) 747879db76SDevin Teske# #allow.mount; 757879db76SDevin Teske# #allow.set_hostname = 1; 767879db76SDevin Teske# #allow.sysvipc = 1; 777879db76SDevin Teske# #devfs_ruleset = "11"; # rule to unhide bpf for DHCP 787879db76SDevin Teske# } 797879db76SDevin Teske# 807879db76SDevin Teske# ### END EXCERPT ### 817879db76SDevin Teske# 827879db76SDevin Teske# In rc.conf(5) ``legacy'' format (used when /etc/jail.conf does not exist): 837879db76SDevin Teske# 847879db76SDevin Teske# ### BEGIN EXCERPT ### 857879db76SDevin Teske# 867879db76SDevin Teske# jail_enable="YES" 877879db76SDevin Teske# jail_list="xxx" 887879db76SDevin Teske# 897879db76SDevin Teske# # 907879db76SDevin Teske# # Global presets for all jails 917879db76SDevin Teske# # 927879db76SDevin Teske# jail_devfs_enable="YES" # mount devfs 937879db76SDevin Teske# 947879db76SDevin Teske# # 957879db76SDevin Teske# # Global options (default off) 967879db76SDevin Teske# # 977879db76SDevin Teske# #jail_mount_enable="YES" # mount /etc/fstab.{name} 987879db76SDevin Teske# #jail_set_hostname_allow="YES" # Allow hostname to change 997879db76SDevin Teske# #jail_sysvipc_allow="YES" # Allow SysV Interprocess Comm. 1007879db76SDevin Teske# 1017879db76SDevin Teske# # xxx 1027879db76SDevin Teske# jail_xxx_hostname="xxx.shxd.cx" # hostname 1037879db76SDevin Teske# jail_xxx_rootdir="/vm/xxx" # root directory 1047879db76SDevin Teske# jail_xxx_vnet_interfaces="e0b_xxx e1bxxx ..." # vnet interface(s) 1057879db76SDevin Teske# jail_xxx_exec_prestart0="jib addm xxx em0 em1 ..." # bridge interface(s) 1067879db76SDevin Teske# jail_xxx_exec_poststop0="jib destroy xxx" # destroy interface(s) 1077879db76SDevin Teske# #jail_xxx_mount_enable="YES" # mount /etc/fstab.xxx 1087879db76SDevin Teske# #jail_xxx_devfs_ruleset="11" # rule to unhide bpf for DHCP 1097879db76SDevin Teske# 1107879db76SDevin Teske# ### END EXCERPT ### 1117879db76SDevin Teske# 1127879db76SDevin Teske# Note that the legacy rc.conf(5) format is converted to 1137879db76SDevin Teske# /var/run/jail.{name}.conf by /etc/rc.d/jail if jail.conf(5) is missing. 1147879db76SDevin Teske# 1157879db76SDevin Teske# ASIDE: dhclient(8) inside a vnet jail... 1167879db76SDevin Teske# 1177879db76SDevin Teske# To allow dhclient(8) to work inside a vnet jail, make sure the following 1187879db76SDevin Teske# appears in /etc/devfs.rules (which should be created if it doesn't exist): 1197879db76SDevin Teske# 1207879db76SDevin Teske# [devfsrules_jail=11] 1217879db76SDevin Teske# add include $devfsrules_hide_all 1227879db76SDevin Teske# add include $devfsrules_unhide_basic 1237879db76SDevin Teske# add include $devfsrules_unhide_login 124517ca8c0SDevin Teske# add path 'bpf*' unhide 1257879db76SDevin Teske# 1267879db76SDevin Teske# And set ether devfs.ruleset="11" (jail.conf(5)) or 1277879db76SDevin Teske# jail_{name}_devfs_ruleset="11" (rc.conf(5)). 1287879db76SDevin Teske# 1297879db76SDevin Teske# NB: While this tool can't create every type of desirable topology, it should 1307879db76SDevin Teske# handle most setups, minus some which considered exotic or purpose-built. 1317879db76SDevin Teske# 1327879db76SDevin Teske############################################################ GLOBALS 1337879db76SDevin Teske 1347879db76SDevin Teskepgm="${0##*/}" # Program basename 1357879db76SDevin Teske 1367879db76SDevin Teske# 1377879db76SDevin Teske# Global exit status 1387879db76SDevin Teske# 1397879db76SDevin TeskeSUCCESS=0 1407879db76SDevin TeskeFAILURE=1 1417879db76SDevin Teske 1427879db76SDevin Teske############################################################ FUNCTIONS 1437879db76SDevin Teske 1447879db76SDevin Teskeusage() 1457879db76SDevin Teske{ 1467879db76SDevin Teske local action usage descr 1477879db76SDevin Teske exec >&2 1487879db76SDevin Teske echo "Usage: $pgm action [arguments]" 1497879db76SDevin Teske echo "Actions:" 1507879db76SDevin Teske for action in \ 1517879db76SDevin Teske addm \ 1527879db76SDevin Teske show \ 1537879db76SDevin Teske show1 \ 1547879db76SDevin Teske destroy \ 1557879db76SDevin Teske ; do 1567879db76SDevin Teske eval usage=\"\$jib_${action}_usage\" 1577879db76SDevin Teske [ "$usage" ] || continue 1587879db76SDevin Teske eval descr=\"\$jib_${action}_descr\" 1597879db76SDevin Teske printf "\t%s\n\t\t%s\n" "$usage" "$descr" 1607879db76SDevin Teske done 1617879db76SDevin Teske exit $FAILURE 1627879db76SDevin Teske} 1637879db76SDevin Teske 1647879db76SDevin Teskeaction_usage() 1657879db76SDevin Teske{ 1663ce83dbfSDevin Teske local usage descr action="$1" 1677879db76SDevin Teske eval usage=\"\$jib_${action}_usage\" 1687879db76SDevin Teske echo "Usage: $pgm $usage" >&2 1693ce83dbfSDevin Teske eval descr=\"\$jib_${action}_descr\" 1703ce83dbfSDevin Teske printf "\t%s\n" "$descr" 1717879db76SDevin Teske exit $FAILURE 1727879db76SDevin Teske} 1737879db76SDevin Teske 1747e4b7c79SDevin Teskederive_mac() 1757e4b7c79SDevin Teske{ 1767e4b7c79SDevin Teske local OPTIND=1 OPTARG __flag 1777e4b7c79SDevin Teske local __mac_num= __make_pair= 1787e4b7c79SDevin Teske while getopts 2n: __flag; do 1797e4b7c79SDevin Teske case "$__flag" in 1807e4b7c79SDevin Teske 2) __make_pair=1 ;; 1817e4b7c79SDevin Teske n) __mac_num=${OPTARG%%[^0-9]*} ;; 1827e4b7c79SDevin Teske esac 1837e4b7c79SDevin Teske done 1847e4b7c79SDevin Teske shift $(( $OPTIND - 1 )) 1857e4b7c79SDevin Teske 1867e4b7c79SDevin Teske if [ ! "$__mac_num" ]; then 1877e4b7c79SDevin Teske eval __mac_num=\${_${iface}_num:--1} 1887e4b7c79SDevin Teske __mac_num=$(( $__mac_num + 1 )) 1897e4b7c79SDevin Teske eval _${iface}_num=\$__mac_num 1907e4b7c79SDevin Teske fi 1917e4b7c79SDevin Teske 1927e4b7c79SDevin Teske local __iface="$1" __name="$2" __var_to_set="$3" __var_to_set_b="$4" 1937e4b7c79SDevin Teske local __iface_devid __new_devid __num __new_devid_b 1947e4b7c79SDevin Teske # 1957e4b7c79SDevin Teske # Calculate MAC address derived from given iface. 1967e4b7c79SDevin Teske # 1977e4b7c79SDevin Teske # The formula I'm using is ``NP:SS:SS:II:II:II'' where: 1987e4b7c79SDevin Teske # + N denotes 4 bits used as a counter to support branching 1997e4b7c79SDevin Teske # each parent interface up to 15 times under the same jail 2007e4b7c79SDevin Teske # name (see S below). 2017e4b7c79SDevin Teske # + P denotes the special nibble whose value, if one of 2027e4b7c79SDevin Teske # 2, 6, A, or E (but usually 2) denotes a privately 2037e4b7c79SDevin Teske # administered MAC address (while remaining routable). 2047e4b7c79SDevin Teske # + S denotes 16 bits, the sum(1) value of the jail name. 2057e4b7c79SDevin Teske # + I denotes bits that are inherited from parent interface. 2067e4b7c79SDevin Teske # 2077e4b7c79SDevin Teske # The S bits are a CRC-16 checksum of NAME, allowing the jail 2087e4b7c79SDevin Teske # to change link numbers in ng_bridge(4) without affecting the 2097e4b7c79SDevin Teske # MAC address. Meanwhile, if... 2107e4b7c79SDevin Teske # + the jail NAME changes (e.g., it was duplicated and given 2117e4b7c79SDevin Teske # a new name with no other changes) 2127e4b7c79SDevin Teske # + the underlying network interface changes 2137e4b7c79SDevin Teske # + the jail is moved to another host 2147e4b7c79SDevin Teske # the MAC address will be recalculated to a new, similarly 2157e4b7c79SDevin Teske # unique value preventing conflict. 2167e4b7c79SDevin Teske # 2177e4b7c79SDevin Teske __iface_devid=$( ifconfig $__iface ether | awk '/ether/,$0=$2' ) 21878954c3bSDevin Teske # ??:??:??:II:II:II 21978954c3bSDevin Teske __new_devid=${__iface_devid#??:??:??} # => :II:II:II 22078954c3bSDevin Teske # => :SS:SS:II:II:II 2217e4b7c79SDevin Teske __num=$( set -- `echo -n "$__name" | sum` && echo $1 ) 22278954c3bSDevin Teske __new_devid=$( printf :%02x:%02x \ 22378954c3bSDevin Teske $(( $__num >> 8 & 255 )) $(( $__num & 255 )) )$__new_devid 22478954c3bSDevin Teske # => P:SS:SS:II:II:II 2257e4b7c79SDevin Teske case "$__iface_devid" in 2267e4b7c79SDevin Teske ?2:*) __new_devid=a$__new_devid __new_devid_b=e$__new_devid ;; 2277e4b7c79SDevin Teske ?[Ee]:*) __new_devid=2$__new_devid __new_devid_b=6$__new_devid ;; 2287e4b7c79SDevin Teske *) __new_devid=2$__new_devid __new_devid_b=e$__new_devid 2297e4b7c79SDevin Teske esac 23078954c3bSDevin Teske # => NP:SS:SS:II:II:II 2317e4b7c79SDevin Teske __new_devid=$( printf %x $(( $__mac_num & 15 )) )$__new_devid 2327e4b7c79SDevin Teske __new_devid_b=$( printf %x $(( $__mac_num & 15 )) )$__new_devid_b 2337e4b7c79SDevin Teske 2347e4b7c79SDevin Teske # 2357e4b7c79SDevin Teske # Return derivative MAC address(es) 2367e4b7c79SDevin Teske # 2377e4b7c79SDevin Teske if [ "$__make_pair" ]; then 2387e4b7c79SDevin Teske if [ "$__var_to_set" -a "$__var_to_set_b" ]; then 2397e4b7c79SDevin Teske eval $__var_to_set=\$__new_devid 2407e4b7c79SDevin Teske eval $__var_to_set_b=\$__new_devid_b 2417e4b7c79SDevin Teske else 2427e4b7c79SDevin Teske echo $__new_devid $__new_devid_b 2437e4b7c79SDevin Teske fi 2447e4b7c79SDevin Teske else 2457e4b7c79SDevin Teske if [ "$__var_to_set" ]; then 2467e4b7c79SDevin Teske eval $__var_to_set=\$__new_devid 2477e4b7c79SDevin Teske else 2487e4b7c79SDevin Teske echo $__new_devid 2497e4b7c79SDevin Teske fi 2507e4b7c79SDevin Teske fi 2517e4b7c79SDevin Teske} 2527e4b7c79SDevin Teske 2537879db76SDevin Teskemustberoot_to_continue() 2547879db76SDevin Teske{ 2557879db76SDevin Teske if [ "$( id -u )" -ne 0 ]; then 2567879db76SDevin Teske echo "Must run as root!" >&2 2577879db76SDevin Teske exit $FAILURE 2587879db76SDevin Teske fi 2597879db76SDevin Teske} 2607879db76SDevin Teske 2611ccea30fSDevin Teskejib_addm_usage="addm [-b BRIDGE_NAME] NAME [!]iface0 [[!]iface1 ...]" 2627879db76SDevin Teskejib_addm_descr="Creates e0b_NAME [e1b_NAME ...]" 2637879db76SDevin Teskejib_addm() 2647879db76SDevin Teske{ 2657879db76SDevin Teske local OPTIND=1 OPTARG flag bridge=bridge 2667879db76SDevin Teske while getopts b: flag; do 2677879db76SDevin Teske case "$flag" in 2687879db76SDevin Teske b) bridge="${OPTARG:-bridge}" ;; 2697879db76SDevin Teske *) action_usage addm # NOTREACHED 2707879db76SDevin Teske esac 2717879db76SDevin Teske done 2727879db76SDevin Teske shift $(( $OPTIND - 1 )) 2737879db76SDevin Teske 2747879db76SDevin Teske local name="$1" 2757879db76SDevin Teske [ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -gt 1 ] || 2767879db76SDevin Teske action_usage addm # NOTREACHED 2777879db76SDevin Teske shift 1 # name 2787879db76SDevin Teske 2797879db76SDevin Teske mustberoot_to_continue 2807879db76SDevin Teske 2817e4b7c79SDevin Teske local iface eiface_devid_a eiface_devid_b 2821ccea30fSDevin Teske local new no_derive num quad i=0 2837879db76SDevin Teske for iface in $*; do 2847879db76SDevin Teske 2851ccea30fSDevin Teske no_derive= 2861ccea30fSDevin Teske case "$iface" in 2871ccea30fSDevin Teske !*) iface=${iface#!} no_derive=1 ;; 2881ccea30fSDevin Teske esac 2891ccea30fSDevin Teske 2904b9a5d61SDevin Teske # Make sure the interface doesn't exist already 2914b9a5d61SDevin Teske if ifconfig "e${i}a_$name" > /dev/null 2>&1; then 2924b9a5d61SDevin Teske i=$(( $i + 1 )) 2934b9a5d61SDevin Teske continue 2944b9a5d61SDevin Teske fi 2957879db76SDevin Teske 2964b9a5d61SDevin Teske # Bring the interface up 2977879db76SDevin Teske ifconfig $iface up || return 2987879db76SDevin Teske 2994b9a5d61SDevin Teske # Make sure the interface has been bridged 3007879db76SDevin Teske if ! ifconfig "$iface$bridge" > /dev/null 2>&1; then 3017879db76SDevin Teske new=$( ifconfig bridge create ) || return 3027879db76SDevin Teske ifconfig $new addm $iface || return 3037879db76SDevin Teske ifconfig $new name "$iface$bridge" || return 304f2c27deaSDevin Teske ifconfig "$iface$bridge" up || return 3057879db76SDevin Teske fi 3067879db76SDevin Teske 3074b9a5d61SDevin Teske # Create a new interface to the bridge 3087879db76SDevin Teske new=$( ifconfig epair create ) || return 3097879db76SDevin Teske ifconfig "$iface$bridge" addm $new || return 3107879db76SDevin Teske 3114b9a5d61SDevin Teske # Rename the new interface 3127879db76SDevin Teske ifconfig $new name "e${i}a_$name" || return 3137879db76SDevin Teske ifconfig ${new%a}b name "e${i}b_$name" || return 314f2c27deaSDevin Teske ifconfig "e${i}a_$name" up || return 315f2c27deaSDevin Teske ifconfig "e${i}b_$name" up || return 3167879db76SDevin Teske 3177879db76SDevin Teske # 3184b9a5d61SDevin Teske # Set the MAC address of the new interface using a sensible 3197879db76SDevin Teske # algorithm to prevent conflicts on the network. 3207879db76SDevin Teske # 3211ccea30fSDevin Teske eiface_devid_a= eiface_devid_b= 3221ccea30fSDevin Teske [ "$no_derive" ] || derive_mac -2 $iface "$name" \ 3231ccea30fSDevin Teske eiface_devid_a eiface_devid_b 3241ccea30fSDevin Teske if [ "$eiface_devid_a" -a "$eiface_devid_b" ]; then 3251ccea30fSDevin Teske ifconfig "e${i}a_$name" ether $eiface_devid_a 3261ccea30fSDevin Teske ifconfig "e${i}b_$name" ether $eiface_devid_b 3271ccea30fSDevin Teske fi > /dev/null 2>&1 3287879db76SDevin Teske 3294b9a5d61SDevin Teske i=$(( $i + 1 )) 3307879db76SDevin Teske done # for iface 3317879db76SDevin Teske} 3327879db76SDevin Teske 3337879db76SDevin Teskejib_show_usage="show" 3347879db76SDevin Teskejib_show_descr="List possible NAME values for \`show NAME'" 3357879db76SDevin Teskejib_show1_usage="show NAME" 3360df549cbSDevin Teskejib_show1_descr="Lists e0b_NAME [e1b_NAME ...]" 3377879db76SDevin Teskejib_show2_usage="show [NAME]" 3387879db76SDevin Teskejib_show() 3397879db76SDevin Teske{ 3407879db76SDevin Teske local OPTIND=1 OPTARG flag 3417879db76SDevin Teske while getopts "" flag; do 3427879db76SDevin Teske case "$flag" in 3437879db76SDevin Teske *) action_usage show2 # NOTREACHED 3447879db76SDevin Teske esac 3457879db76SDevin Teske done 3467879db76SDevin Teske shift $(( $OPTIND - 1 )) 3477879db76SDevin Teske if [ $# -eq 0 ]; then 3487879db76SDevin Teske ifconfig | awk ' 3497879db76SDevin Teske /^[^:[:space:]]+:/ { 3507879db76SDevin Teske iface = $1 3517879db76SDevin Teske sub(/:.*/, "", iface) 3527879db76SDevin Teske next 3537879db76SDevin Teske } 3547879db76SDevin Teske $1 == "groups:" { 3557879db76SDevin Teske for (n = split($0, group); n > 1; n--) { 3567879db76SDevin Teske if (group[n] != "bridge") continue 3577879db76SDevin Teske print iface 3587879db76SDevin Teske next 3597879db76SDevin Teske } 3607879db76SDevin Teske }' | 3617879db76SDevin Teske xargs -rn1 ifconfig | 3627879db76SDevin Teske awk '$1 == "member:" && 3637879db76SDevin Teske sub(/^e[[:digit:]]+a_/, "", $2), $0 = $2' | 3647879db76SDevin Teske sort -u 3657879db76SDevin Teske return 3667879db76SDevin Teske fi 3677879db76SDevin Teske ifconfig | awk -v name="$1" ' 3687879db76SDevin Teske match($0, /^e[[:digit:]]+a_/) && sub(/:.*/, "") && 3697879db76SDevin Teske substr($1, RSTART + RLENGTH) == name 3707879db76SDevin Teske ' | sort 3717879db76SDevin Teske} 3727879db76SDevin Teske 3737879db76SDevin Teskejib_destroy_usage="destroy NAME" 3747879db76SDevin Teskejib_destroy_descr="Destroy e0b_NAME [e1b_NAME ...]" 3757879db76SDevin Teskejib_destroy() 3767879db76SDevin Teske{ 3777879db76SDevin Teske local OPTIND=1 OPTARG flag 3787879db76SDevin Teske while getopts "" flag; do 3797879db76SDevin Teske case "$flag" in 3807879db76SDevin Teske *) action_usage destroy # NOTREACHED 3817879db76SDevin Teske esac 3827879db76SDevin Teske done 3837879db76SDevin Teske shift $(( $OPTIND -1 )) 3847879db76SDevin Teske local name="$1" 3857879db76SDevin Teske [ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -eq 1 ] || 3867879db76SDevin Teske action_usage destroy # NOTREACHED 3877879db76SDevin Teske mustberoot_to_continue 3887879db76SDevin Teske jib_show "$name" | xargs -rn1 -I eiface ifconfig eiface destroy 3897879db76SDevin Teske} 3907879db76SDevin Teske 3917879db76SDevin Teske############################################################ MAIN 3927879db76SDevin Teske 3937879db76SDevin Teske# 3947879db76SDevin Teske# Command-line arguments 3957879db76SDevin Teske# 3967879db76SDevin Teskeaction="$1" 3977879db76SDevin Teske[ "$action" ] || usage # NOTREACHED 3987879db76SDevin Teske 3997879db76SDevin Teske# 4007879db76SDevin Teske# Validate action argument 4017879db76SDevin Teske# 4027879db76SDevin Teskeif [ "$BASH_VERSION" ]; then 4037879db76SDevin Teske type="$( type -t "jib_$action" )" || usage # NOTREACHED 4047879db76SDevin Teskeelse 4057879db76SDevin Teske type="$( type "jib_$action" 2> /dev/null )" || usage # NOTREACHED 4067879db76SDevin Teskefi 4077879db76SDevin Teskecase "$type" in 4087879db76SDevin Teske*function) 4097879db76SDevin Teske shift 1 # action 4107879db76SDevin Teske eval "jib_$action" \"\$@\" 4117879db76SDevin Teske ;; 4127879db76SDevin Teske*) usage # NOTREACHED 4137879db76SDevin Teskeesac 4147879db76SDevin Teske 4157879db76SDevin Teske################################################################################ 4167879db76SDevin Teske# END 4177879db76SDevin Teske################################################################################ 418