406 lines
13 KiB
Bash
406 lines
13 KiB
Bash
#!/bin/sh
|
|
#-------------------------------------------------------------------------+
|
|
# Copyright (C) 2016 Matt Churchyard (churchers@gmail.com)
|
|
# All rights reserved
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted providing that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
# creaate bridge interface for a standard switch
|
|
#
|
|
# @param string _name name of the switch
|
|
#
|
|
switch::standard::init(){
|
|
local _name="$1"
|
|
local _id _addr _mtu _len _ifconf
|
|
|
|
# see if it already exists
|
|
switch::standard::id "_id" "${_name}" && return 0
|
|
|
|
# get the length of the switch name
|
|
# it's useful for other utilities to use switch name as interface name
|
|
# as it's static. can't do that if it's > 12 chars
|
|
_len=$(echo -n "${_name}" | wc -m)
|
|
|
|
if [ ${_len} -le 12 ]; then
|
|
_ifconf="name vm-${_name}"
|
|
else
|
|
_ifconf="descr vm/${_name}"
|
|
fi
|
|
|
|
# create a bridge for this switch
|
|
_id=$(ifconfig bridge create ${_ifconf} group vm-switch up 2>/dev/null)
|
|
[ $? -eq 0 ] || util::err "failed to create bridge interface for switch ${_name}"
|
|
|
|
switch::set_viid "${_name}" "${_id}"
|
|
|
|
# randomise mac if feature is available
|
|
[ ${VERSION_BSD} -ge 1102000 ] && ifconfig "${_id}" link random
|
|
|
|
# try to set ip address
|
|
config::core::get "_addr" "addr_${_name}"
|
|
[ -n "${_addr}" ] && ifconfig "${_id}" inet ${_addr} 2>/dev/null
|
|
config::core::get "_addr" "addr6_${_name}"
|
|
[ -n "${_addr}" ] && ifconfig "${_id}" inet6 ${_addr} 2>/dev/null
|
|
|
|
# custom mtu?
|
|
config::core::get "_mtu" "mtu_${_name}"
|
|
[ -n "${_mtu}" ] && ifconfig "${_id}" mtu ${_mtu}
|
|
|
|
# add member interfaces
|
|
switch::standard::__add_members "${_name}" "${_id}"
|
|
}
|
|
|
|
# show the configuration details for a switch
|
|
#
|
|
# @param string _name the switch name
|
|
# @param string _format output format
|
|
#
|
|
switch::standard::show(){
|
|
local _name="$1"
|
|
local _format="$2"
|
|
local _id _vlan _ports _addr _mtu _priv
|
|
|
|
switch::find "_id" "${_name}"
|
|
config::core::get "_ports" "ports_${_name}"
|
|
config::core::get "_vlan" "vlan_${_name}"
|
|
config::core::get "_addr" "addr_${_name}"
|
|
config::core::get "_mtu" "mtu_${_name}"
|
|
config::core::get "_priv" "private_${_name}" "no"
|
|
|
|
printf "${_format}" "${_name}" "standard" "${_id:--}" "${_addr:--}" "${_priv}" "${_mtu:--}" \
|
|
"${_vlan:--}" "${_ports:--}"
|
|
}
|
|
|
|
# create a standard virtual switch
|
|
#
|
|
switch::standard::create(){
|
|
|
|
# store configuration
|
|
config::core::set "switch_list" "${_switch}" "1"
|
|
config::core::set "type_${_switch}" "standard"
|
|
|
|
[ -n "${_if}" ] && config::core::set "ports_${_switch}" "${_if}"
|
|
[ -n "${_vlan}" ] && config::core::set "vlan_${_switch}" "${_vlan}"
|
|
[ -n "${_addr}" ] && config::core::set "addr_${_switch}" "${_addr}"
|
|
[ -n "${_priv}" ] && config::core::set "private_${_switch}" "${_priv}"
|
|
[ -n "${_mtu}" ] && config::core::set "mtu_${_switch}" "${_mtu}"
|
|
|
|
config::core::load
|
|
switch::standard::init "${_switch}"
|
|
}
|
|
|
|
# destroy a standard switch
|
|
#
|
|
# @param string _switch name of the switch to destroy
|
|
#
|
|
switch::standard::remove(){
|
|
local _switch="$1"
|
|
local _id
|
|
|
|
# get the bridge id
|
|
switch::standard::id "_id" "${_switch}"
|
|
[ $? -eq 0 ] || return 1
|
|
|
|
# remove all member interfaces
|
|
switch::standard::__remove_members "${_switch}" "${_id}"
|
|
|
|
# destroy the bridge
|
|
ifconfig "${_id}" destroy >/dev/null 2>&1
|
|
}
|
|
|
|
# add a new interface to this switch
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param string _if the interface to add
|
|
#
|
|
switch::standard::add_member(){
|
|
local _switch="$1"
|
|
local _if="$2"
|
|
local _id _vlan _mtu
|
|
|
|
switch::standard::id "_id" "${_switch}" || util::err "unable to locate switch id"
|
|
config::core::get "_vlan" "vlan_${_switch}"
|
|
config::core::get "_mtu" "mtu_${_switch}"
|
|
switch::standard::__configure_port "${_switch}" "${_id}" "${_if}" "${_vlan}" "${_mtu}"
|
|
config::core::set "ports_${_switch}" "${_if}" "1"
|
|
}
|
|
|
|
# remove a member interface from this switch
|
|
#
|
|
# @param string _switch name of the switch
|
|
# @param string _if the interface to remove
|
|
#
|
|
switch::standard::remove_member(){
|
|
local _switch="$1"
|
|
local _if="$2"
|
|
local _id _vlan
|
|
|
|
switch::standard::id "_id" "${_switch}" || util::err "unable to locate switch id"
|
|
config::core::remove "ports_${_switch}" "${_if}"
|
|
config::core::get "_vlan" "vlan_${_switch}"
|
|
switch::standard::__unconfigure_port "${_switch}" "${_id}" "${_if}" "${_vlan}"
|
|
}
|
|
|
|
# set vlan id
|
|
#
|
|
# @param string _switch name of switch
|
|
# @param int _vlan vlan id to set
|
|
#
|
|
switch::standard::vlan(){
|
|
local _switch="$1"
|
|
local _vlan="$2"
|
|
local _id
|
|
|
|
switch::standard::id "_id" "${_switch}" || util::err "unable to locate switch id"
|
|
switch::standard::__remove_members "${_switch}" "${_id}"
|
|
|
|
# update configuration
|
|
if [ "${_vlan}" = "0" ]; then
|
|
config::core::remove "vlan_${_switch}"
|
|
else
|
|
config::core::set "vlan_${_switch}" "${_vlan}"
|
|
fi
|
|
|
|
config::core::load
|
|
switch::standard::__add_members "${_switch}" "${_id}"
|
|
}
|
|
|
|
# set or remove ip address
|
|
#
|
|
# @param string _swtich name of the switch
|
|
# @param string _addr address or "none"
|
|
# @scope _id switch if from parent switch::address
|
|
#
|
|
switch::standard::address(){
|
|
local _switch="$1"
|
|
local _addr="$2"
|
|
local _curr
|
|
|
|
if [ "${_addr}" = "none" ]; then
|
|
|
|
config::core::get "_curr" "addr_${_switch}"
|
|
[ $? -eq 0 ] || util::err "unable to locate an existing address for this switch"
|
|
|
|
config::core::remove "addr_${_switch}"
|
|
ifconfig "${_id}" "${_curr}" delete
|
|
else
|
|
|
|
config::core::set "addr_${_switch}" "${_addr}"
|
|
ifconfig "${_id}" "${_addr}"
|
|
fi
|
|
}
|
|
|
|
# add all member interfaces to a switch
|
|
#
|
|
# @param string _switch the name of the switch
|
|
# @param string _id interface id for the switch
|
|
#
|
|
switch::standard::__add_members(){
|
|
local _switch="$1"
|
|
local _id="$2"
|
|
local _ports _vlan _port _mtu
|
|
|
|
# get the id if not provided
|
|
if [ -z "${_id}" ]; then
|
|
switch::standard::id "_id" "${_switch}" || util:err "failed to get switch id while adding members"
|
|
fi
|
|
|
|
config::core::get "_ports" "ports_${_switch}"
|
|
config::core::get "_vlan" "vlan_${_switch}"
|
|
config::core::get "_mtu" "mtu_${_switch}"
|
|
|
|
if [ -n "${_ports}" ]; then
|
|
for _port in ${_ports}; do
|
|
switch::standard::__configure_port "${_switch}" "${_id}" "${_port}" "${_vlan}" "${_mtu}"
|
|
done
|
|
fi
|
|
}
|
|
|
|
# remove member interfaces from a switch
|
|
#
|
|
# @param string _switch the name of the switch
|
|
# @param string _id bridge id if already known
|
|
#
|
|
switch::standard::__remove_members(){
|
|
local _switch="$1"
|
|
local _id="$2"
|
|
local _ports _port _vlan
|
|
|
|
# get id if not given to us
|
|
if [ -z "${_id}" ]; then
|
|
switch::standard::id "_id" "${_switch}"
|
|
[ $? -eq 0 ] || util::err "failed to get switch id while removing members"
|
|
fi
|
|
|
|
# get full port list
|
|
config::core::get "_ports" "ports_${_switch}"
|
|
config::core::get "_vlan" "vlan_${_switch}"
|
|
|
|
if [ -n "${_ports}" ]; then
|
|
for _port in ${_ports}; do
|
|
switch::standard::__unconfigure_port "${_switch}" "${_id}" "${_port}" "${_vlan}"
|
|
done
|
|
fi
|
|
}
|
|
|
|
# configure a local port for our bridge
|
|
#
|
|
# @param string _switch the switch to add port to
|
|
# @param string _id the bridge id of the switch
|
|
# @param string _port the interface to add
|
|
# @param int _vlan vlan number if assigned to this switch
|
|
# @param int _mtu custom mtu to use for this port
|
|
#
|
|
switch::standard::__configure_port(){
|
|
local _switch="$1"
|
|
local _id="$2"
|
|
local _port="$3"
|
|
local _vlan="$4"
|
|
local _mtu="$5"
|
|
local _viface _vname
|
|
|
|
# try to set mtu of port?
|
|
[ -n "${_mtu}" ] && ifconfig "${_port}" mtu ${_mtu} >/dev/null 2>&1
|
|
|
|
# vlan enabled?
|
|
if [ -n "${_vlan}" ]; then
|
|
|
|
# see if vlan interface already exists
|
|
_vname="${_port}.${_vlan}"
|
|
switch::standard::id "_viface" "${_vname}"
|
|
|
|
# create if needed
|
|
if [ $? -ne 0 ]; then
|
|
# use our id as the interface name here.
|
|
# it should always be a valid name and interface.vlan-id is much easier to understand in ifconfig
|
|
# than a bunch of vlanX interfaces
|
|
_viface=$(ifconfig vlan create vlandev "${_port}" vlan "${_vlan}" descr "vm-vlan/${_switch}/${_vname}" name "${_vname}" group vm-vlan up 2>/dev/null)
|
|
[ $? -eq 0 ] || util::err "failed to create vlan interface for port ${_port} on switch ${_switch}"
|
|
fi
|
|
|
|
switch::set_viid "${_vname}" "${_viface}"
|
|
ifconfig ${_id} addm ${_viface} >/dev/null 2>&1
|
|
else
|
|
# add to bridge, nice and simple :)
|
|
ifconfig ${_id} addm ${_port} >/dev/null 2>&1
|
|
fi
|
|
|
|
[ $? -eq 0 ] || util::err "failed to add member ${_port} to the virtual switch ${_switch}"
|
|
}
|
|
|
|
# unconfigure a local port
|
|
#
|
|
# @param string _switch the switch to remove port from
|
|
# @param string _id the bridge id of the switch
|
|
# @param string _port the interface to remove
|
|
# @param string _vlan vlan number if assigned to this switch
|
|
#
|
|
switch::standard::__unconfigure_port(){
|
|
local _switch="$1"
|
|
local _id="$2"
|
|
local _port="$3"
|
|
local _vlan="$4"
|
|
local _vid
|
|
|
|
if [ -n "${_vlan}" ]; then
|
|
# get vlan interface
|
|
switch::standard::id "_vid" "${_port}.${_vlan}"
|
|
|
|
# remove the vlan interface, it will be removed from bridge automatically
|
|
[ $? -eq 0 ] && ifconfig ${_vid} destroy >/dev/null 2>&1
|
|
else
|
|
ifconfig ${_id} deletem ${_port} >/dev/null 2>&1
|
|
fi
|
|
}
|
|
|
|
# get the id for a standard switch
|
|
# this returns the associated bridge name
|
|
#
|
|
# @param string _var variable to put id into
|
|
# @param string _switch the switch to look for
|
|
# @return 0 on success
|
|
#
|
|
switch::standard::id(){
|
|
switch::find "$1" "$2"
|
|
}
|
|
|
|
# creates a standard tap interface for a guest
|
|
# relies heavily on variables set in the main vm::run function
|
|
#
|
|
# @modifies _func _devices
|
|
# @return 1 if we don't get a tap device
|
|
#
|
|
switch::standard::provision(){
|
|
local _tap _custom_tap _sid _mtu _member_type _iname
|
|
|
|
config::get "_custom_tap" "network${_num}_device"
|
|
config::get "_iname" "network${_num}_name"
|
|
|
|
# create interface
|
|
if [ -n "${_custom_tap}" ]; then
|
|
_tap="${_custom_tap}"
|
|
elif [ -n "${_iname}" ]; then
|
|
_tap=$(ifconfig tap create name "${_iname}")
|
|
else
|
|
_tap=$(ifconfig tap create)
|
|
fi
|
|
|
|
[ -z "${_tap}" ] && return 1;
|
|
|
|
util::log "guest" "${_name}" "initialising network device ${_tap}"
|
|
ifconfig "${_tap}" descr "vmnet/${_name}/${_num}/${_switch:-custom}" group vm-port >/dev/null 2>&1
|
|
|
|
if [ -n "${_switch}" ]; then
|
|
switch::id "_sid" "${_switch}"
|
|
|
|
# should this be a span member?
|
|
_member_type="addm"
|
|
config::yesno "network${_num}_span" && _member_type="span"
|
|
|
|
if [ -n "${_sid}" ]; then
|
|
_mtu=$(ifconfig "${_sid}" | head -n1 | awk '{print $NF}')
|
|
|
|
if [ "${_mtu}" != "1500" ]; then
|
|
util::log "guest" "${_name}" "setting mtu of ${_tap} to ${_mtu}"
|
|
ifconfig "${_tap}" mtu "${_mtu}" >/dev/null 2>&1
|
|
fi
|
|
|
|
util::log "guest" "${_name}" "adding ${_tap} -> ${_sid} (${_switch} ${_member_type})"
|
|
ifconfig "${_sid}" "${_member_type}" "${_tap}" >/dev/null 2>&1 || util::log "guest" "${_name}" "failed to add ${_tap} to ${_sid}"
|
|
|
|
util::log "guest" "${_name}" "bring up ${_tap} -> ${_sid} (${_switch} ${_member_type})"
|
|
ifconfig "${_tap}" up >/dev/null 2>&1 || util::log "guest" "${_name}" "failed to bring up ${_tap} in ${_sid}"
|
|
|
|
# set private if configured
|
|
switch::is_private "${_switch}" && ifconfig "${_sid}" "private" "${_tap}" >/dev/null 2>&1
|
|
else
|
|
util::log "guest" "${_name}" "failed to find virtual switch '${_switch}'"
|
|
fi
|
|
fi
|
|
|
|
_devices="${_devices} -s ${_slot}:${_func},${_emulation},${_tap}"
|
|
[ -n "${_mac}" ] && _devices="${_devices},mac=${_mac}"
|
|
|
|
_func=$((_func + 1))
|
|
[ -z "${_custom_tap}" ] && _taplist="${_taplist}${_taplist:+ }${_tap}"
|
|
}
|