#!/bin/bash # # Create/delete macvtap interfaces # usage () { echo -e "Usage:\t$0 -m -i [ -u ]" echo -e "\t\t-d -m " echo -e "\t\t-d -t " exit 1 } justincasedel () { local tname=$1 [ -z "$tname" ] && exit 1 ip link del dev $tname 2>&1 >/dev/null exit 15 } createmacvtap () { local iface=$1 local macaddr=$2 local tname=$( echo "$(date)$$" | md5sum ) tname="vm${tname:0:6}" [ -z "$iface" -o -z "$macaddr" ] && exit 10 [[ "$macaddr" =~ ^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$ ]] || exit 11 ip link add link $iface name $tname type macvtap [ $? -ne 0 ] && justincasedel $tname ip link set addr $macaddr dev $tname [ $? -ne 0 ] && justincasedel $tname ip link set up dev $tname [ $? -ne 0 ] && justincasedel $tname echo $tname } deletemacvtap () { local tname=$1 [ -z "$tname" ] && exit 10 ip link del dev $tname [ $? -ne 0 ] && exit 15 return 0 } getindexbyname () { local tname=$1 [ -z "$tname" ] && exit 20 ip link show | grep $tname | sed "s/^\([0-9]*\): $tname.*/\1/" } getnamebyindex () { local tidx=$1 [ -z "$tidx" ] && exit 20 ip link show | grep -e "^$tidx:" | sed "s/^$tidx: \(.\{1,8\}\)@.*/\1/" } getnamebyaddr () { local macaddr=$1 [[ "$macaddr" =~ ^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$ ]] || exit 20 ip li sh | grep -B1 $macaddr | head -n1 | sed "s/^[0-9]*: \(.\{1,8\}\)@.*/\1/" } chowndev () { local tidx=$1 local user=$2 [ -z "$tidx" -o -z "$user" ] && exit 20 sleep 1 chown $user /dev/tap$tidx # for i in {1..5}; do # [ -n "$( find /dev -user $user -name tap$tidx )" ] && break # chown $user /dev/tap$tidx # sleep 1 # done } [ $# -eq 0 ] && usage # parse options while getopts ":dm:i:u:t:" opt; do case $opt in d) delmacvtap=1 ;; m) macaddr="$OPTARG" ;; i) iface="$OPTARG" ;; u) owner="$OPTARG" ;; t) devindex="$OPTARG" ;; \?) usage ;; :) echo "Option -$OPTARG requires an argument." >&2 usage ;; esac done # request processing if [ "x$delmacvtap" = "x1" ]; then if [ -n "$devindex" ]; then devname=$( getnamebyindex "$devindex" ) || exit $? elif [ -n "$macaddr" ]; then devname=$( getnamebyaddr "$macaddr" ) || exit $? else exit 30 fi deletemacvtap "$devname" else devname=$( createmacvtap "$iface" "$macaddr" ) || exit $? devidx=$( getindexbyname "$devname" ) || exit $? [ -n "$owner" ] && chowndev "$devidx" "$owner" echo "/dev/tap$devidx" fi