mirror of
https://github.com/zerotier/edge.git
synced 2026-05-22 16:25:05 -07:00
594 lines
13 KiB
Bash
Executable File
594 lines
13 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
PROGRAM=setup-interfaces
|
|
PREFIX=
|
|
|
|
PKGS=
|
|
|
|
for i in ./libalpine.sh $PREFIX/lib/libalpine.sh; do
|
|
[ -e $i ] && . $i && break
|
|
done
|
|
|
|
unconfigured_add() {
|
|
touch $1.noconf
|
|
}
|
|
|
|
unconfigured_detect() {
|
|
local i=
|
|
for i in ${INTERFACES:-$(available_ifaces)}; do
|
|
if [ "$i" != "lo" ]; then
|
|
unconfigured_add $i
|
|
fi
|
|
done
|
|
}
|
|
|
|
unconfigured_get_first() {
|
|
ls *.noconf 2>/dev/null | head -n 1 | sed 's/.noconf//'
|
|
}
|
|
|
|
unconfigured_del() {
|
|
rm -f $1.noconf
|
|
}
|
|
|
|
unconfigured_all_done() {
|
|
local i=
|
|
for i in *.noconf; do
|
|
[ -e $i ] && return 1
|
|
done
|
|
return 0
|
|
}
|
|
|
|
unconfigured_list() {
|
|
local list= i=
|
|
for i in *.noconf; do
|
|
[ -e "$i" ] || continue
|
|
list="${list} ${i%.noconf}"
|
|
done
|
|
echo $list
|
|
}
|
|
|
|
unconfigured_isin() {
|
|
[ -f $1.noconf ]
|
|
}
|
|
|
|
iface_exists() {
|
|
test -e /sys/class/net/$1
|
|
}
|
|
|
|
get_default_addr() {
|
|
# check if dhcpcd is running
|
|
if pidof dhcpcd > /dev/null && [ -f "$ROOT/var/lib/dhcpc/dhcpcd-$1.info" ]; then
|
|
echo dhcp
|
|
elif iface_exists $1; then
|
|
ip addr show $1 | awk '/inet / {print $2}' | head -n 1 | sed 's:/.*::'
|
|
fi
|
|
}
|
|
|
|
get_default_mask() {
|
|
if [ "$1" ] ; then
|
|
ipcalc -m $1 | sed 's/.*=//'
|
|
else
|
|
echo "255.255.255.0"
|
|
fi
|
|
}
|
|
|
|
get_default_gateway() {
|
|
if iface_exists $1; then
|
|
ip route show dev $1 | awk '/^default/ {print $3}'
|
|
fi
|
|
}
|
|
|
|
ipaddr_help() {
|
|
cat <<-__EOF__
|
|
|
|
Select the ip address for this interface.
|
|
|
|
dhcp Dynamic/automatic ip via DHCP
|
|
none Do not add any address
|
|
n.n.n.n (ex: 192.168.0.1) Static ip
|
|
n.n.n.n/m (ex: 192.168.0.1/24) Static ip with mask
|
|
br[0-9]+ (ex: br0) Add this interface to a bridge
|
|
bridge[0-9] (ex: bridge0) Add this interface to a bridge
|
|
|
|
You will be prompted for netmask if not specified with the address.
|
|
|
|
__EOF__
|
|
}
|
|
|
|
bridge_add_port() {
|
|
local bridge=$1 iface=
|
|
shift
|
|
for iface; do
|
|
echo $iface >> $bridge.bridge_ports
|
|
unconfigured_add $bridge
|
|
unconfigured_del $iface
|
|
done
|
|
}
|
|
|
|
bridge_list_ports() {
|
|
if [ -r $1.bridge_ports ]; then
|
|
echo $(cat $1.bridge_ports)
|
|
fi
|
|
}
|
|
|
|
is_bridge() {
|
|
test -r $1.bridge_ports
|
|
}
|
|
|
|
is_wifi() {
|
|
test -d /sys/class/net/$1/phy80211
|
|
}
|
|
|
|
find_essids() {
|
|
local iface=$1
|
|
export essids_list=wlans
|
|
# Supports only open or PSK
|
|
ip link set dev "$iface" up
|
|
iwlist $iface scanning | awk -F: '/ESSID/ { printf "%s ",$2 } /Authentication Suites/ \
|
|
{ printf ":%s\n",$2 }' | grep -v 802.1x | sort -u >$essids_list
|
|
if [ -s $essids_list ]; then
|
|
cat $essids_list
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
config_wpa_supp() {
|
|
local iface=$1
|
|
local essid=$2
|
|
local psk=$3
|
|
local conffile=/etc/wpa_supplicant/wpa_supplicant.conf
|
|
if [ "$auth_type" == "WPA-PSK" ]; then
|
|
cat << EOF >> $conffile
|
|
network={
|
|
ssid="$essid"
|
|
key_mgmt=$auth_type
|
|
psk="$psk"
|
|
}
|
|
EOF
|
|
else
|
|
cat << EOF >> $conffile
|
|
network={
|
|
ssid="$essid"
|
|
key_mgmt=$auth_type
|
|
}
|
|
EOF
|
|
fi
|
|
|
|
wpa_supplicant -B -c $conffile -i $iface 2>/dev/null
|
|
}
|
|
|
|
wlan_is_not_open() {
|
|
local iface=$1
|
|
local essid=$2
|
|
auth_type=$(awk -F: '/'"$essid"'/ { print $2 }' $essids_list)
|
|
echo $auth_type | grep -q PSK
|
|
if [ "$?" -eq "0" ]; then
|
|
export auth_type="WPA-PSK"
|
|
return 0
|
|
else
|
|
export auth_type="open"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
config_iface() {
|
|
local iface=$1
|
|
local prefix=$2
|
|
local default_address=$3
|
|
local address= netmask= gateway= bridge_ports=
|
|
local bridge
|
|
local conf=$prefix$iface.conf
|
|
local answer=
|
|
|
|
while [ -n "$ask_bridge" ] && ! is_bridge $iface; do
|
|
ask "Do you want to bridge the interface $iface?" yes
|
|
case "$resp" in
|
|
yes|y) resp=yes; break;;
|
|
no|n) break;;
|
|
esac
|
|
done
|
|
|
|
if [ "$resp" = "yes" ]; then
|
|
bridge="br$(echo $iface | sed 's/[^0-9]//g')"
|
|
ask "Name of the bridge you want add $iface to:" $bridge
|
|
bridge_add_port $resp $iface
|
|
return
|
|
fi
|
|
|
|
if [ -r "$iface.bridge_ports" ]; then
|
|
bridge_ports=$(echo $(cat $iface.bridge_ports))
|
|
echo "bridge_ports=\"$bridge_ports\"" >> $conf
|
|
fi
|
|
if [ -r "$iface.bond_slaves" ]; then
|
|
bond_slaves=$(echo $(cat $iface.bond_slaves))
|
|
echo "bond_slaves=\"$bond_slaves\"" >> $conf
|
|
fi
|
|
if [ -r "$iface.raw_device" ]; then
|
|
raw_device=$(cat $iface.raw_device)
|
|
echo "raw_device=\"$raw_device\"" >> $conf
|
|
fi
|
|
if is_wifi $iface; then
|
|
apk add --quiet --no-progress wireless-tools wpa_supplicant || prompt_for_interfaces
|
|
echo "Available wireless networks (scanning):"
|
|
if find_essids $iface; then
|
|
ask "Type the wireless network name to connect to:"
|
|
local essid=$resp
|
|
if wlan_is_not_open $iface "$essid"; then
|
|
ask "Type the \"$essid\" network Pre-Shared Key:"
|
|
psk=$resp
|
|
fi
|
|
config_wpa_supp $iface "$essid" "$psk"
|
|
else
|
|
echo -e "\nNo available wireless networks\n"
|
|
prompt_for_interfaces
|
|
fi
|
|
fi
|
|
# use ipcalc to validate the address. we do accept /mask
|
|
# we are no interested in the result, only error code, so
|
|
# we send result to /dev/null
|
|
while ! ipcalc -s -m $address >/dev/null 2>&1; do
|
|
address=${default_address:-$(get_default_addr $iface)}
|
|
[ -z "$address" ] && address="dhcp"
|
|
ask "Ip address for $iface? (or 'dhcp', 'none', '?')" $address
|
|
address=$resp
|
|
case "$resp" in
|
|
'?') ipaddr_help;;
|
|
"abort") return;;
|
|
"dhcp")
|
|
echo "type=dhcp" >> $conf
|
|
unconfigured_del $iface
|
|
return ;;
|
|
"none")
|
|
echo "type=manual" >> $conf
|
|
unconfigured_del $iface
|
|
return;;
|
|
br[0-9]*|bridge[0-9]*)
|
|
case "$iface" in
|
|
# we dont allow bridge bridges
|
|
br[0-9]*|bridge[0-9]*) continue;;
|
|
esac
|
|
bridge_add_port $resp $iface
|
|
return ;;
|
|
esac
|
|
done
|
|
|
|
# extract netmask if entered together with address
|
|
if [ "$address" != "${address%%/*}" ]; then
|
|
netmask=$(ipcalc -s -m $address | cut -d= -f2)
|
|
fi
|
|
|
|
# use ipcalc -m to validate netmask. we dont accept <addr>/mask suffix
|
|
# so we pass on a dummy mask to ipcalc.
|
|
while ! ipcalc -s -m $netmask/0 >/dev/null 2>&1; do
|
|
netmask=$(get_default_mask $address)
|
|
ask "Netmask?" $netmask
|
|
netmask=$resp
|
|
[ "$netmask" = "abort" ] && return
|
|
done
|
|
|
|
# use ipcalc -m to validate netmask. we dont accept <addr>/mask suffix
|
|
# so we pass on a dummy mask to ipcalc.
|
|
while ! ipcalc -s -m $gateway/0 >/dev/null 2>&1; do
|
|
gateway=$(get_default_gateway $iface)
|
|
[ -z "$gateway" ] && gateway=none
|
|
ask "Gateway? (or 'none')" $gateway
|
|
gateway=$resp
|
|
[ "$gateway" = "abort" ] && return
|
|
[ "$gateway" = "none" ] && gateway=""
|
|
[ -z "$gateway" ] && break
|
|
done
|
|
|
|
echo "type=static" >> $conf
|
|
if [ -n "$bridge_ports" ]; then
|
|
echo "bridge_ports=$bridge_ports" >> $conf
|
|
fi
|
|
echo "address=${address%%/*}" >> $conf #strip off /mask if there
|
|
echo "netmask=$netmask" >> $conf
|
|
echo "gateway=$gateway" >> $conf
|
|
|
|
|
|
# print summary
|
|
echo "Configuration for $iface:"
|
|
sed 's/^/ /' $conf
|
|
|
|
unconfigured_del $iface
|
|
}
|
|
|
|
is_bridge() {
|
|
[ -e /sys/class/net/$1/bridge ] || [ -e $1.bridge_ports ]
|
|
}
|
|
|
|
is_bond_master() {
|
|
[ -e $1.bond_slaves ]
|
|
}
|
|
|
|
unconfigured_available() {
|
|
local local i= iflist=
|
|
for i in $(unconfigured_list); do
|
|
if ! is_bridge $i && ! is_bond_master $i; then
|
|
iflist="${iflist}${iflist:+ }$i"
|
|
fi
|
|
done
|
|
echo $iflist
|
|
}
|
|
|
|
unconfigured_all_are() {
|
|
local i=
|
|
for i; do
|
|
unconfigured_isin $i || return 1
|
|
done
|
|
return 0
|
|
}
|
|
|
|
config_bridge() {
|
|
local bridge=$1 iflist= i= ports=
|
|
while ! unconfigured_all_done; do
|
|
set -- $(unconfigured_available)
|
|
[ $# -eq 0 ] && return 0;
|
|
ports=$(bridge_list_ports $bridge)
|
|
if [ -n "$ports" ]; then
|
|
echo "Bridge ports in $bridge are: $ports"
|
|
fi
|
|
echo "Available bridge ports are: $@"
|
|
ask "Which port(s) do you want add to bridge $bridge? (or 'done')" $1
|
|
case $resp in
|
|
'abort') return 1;;
|
|
'done') return 0;;
|
|
esac
|
|
for i in $resp; do
|
|
if unconfigured_isin $i; then
|
|
bridge_add_port $bridge $i
|
|
else
|
|
echo "$i is not valid"
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
bond_add_slave() {
|
|
local master=$1 slave=
|
|
shift
|
|
for slave; do
|
|
echo $slave >> $master.bond_slaves
|
|
unconfigured_add $master
|
|
unconfigured_del $slave
|
|
done
|
|
}
|
|
|
|
bond_list_slaves() {
|
|
if [ -r $1.bond_slaves ]; then
|
|
echo $(cat $1.bond_slaves)
|
|
fi
|
|
}
|
|
|
|
config_bond() {
|
|
local master=$1 slaves=
|
|
while ! unconfigured_all_done; do
|
|
set -- $(unconfigured_available)
|
|
[ $# -eq 0 ] && return 0;
|
|
slaves=$(bond_list_slaves $master)
|
|
if [ -n "$slaves" ]; then
|
|
echo "Bond slaves in $master are: $slaves"
|
|
fi
|
|
echo "Available bond slaves are: $@"
|
|
ask "Which slave(s) do you want add to $master? (or 'done')" $1
|
|
case $resp in
|
|
'abort') return 1;;
|
|
'done') return 0;;
|
|
esac
|
|
for i in $resp; do
|
|
if unconfigured_isin $i; then
|
|
bond_add_slave $master $i
|
|
else
|
|
echo "$i is not valid"
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
config_vlan() {
|
|
local iface=$1 vid= raw_device=
|
|
case $iface in
|
|
*.*) raw_device=${iface%.*}
|
|
vid=${iface#*.}
|
|
;;
|
|
vlan*) vid=${iface#vlan}
|
|
ask_which "raw device" "do you want use for $iface" "$(unconfigured_list)"
|
|
echo "$resp" > $iface.raw_device
|
|
return 0
|
|
;;
|
|
esac
|
|
if unconfigured_isin $raw_device || is_bond_master $raw_device; then
|
|
return 0
|
|
fi
|
|
echo "$raw_device is not a valid raw device for $iface"
|
|
return 1
|
|
}
|
|
|
|
usage() {
|
|
cat <<-__EOF__
|
|
usage: setup-interfaces [-bhi]
|
|
|
|
Setup network interfaces
|
|
|
|
options:
|
|
-b Ask for bridging of interfaces
|
|
-h Show this help
|
|
-i Read new contents of ${ROOT}etc/network/interfaces from stdin
|
|
__EOF__
|
|
exit 1
|
|
}
|
|
|
|
iface_help() {
|
|
cat <<-__EOF__
|
|
|
|
Select the interface you wish to configure.
|
|
|
|
For advanced configurations, you can also enter:
|
|
br[0-9]+ (ex: br0) bridge interface
|
|
bridge[0-9]+ (ex: bridge0) bridge interface
|
|
bond[0-9]+ (ex: bond32) bonded interface
|
|
vlan[0-9]+ (ex: vlan371) vlan interface
|
|
eth?.[0-9]+ (ex: eth0.371) vlan interface
|
|
bond?.[0.9]+ (ex: bond0.371) vlan interface
|
|
|
|
You will be asked which physical interface(s) to
|
|
be used for advanced configurations.
|
|
|
|
__EOF__
|
|
}
|
|
prompt_for_interfaces() {
|
|
init_tmpdir TMP
|
|
|
|
cd $TMP
|
|
unconfigured_detect
|
|
|
|
index=1
|
|
while ! unconfigured_all_done; do
|
|
echo "Available interfaces are: $(unconfigured_list)."
|
|
echo "Enter '?' for help on bridges, bonding and vlans."
|
|
ask "Which one do you want to initialize? (or '?' or 'done')" \
|
|
$(unconfigured_get_first)
|
|
iface=$resp
|
|
|
|
case "$iface" in
|
|
"done") break;;
|
|
'?') iface_help; continue;;
|
|
br[0-9]*|bridge[0-9]*|virbr[0-9]*)
|
|
config_bridge $iface || continue;;
|
|
bond[0-9]*.[0-9]*)
|
|
config_bond ${iface%.*} || continue
|
|
config_iface ${iface%.*} $(printf "%.3d~" $index) none
|
|
index=$(( $index + 1 ))
|
|
config_vlan $iface || continue
|
|
;;
|
|
bond[0-9]*)
|
|
config_bond $iface || continue;;
|
|
*.[0-9]*|vlan[0-9]*)
|
|
config_vlan $iface || continue;;
|
|
*) unconfigured_isin $iface || continue;;
|
|
esac
|
|
config_iface $iface $(printf "%.3d~" $index)
|
|
index=$(( $index + 1 ))
|
|
done
|
|
|
|
if [ "$(openrc --sys)" != "LXC" ] || ! ip addr show lo | grep -q 'inet.*127\.0'; then
|
|
echo "type=loopback" > 000~lo.conf
|
|
echo "" > interface
|
|
fi
|
|
hostname=$(cat $ROOT/etc/hostname 2>/dev/null)
|
|
|
|
for i in *.conf ; do
|
|
iface=$(basename $i .conf)
|
|
iface=${iface#[0-9]*~}
|
|
bridge_ports=
|
|
bond_slaves=
|
|
raw_device=
|
|
address=
|
|
type=
|
|
gateway=
|
|
. ./$i
|
|
echo "auto $iface" >> interfaces
|
|
echo "iface $iface inet $type" >> interfaces
|
|
if [ -n "$bridge_ports" ]; then
|
|
PKGS="$PKGS bridge"
|
|
echo -e "\tbridge-ports $bridge_ports" >> interfaces
|
|
fi
|
|
if [ -n "$bond_slaves" ]; then
|
|
PKGS="$PKGS bonding"
|
|
echo -e "\tbond-slaves $bond_slaves" >> interfaces
|
|
fi
|
|
if [ -n "$raw_device" ]; then
|
|
echo -e "\tvlan-raw-device $raw_device" >> interfaces
|
|
fi
|
|
case "$iface" in
|
|
*.[0-9]*|vlan[0-9]*) PKGS="$PKGS vlan";;
|
|
esac
|
|
case $type in
|
|
manual)
|
|
echo -e "\tup ip link set \$IFACE up" >> interfaces
|
|
echo -e "\tdown ip link set \$IFACE down" >> interfaces
|
|
;;
|
|
dhcp)
|
|
[ -n "$hostname" ] \
|
|
&& echo -e "\thostname $hostname" >> interfaces
|
|
;;
|
|
static)
|
|
echo -e "\taddress $address" >> interfaces
|
|
echo -e "\tnetmask $netmask" >> interfaces
|
|
[ "$gateway" ] \
|
|
&& echo -e "\tgateway $gateway" >> interfaces
|
|
;;
|
|
esac
|
|
echo "" >> interfaces
|
|
done
|
|
|
|
while [ "$answer" != "yes" ] && [ "$answer" != "no" ] ; do
|
|
ask "Do you want to do any manual network configuration?" no
|
|
case $resp in
|
|
y) answer=yes;;
|
|
n) answer=no;;
|
|
*) answer=$resp;;
|
|
esac
|
|
done
|
|
|
|
if yesno "$answer"; then
|
|
case "$EDITOR" in
|
|
nano) apk add nano;;
|
|
vim) apk add vim;;
|
|
esac
|
|
${EDITOR:-vi} interfaces
|
|
fi
|
|
|
|
if [ -n "$PKGS" ]; then
|
|
apk add --quiet $PKGS
|
|
fi
|
|
|
|
mkdir -p $ROOT/etc/network
|
|
cp interfaces $ROOT/etc/network/
|
|
}
|
|
|
|
auto_setup() {
|
|
local iface
|
|
local hostname=$(cat $ROOT/etc/hostname 2>/dev/null)
|
|
for iface in $(available_ifaces); do
|
|
if [ "$(cat /sys/class/net/$iface/operstate)" = "up" ]; then
|
|
break
|
|
fi
|
|
done
|
|
[ -z "$iface" ] && return 0
|
|
cat >$ROOT/etc/network/interfaces <<-EOF
|
|
auto lo
|
|
iface lo inet loopback
|
|
|
|
auto $iface
|
|
iface $iface inet dhcp
|
|
EOF
|
|
if [ -n "$hostname" ]; then
|
|
echo -e "\thostname $hostname" >> $ROOT/etc/network/interfaces
|
|
fi
|
|
}
|
|
|
|
ask_bridge=
|
|
is_xen_dom0 && ask_bridge=1
|
|
|
|
while getopts "abhip:" opt; do
|
|
case $opt in
|
|
a) auto=1;;
|
|
b) ask_bridge=1;;
|
|
h) usage;;
|
|
i) STDINPUT=1;;
|
|
p) ROOT=$OPTARG;;
|
|
esac
|
|
done
|
|
|
|
mkdir -p $ROOT/etc/network
|
|
if [ "$STDINPUT" = "1" ]; then
|
|
cat > $ROOT/etc/network/interfaces
|
|
elif [ -n "$auto" ]; then
|
|
auto_setup
|
|
else
|
|
prompt_for_interfaces
|
|
fi
|