657 lines
14 KiB
Bash
Executable File
657 lines
14 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Generate s6 network definitions
|
|
|
|
set -ex
|
|
|
|
header_eb() {
|
|
echo '#!/bin/execlineb -P'
|
|
}
|
|
|
|
header_if() {
|
|
local if="${1:?missing if}"
|
|
echo "define INTERFACE $if"
|
|
}
|
|
|
|
header_addr() {
|
|
local addr="${1:?missing addr}"
|
|
echo "define ADDR $addr"
|
|
}
|
|
|
|
header_fam() {
|
|
local fam="${1:?missing family}"
|
|
echo "define FAMILY $fam"
|
|
}
|
|
|
|
header_vlan() {
|
|
local vlan="${1:?missing vlan}"
|
|
local parent="${2:?missing parent}"
|
|
echo "define VLAN $vlan"
|
|
echo "define PARENT $parent"
|
|
}
|
|
|
|
header_vrf() {
|
|
local vrf="${1:?missing vrf}"
|
|
echo "define VRF $vrf"
|
|
}
|
|
|
|
header_prop() {
|
|
local prop="${1:?missing prop}"
|
|
echo "define PROP $prop"
|
|
}
|
|
|
|
header_path() {
|
|
cat <<EOF
|
|
s6-envdir -i /etc/s6/env/path
|
|
emptyenv -p
|
|
EOF
|
|
}
|
|
|
|
addrfam() {
|
|
# Use ipv6 if cannot autodetect of if no semicolons are present
|
|
local addr="$1"
|
|
local fam='6'
|
|
if which grep >/dev/null 2>&1 && echo "$addr" | grep -v ':' >/dev/null 2>&1; then
|
|
fam='4'
|
|
fi
|
|
echo "$fam"
|
|
}
|
|
|
|
linkdel() {
|
|
local if="${1:?missing if}"
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
echo 'ip link del $INTERFACE'
|
|
}
|
|
|
|
depends() {
|
|
echo "$@"
|
|
local svcname="${1:?missing sname}"
|
|
|
|
shift 1
|
|
local sname # God i fucking hate global contexts by default
|
|
for sname in $@; do
|
|
install -Dm644 /dev/null rc/"$svcname"/dependencies.d/"$sname"
|
|
done
|
|
}
|
|
|
|
contains() {
|
|
local svcname="${1:?missing sname}"
|
|
|
|
shift 1
|
|
local sname # God i fucking hate global contexts by default
|
|
for sname in $@; do
|
|
install -Dm644 /dev/null rc/"$svcname"/contents.d/"$sname"
|
|
done
|
|
}
|
|
|
|
#
|
|
# Bundle management
|
|
#
|
|
|
|
bundle_deps() {
|
|
local if="${1:?missing if}"
|
|
|
|
local svcname="bundle.interface.$if"
|
|
[ -r "rc/$svcname/type" ] || install -Dm644 <(echo bundle) rc/"$svcname"/type
|
|
|
|
shift 1
|
|
contains "$svcname" $@
|
|
}
|
|
|
|
# Currently used stages
|
|
# > configure
|
|
# - create
|
|
# - enslave
|
|
# - configure (anything that must be configured before interface is up)
|
|
# > ready
|
|
# - link
|
|
# - configure (anything that may be configured after interface is up)
|
|
bundle_stage_create() {
|
|
local if="${1:?missing if}"
|
|
local stage="${2:?missing stage}"
|
|
|
|
local svcname="bundle.interface.$if.$stage"
|
|
[ -r "rc/$svcname/type" ] || install -Dm644 <(echo bundle) rc/"$svcname"/type
|
|
|
|
# Add to parent bundle
|
|
bundle_deps "$if" "$svcname"
|
|
|
|
shift 2
|
|
contains "$svcname" $@
|
|
}
|
|
|
|
bundle_stage_depend_on() {
|
|
local if="${1:?missing if}"
|
|
local stage="${2:?missing stage}"
|
|
|
|
local svcname="bundle.interface.$if.$stage"
|
|
|
|
shift 2
|
|
local sname
|
|
for sname in $@; do
|
|
depends "$sname" "$svcname"
|
|
done
|
|
}
|
|
|
|
bundle_stage_step_configure() {
|
|
local if="$1"
|
|
local stage="configure"
|
|
|
|
shift 1
|
|
bundle_stage_create "$if" "$stage" $@
|
|
}
|
|
|
|
bundle_stage_step_ready() {
|
|
local if="$1"
|
|
local stage="ready"
|
|
|
|
shift 1
|
|
bundle_stage_create "$if" "$stage" $@
|
|
}
|
|
|
|
#
|
|
# Interface creation
|
|
#
|
|
|
|
new_link() {
|
|
local if="${1:?missing if}"
|
|
|
|
local sname="interface.$if.link"
|
|
bundle_stage_step_ready "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
echo 'ip link set dev $INTERFACE up'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
echo 'ip link set dev $INTERFACE down'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
bundle_stage_depend_on "$if" "configure" "$sname"
|
|
}
|
|
|
|
new_if_bridge() {
|
|
local if="${1:?missing if}"
|
|
|
|
local sname="interface.$if.create"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
new_link "$if"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
shift 1
|
|
echo 'ip link add $INTERFACE type bridge'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(linkdel "$if") rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" module.bridge
|
|
}
|
|
|
|
new_if_phys() {
|
|
local if="${1:?missing if}"
|
|
|
|
local sname="interface.$if.create"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
new_link "$if"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
echo 'bcnm-waitif 1 $INTERFACE'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" mdevd.coldplug
|
|
}
|
|
|
|
new_if_wg() {
|
|
local if="${1:?missing if}"
|
|
|
|
# Main service for creating interface
|
|
local sname="interface.$if.create"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
echo 'ip link add $INTERFACE type wireguard'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(linkdel "$if") rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" module.wireguard
|
|
|
|
new_link "$if"
|
|
# Secondary service for loading config
|
|
if_wg_conf "$if"
|
|
}
|
|
|
|
new_if_vrf() {
|
|
local if="${1:?missing if}"
|
|
local table="${2:?missing table}"
|
|
|
|
local sname="interface.$if.create"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
cat <<EOF
|
|
s6-envdir -i /etc/s6/env/interface.\${INTERFACE}
|
|
importas -i TABLE TABLE
|
|
EOF
|
|
echo 'ip link add $INTERFACE type vrf table $TABLE'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(linkdel "$if") rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
install -Dm644 <(echo "$table") env/interface."$if"/TABLE
|
|
|
|
depends "$sname" module.vrf sysctl.net-ipv6-conf-all-keep_addr_on_down
|
|
|
|
new_link "$if"
|
|
}
|
|
|
|
new_if_vlan() {
|
|
local if="${1:?missing if}"
|
|
local vlan="$(echo $if | cut -d'-' -f2)"
|
|
local parent="$(echo $if | cut -d'-' -f1)"
|
|
|
|
local sname="interface.$if.create"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_vlan "$vlan" "$parent"
|
|
echo 'ip link add link $PARENT name $INTERFACE type vlan id $VLAN'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(linkdel "$if") rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" module.8021q interface."$parent".create
|
|
|
|
new_link "$if"
|
|
}
|
|
|
|
#
|
|
# Interface configuration and properties
|
|
#
|
|
|
|
if_slave() {
|
|
local master="${1:?missing master}"
|
|
local slave="${2:?missing slave}"
|
|
|
|
local sname="interface.$master.slave.$slave"
|
|
bundle_stage_step_configure "$master" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
cat <<EOF
|
|
define MASTERIF $master
|
|
define SLAVEIF $slave
|
|
EOF
|
|
echo 'ip link set dev $SLAVEIF master $MASTERIF'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
cat <<EOF
|
|
define SLAVEIF $slave
|
|
EOF
|
|
echo 'ip link set dev $SLAVEIF nomaster'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$master".create interface."$slave".create
|
|
}
|
|
|
|
if_forward() {
|
|
local if="${1:?missing if}"
|
|
local fam="${2:-6}"
|
|
|
|
if_sysctl "$if" "forwarding" '1' '0' "$fam"
|
|
}
|
|
|
|
if_accept_ra() {
|
|
local if="${1:?missing if}"
|
|
local fam="6"
|
|
|
|
if_sysctl "$if" "accept_ra" '2' '0' "$fam"
|
|
}
|
|
|
|
if_sysctl() {
|
|
local if="${1:?missing if}"
|
|
local prop="${2:?missing property}"
|
|
local val_e="${3:-1}"
|
|
local val_d="${4:-0}"
|
|
local fam="${5:-6}"
|
|
|
|
local sname="sysctl.net-ipv$fam-conf-$if-$prop"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_fam "$fam"
|
|
header_prop "$prop"
|
|
cat <<EOF
|
|
export VAL $val_e
|
|
s6-envdir -I /etc/s6/env/sysctl.net-ipv\${FAMILY}-conf-\${INTERFACE}-\${PROP}
|
|
export SYSCTL net/ipv\${FAMILY}/conf/\${INTERFACE}/\${PROP}
|
|
/usr/libexec/nnd/s6/sysctl
|
|
EOF
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_fam "$fam"
|
|
header_prop "$prop"
|
|
cat <<EOF
|
|
export SYSCTL net/ipv\${FAMILY}/conf/\${INTERFACE}/\${PROP}
|
|
export VAL $val_d
|
|
/usr/libexec/nnd/s6/sysctl
|
|
EOF
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
[ "$fam" = '6' ] && depends "$sname" module.ipv6
|
|
depends "$sname" mount.proc interface."$if".create
|
|
}
|
|
|
|
if_bridge_property() {
|
|
local prop="${1:?missing prop}"
|
|
local if="${2:?missing if}"
|
|
local state="${3:-1}"
|
|
local downstate="${4-0}"
|
|
|
|
local sname="interface.$if.bridge.$prop"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
cat <<EOF
|
|
define PROP $prop
|
|
define STATE $state
|
|
EOF
|
|
echo 'ip link set $INTERFACE type bridge $PROP $STATE'
|
|
) rc/"$sname"/up
|
|
[ -z "$downstate" ] || install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
cat <<EOF
|
|
define PROP $prop
|
|
define STATE $downstate
|
|
EOF
|
|
echo 'ip link set $INTERFACE type bridge $PROP $STATE'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
# Might not be a requirement since STP is probably a hard dependency of bridges
|
|
[ "$prop" == 'stp_state' ] && depends "$sname" module.stp
|
|
depends "$sname" interface."$if".create
|
|
}
|
|
|
|
if_ether_address() {
|
|
local if="${1:?missing if}"
|
|
local addr="${2:?missing addr}"
|
|
|
|
local sname="interface.$if.ether.addr"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_addr "$addr"
|
|
echo 'ip link set $INTERFACE address $ADDR'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".create
|
|
}
|
|
|
|
if_wg_conf() {
|
|
local if="${1:?missing if}"
|
|
|
|
local sname="interface.$if.wg.config"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
cat <<EOF
|
|
s6-envdir -I /etc/s6/env/interface.\${INTERFACE}.wg-config
|
|
importas -D /etc/wireguard/\${INTERFACE} CONFIG CONFIG
|
|
EOF
|
|
echo 'wg setconf $INTERFACE $CONFIG'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".create
|
|
}
|
|
|
|
if_dhcp() {
|
|
local if="${1:?missing if}"
|
|
|
|
local sname="interface.$if.dhcp"
|
|
bundle_stage_step_ready "$if" "$sname"
|
|
|
|
install -Dm755 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
cat <<EOF
|
|
fdmove -c 2 1
|
|
udhcpc -i \$INTERFACE -f -S
|
|
EOF
|
|
) rc/"$sname"/run
|
|
install -Dm644 <(echo longrun) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".link syslogd logger.udhcpc
|
|
}
|
|
|
|
if_ip_addr() {
|
|
local if="${1:?missing if}"
|
|
local addr="${2:?missing addr}"
|
|
local fam="${3:-$(addrfam "$addr")}"
|
|
local addrn="$(echo "$addr" | sed 's/\//_/g')"
|
|
|
|
local sname="interface.$if.ip.addr.$fam.$addrn"
|
|
bundle_stage_step_ready "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_addr "$addr"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} address add $ADDR dev $INTERFACE'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_addr "$addr"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} address del $ADDR dev $INTERFACE'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".link
|
|
}
|
|
|
|
if_route_vrf_addr() {
|
|
local vrf="${1:?missing vrf}"
|
|
local if="${2:?missing if}"
|
|
local addr="${3:?missing addr}"
|
|
local fam="${4:-6}"
|
|
local addrn="$(echo "$addr" | sed 's/\//_/g')"
|
|
|
|
local sname="interface.$if.route.$vrf.$fam.$addrn"
|
|
bundle_stage_step_ready "$if" "$sname" # Interface route may be added only if it's up
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_vrf "$vrf"
|
|
header_if "$if"
|
|
header_addr "$addr"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route add to $ADDR dev $INTERFACE vrf $VRF'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_vrf "$vrf"
|
|
header_if "$if"
|
|
header_addr "$addr"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route del to $ADDR dev $INTERFACE vrf $VRF'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".link interface."$vrf".create
|
|
}
|
|
|
|
if_route_vrf_addr_gateway() {
|
|
local vrf="${1:?missing vrf}"
|
|
local if="${2:?missing if}"
|
|
local gateway="${3:?missing gw}"
|
|
local addr="${4:?missing addr}"
|
|
local fam="${5:-6}"
|
|
local gatewayn="$(echo "$gateway" | sed 's/\//_/g')"
|
|
local addrn="$(echo "$addr" | sed 's/\//_/g')"
|
|
|
|
local sname="interface.$if.gateway.$vrf.$fam.$gatewayn"
|
|
bundle_stage_step_ready "$if" "$sname" # Interface route may be added only if it's up
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_vrf "$vrf"
|
|
header_if "$if"
|
|
header_addr "$gateway"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route add default via $ADDR dev $INTERFACE vrf $VRF'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_vrf "$vrf"
|
|
header_if "$if"
|
|
header_addr "$gateway"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route del default via $ADDR dev $INTERFACE vrf $VRF'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" "interface.$if.route.$vrf.$fam.$addrn" interface."$if".link interface."$vrf".create
|
|
}
|
|
|
|
if_route_vrf_default_interface() {
|
|
local vrf="${1:?missing vrf}"
|
|
local if="${2:?missing if}"
|
|
local fam="${3:-6}"
|
|
|
|
local sname="interface.$vrf.route.$fam.default"
|
|
bundle_stage_step_configure "$vrf" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_vrf "$vrf"
|
|
header_if "$if"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route add default dev $INTERFACE vrf $VRF'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_vrf "$vrf"
|
|
header_if "$if"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route del default dev $INTERFACE vrf $VRF'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".link interface."$vrf".create
|
|
}
|
|
|
|
if_route_vrf_default_unreach() {
|
|
local if="${1:?missing if}"
|
|
local fam="${2:-6}"
|
|
|
|
local sname="interface.$if.route.$fam.unreach"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route add unreachable default metric 4096 vrf $INTERFACE'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route del unreachable default metric 4096 vrf $INTERFACE'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".create
|
|
}
|
|
|
|
if_route_vrf_sink_unreach() {
|
|
local if="${1:?missing if}"
|
|
local addr="${2:?missing addr}"
|
|
local fam="${3:-6}"
|
|
local addrn="$(echo "$addr" | sed 's/\//_/g')"
|
|
|
|
local sname="interface.$if.route.$fam.sink.$addrn"
|
|
bundle_stage_step_configure "$if" "$sname"
|
|
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_addr "$addr"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route add unreachable $ADDR vrf $INTERFACE'
|
|
) rc/"$sname"/up
|
|
install -Dm644 <(
|
|
header_eb
|
|
header_path
|
|
header_if "$if"
|
|
header_addr "$addr"
|
|
header_fam "$fam"
|
|
echo 'ip -${FAMILY} route del unreachable $ADDR vrf $INTERFACE'
|
|
) rc/"$sname"/down
|
|
install -Dm644 <(echo oneshot) rc/"$sname"/type
|
|
|
|
depends "$sname" interface."$if".create
|
|
}
|