s6-netdev/netdev.sh

449 lines
10 KiB
Bash
Executable File

#!/bin/sh
#
# Generate s6 network definitions
set -x
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_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
local fam='4'
fi
echo "$fam"
}
linkdel() {
local if="${1:?missing if}"
header_eb
header_path
header_if "$if"
echo 'ip link del $INTERFACE'
}
ifbundle() {
local if="${1:?missing if}"
[ -r "rc/bundle.interface.$if/type" ] || install -Dm644 <(echo bundle) rc/bundle.interface."$if"/type
shift 1
for sname in $@; do
install -Dm644 /dev/null rc/bundle.interface."$if"/contents.d/"$sname"
done
}
new_link() {
local if="${1:?missing if}"
local sname="interface.$if.link"
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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/bundle.interface."$if"
}
new_forward() {
local if="${1:?missing if}"
local fam="${2:-6}"
local sname="sysctl.net-ipv$fam-conf-$if-forwarding"
ifbundle "$if" "$sname"
install -Dm644 <(
header_eb
header_path
header_if "$if"
header_fam "$fam"
cat <<EOF
export VAL 1
s6-envdir -I /etc/s6/env/sysctl.net-ipv\${FAMILY}-conf-\${INTERFACE}-forwarding
export SYSCTL net/ipv\${FAMILY}/conf/\${INTERFACE}/forwarding
/usr/libexec/nnd/s6/sysctl
EOF
) rc/"$sname"/up
install -Dm644 <(
header_eb
header_path
header_if "$if"
header_fam "$fam"
cat <<EOF
export SYSCTL net/ipv\${FAMILY}/conf/\${INTERFACE}/forwarding
export VAL 0
/usr/libexec/nnd/s6/sysctl
EOF
) rc/"$sname"/down
install -Dm644 <(echo oneshot) rc/"$sname"/type
[ "$fam" = '6' ] && install -Dm644 /dev/null rc/"$sname"/dependencies.d/module.ipv6
install -Dm644 /dev/null rc/"$sname"/dependencies.d/mount.proc
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".create
}
new_if_slave() {
local master="${1:?missing master}"
local slave="${2:?missing slave}"
local sname="interface.$master.slave.$slave"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$master".create
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$slave".create
}
new_if_bridge() {
local if="${1:?missing if}"
local sname="interface.$if.create"
ifbundle "$if" "$sname"
install -Dm644 <(
header_eb
header_path
header_if "$if"
echo 'ip link add $INTERFACE type bridge'
) rc/"$sname"/up
install -Dm644 <(linkdel "$if") rc/"$sname"/down
install -Dm644 <(echo oneshot) rc/"$sname"/type
install -Dm644 /dev/null rc/"$sname"/dependencies.d/module.bridge
new_link "$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.$prop"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".create
[ "$prop" == 'stp_state' ] && install -Dm644 /dev/null rc/"$sname"/dependencies.d/module.stp
}
if_lladdress() {
local if="${1:?missing if}"
local addr="${2:?missing addr}"
local sname="interface.$if.lladdr"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".create
}
new_if_phys() {
local if="${1:?missing if}"
local sname="interface.$if.create"
ifbundle "$if" "$sname"
install -Dm644 <(
header_eb
header_path
header_if "$if"
echo 'bcnm-waitif 1 $INTERFACE'
) rc/"$sname"/up
install -Dm644 <(echo oneshot) rc/"$sname"/type
install -Dm644 /dev/null rc/"$sname"/dependencies.d/mdevd.coldplug
new_link "$if"
}
new_if_wg() {
local if="${1:?missing if}"
# Main service for creating interface
local sname="interface.$if.create"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/module.wireguard
# Secondary service for loading config
wgconf "$if"
new_link "$if"
}
wgconf() {
local if="${1:?missing if}"
local sname="interface.$if.wg-config"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".create
}
new_if_vrf() {
local if="${1:?missing if}"
local table="${2:?missing table}"
local sname="interface.$if.create"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/module.vrf
install -Dm644 /dev/null rc/"$sname"/dependencies.d/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"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/module.8021q
new_link "$if"
}
addr_static_if() {
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.static.addr.$fam.$addrn"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".create
}
route_vrf_default_if() {
local vrf="${1:?missing vrf}"
local if="${2:?missing if}"
local fam="${3:-6}"
local sname="interface.$vrf.route.$fam.default"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$vrf".create
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".link
}
route_vrf_default_unreach() {
local if="${1:?missing if}"
local fam="${2:-6}"
local sname="interface.$if.route.$fam.unreach"
ifbundle "$if" "$sname"
install -Dm644 <(
header_eb
header_path
header_if "$if"
header_fam "$fam"
echo 'ip -${FAMILY} route add unreachable default vrf $INTERFACE'
) rc/"$sname"/up
install -Dm644 <(
header_eb
header_path
header_if "$if"
header_fam "$fam"
echo 'ip -${FAMILY} route del unreachable default vrf $INTERFACE'
) rc/"$sname"/down
install -Dm644 <(echo oneshot) rc/"$sname"/type
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".create
}
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"
ifbundle "$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
install -Dm644 /dev/null rc/"$sname"/dependencies.d/interface."$if".create
}