From owner-svn-src-all@FreeBSD.ORG Sun Oct 24 22:59:38 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E65EE106566B; Sun, 24 Oct 2010 22:59:38 +0000 (UTC) (envelope-from julian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D37B38FC1A; Sun, 24 Oct 2010 22:59:38 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o9OMxcdt043533; Sun, 24 Oct 2010 22:59:38 GMT (envelope-from julian@svn.freebsd.org) Received: (from julian@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9OMxcH7043530; Sun, 24 Oct 2010 22:59:38 GMT (envelope-from julian@svn.freebsd.org) Message-Id: <201010242259.o9OMxcH7043530@svn.freebsd.org> From: Julian Elischer Date: Sun, 24 Oct 2010 22:59:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214306 - in head/share/examples: jails netgraph X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 24 Oct 2010 22:59:39 -0000 Author: julian Date: Sun Oct 24 22:59:38 2010 New Revision: 214306 URL: http://svn.freebsd.org/changeset/base/214306 Log: Add two scripts that demonstrate how to make and hook together jails using teh vortual networking feature. Submitted by: Yavuz Gokirmak MFC after: 2 weeks Added: head/share/examples/jails/ head/share/examples/jails/README (contents, props changed) head/share/examples/netgraph/virtual.chain (contents, props changed) head/share/examples/netgraph/virtual.lan (contents, props changed) Added: head/share/examples/jails/README ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/examples/jails/README Sun Oct 24 22:59:38 2010 (r214306) @@ -0,0 +1,5 @@ +# $FreeBSD$ + +See under share/examples/netgraph for some examples of +making and hooking together jails using netgraph as the +virtual networking fabric. Added: head/share/examples/netgraph/virtual.chain ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/examples/netgraph/virtual.chain Sun Oct 24 22:59:38 2010 (r214306) @@ -0,0 +1,373 @@ +#!/bin/sh +# +# Copyright (c) 2010, Yavuz Gokirmak +# +# All rights reserved. +# +# This source code may be used, modified, copied, distributed, and +# sold, in both source and binary form provided that the above +# copyright and these terms are retained, verbatim, as the first +# lines of this file. Under no circumstances is the author +# responsible for the proper functioning of the software nor does +# the author assume any responsibility for damages incurred with +# its use. +# +# $FreeBSD$ +# +# +# This script creates and connects n router like nodes. Complex wide +# area topologies can be created with the help of script. +# +# Virtual nodes are generated via jails and network connections are +# established using ng_eiface(4) node types. +# +# To use this script: +# +# 0. Make your own copy of this example script. +# +# 1. Edit the definition of ${TARGET_TOPOLOGY} to define your virtual +# nodes. Virtual topology definition includes node names and their +# IP address. Target top. sytax: ( name|ip<->name|ip ... ) +# Example 1: ( n1|10.0.2.1/30<->n2|10.0.2.2/30 ...) +# Example 2: ( n1|2001:b90::14a/125<->n1|2001:b90::14b/125 ...) +# +# 2. Run this script with "start" as the command line argument. +# +# 3. Add necessary static route commands for each virtual node. For +# example assume you have three virtual nodes connected each other +# llike a chain ( n1 is connected to n2, n2 is connecte to n3 ). +# In order to estabklish connectivity among these virtual nodes, +# you have to add default routes to node n1 and node n3. Example +# static route command is: +# STATIC_ROUTE0="jexec n1 route add -inet default 10.0.2.2" +# STATIC_ROUTE1="jexec n3 route add -inet default 10.0.2.5" +# After defining default routes with above format you have to set +# the total number of static route commands as: +# STATIC_ROUTE_CNT=2 +# +# 4. Stop bridging by running this script with "stop" as the +# command line argument. +# +# 5. This cript uses a template file in order to carry information +# between start and stop calls. +# In the start call, the netgraph interfaces and jails are created. +# At the stop phase, all created objects should be removed. +# DO NOT delete the temporary file between the start and stop phases. +# +# Target Topology: +# +# +---------------+ +---------------------------------------------+ +# | n1 (vimage) | | n2 (vimage) | +# | | | | +# | +-----------+ | | +-----------+ +-----------+ +-----------+ | +# | | ngeth0 | | | | ngeth1 | | ngeth2 | | ngeth4 | | +# | |(ng_eiface)| | | |(ng_eiface)| |(ng_eiface)| |(ng_eiface)| | +# | +--+-----+--+ | | +--+-----+--+ +--+-----+--+ +--+-----+--+ | +# | |ether| | | |ether| |ether| |ether| | +# | +-X---+ | | +--X--+ +--X--+ +--X--+ | +# +-------X-------+ +------X--------------X---------------X-------+ +# X X X X +# X X X X +# XXXXXXXXXXXXXXX X X +# X X +# +--------X------+ +--------X------+ +# | -+--X--+- | | -+--X--+- | +# | |ether| | | |ether| | +# | +--+-----+--+ | | +--+-----+--+ | +# | | ngeth3 | | | | ngeth5 | | +# | |(ng_eiface)| | | |(ng_eiface)| | +# | +-----------+ | | +-----------+ | +# | | | | +# | n3 (vimage) | | n4 (vimage) | +# +---------------+ +---------------+ +# +# +# + +# List the names of virtual nodes and their IP addresses. Use ':' +# character to seperate node name from node IP address and netmask. + +TARGET_TOPOLOGY="n1|10.0.2.1/30<->n2|10.0.2.2/30 n2|10.0.2.5/30<->n3|10.0.2.6/30 n2|10.0.2.9/30<->n4|10.0.2.10/30" +STATIC_ROUTE0="jexec n1 route add -inet default 10.0.2.2" +STATIC_ROUTE1="jexec n3 route add -inet default 10.0.2.5" +STATIC_ROUTE2="jexec n4 route add -inet default 10.0.2.9" +STATIC_ROUTE_CNT=3 + +# MAC manifacturer prefix. This can be modified according to needs. +MAC_PREFIX="00:1d:92" + +# Temporary file is important for proper execution of script. +TEMP_FILE="/var/tmp/.virtual.chain.tmp" + +# Set root directory for jails to be created. +JAIL_PATH="/usr/jails/router" + + +#################################################################### +#### Nothing below this point should need to be modified. #### +#################################################################### + + +# Start/restart routine. +virtual_chain_start() { + + # Load netgraph KLD's as necessary. + + for KLD in ng_ether ng_bridge ng_eiface; do + if ! kldstat -v | grep -qw ${KLD}; then + echo -n "Loading ${KLD}.ko... " + kldload ${KLD} || exit 1 + echo "done" + fi + done + + # Reset all interfaces and jails. If temporary file can not be found + # script assumes that there is no previous configuration. + + if [ ! -e ${TEMP_FILE} ]; then + echo "No previous configuration(${TEMP_FILE}) found to clean-up." + else + echo -n "Cleaning previous configuration..." + virtual_chain_stop + echo "done" + fi + + # Create temporary file for usage. This file includes generated + # interface names and jail names. All bridges, interfaces and jails + # are written to file while created. In clean-up process written + # objects are cleaned (i.e removed) from system. + + if [ -e ${TEMP_FILE} ]; then + touch ${TEMP_FILE} + fi + + + # Attach other interfaces as well. + for CONNECTION in ${TARGET_TOPOLOGY}; do + + # Virtual connections are defined in TARGET_TOPOLOGY variable. + # They have the form of 'nodeName|IPaddr'. Below two lines split + + PEER1=`echo ${CONNECTION} | awk -F"<->" '{print $1}'` + PEER1_NAME=`echo ${PEER1} | awk -F"|" '{print $1}'` + PEER1_IP=`echo ${PEER1} | awk -F"|" '{print $2}'` + + PEER2=`echo ${CONNECTION} | awk -F"<->" '{print $2}'` + PEER2_NAME=`echo ${PEER2} | awk -F"|" '{print $1}'` + PEER2_IP=`echo ${PEER2} | awk -F"|" '{print $2}'` + + # !!! if not created already.. + # Create virtual node (jail) with given name and using + # JAIL_PATH as root directory for jail. + + virtual_chain_create_peer_if_necessary ${PEER1_NAME} + virtual_chain_create_peer_if_necessary ${PEER2_NAME} + + # create an interface for peer with the given peer IP. Get interface + # for future use; you will connect this interface to the other + # peers' (PEER2) interface. + virtual_chain_create_interface_with_ip ${PEER1_NAME} ${PEER1_IP} + PEER1_INTERFACE=${RET_INTERFACE} + + # create an interface for peer with the given peer IP. Get interface + # for future use; you will connect this interface to the other + # peers' (PEER2) interface. + virtual_chain_create_interface_with_ip ${PEER2_NAME} ${PEER2_IP} + PEER2_INTERFACE=${RET_INTERFACE} + + # Connect virtual interface to other interface. Syntax is : + # ngctl connect INTERFACE1: INTERFACE2: ether ether. + + echo -n "Connecting ${PEER1_INTERFACE}:ether to ${PEER2_INTERFACE}:ether..." + ngctl connect ${PEER1_INTERFACE}: ${PEER2_INTERFACE}: ether ether \ + || exit 1 + echo "done" + + done + + # Executes static route add commands. + i=0 + while [ $i != $STATIC_ROUTE_CNT ]; do + eval ROUTE=\${STATIC_ROUTE${i}} + ret=`${ROUTE}` + i=`expr $i + 1` + done + + echo "Virtual WAN established succesfully!" +} + +virtual_chain_create_interface_with_ip() { + + NODE_NAME=$1 + NODE_IP=$2 + + # Create a ng_eiface object for virtual node. ng_eiface + # object has a hook that can be connected to one of bridge + # links. After creating interface get its automatically + # generated name for further usage. + + echo "Creating eiface interface for virtual node ${NODE_NAME}." + ngctl mkpeer eiface ether ether + EIFACE=`ngctl l | grep ngeth | tail -n 1| awk '{print $2}'` + echo "Interface ${EIFACE} is created." + + # Write name of the interface to temp file. Clean-up procedure + # will use this name to shutdown interface. + + echo "interface ${EIFACE}" >> ${TEMP_FILE} + + # Move virtual interface to virtual node. Note that Interface + # name will not be changed at the end of this movement. Moved + # interface can be seen at the output of ifconfig command in + # jail: 'jexec jailname ifconfig' + + echo "Moving ${EIFACE} to ${NODE_NAME}" + ifconfig ${EIFACE} vnet ${NODE_NAME} + + # Make lo0 interface localhost. + jexec ${NODE_NAME} ifconfig lo0 localhost + + # Generate a random mac address for virtual interface. First + # three octets can be changed by user. Last three octets are + # generated randomly. + M4=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \ + awk '{ print $1 % 256 }'` + M5=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \ + awk '{ print $1 % 256 }'` + M6=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \ + awk '{ print $1 % 256 }'` + + MAC=`printf ${MAC_PREFIX}:%02x:%02x:%02x ${M4} ${M5} ${M6}` + + # Set the link address (mac address) of virtual interface in + # virtual node to randomly generated MAC. + echo "Setting MAC address of ${EIFACE} to '${MAC}'" + jexec ${NODE_NAME} ifconfig ${EIFACE} link $MAC + + # Either IPv4 or IPv6 can be used in this script. Ifconfig + # IP setting syntax differs slightly for two IP versions. + # For version 4 'inet' keyword is used whereas for version 6 + # 'inet6' is used. Below line tries to decide which IP version + # is given and sets IPVER to 'inet' or 'inet6'. + + IPVER=`echo ${NODE_IP} | awk -F"." '{ split($4,last,"/"); \ + if( NF==4 && $1>0 && $1<256 && $2<256 && $3<256 && \ + last[1]<256) print "inet"; else print "inet6"}'` + + # Set IP address of virtual interface in virtual node. + echo "Setting IP address of ${EIFACE} to '${NODE_IP}'" + jexec ${NODE_NAME} ifconfig ${EIFACE} ${IPVER} ${NODE_IP} + + RET_INTERFACE=${EIFACE} +} + +virtual_chain_create_peer_if_necessary() { + + if ! grep -q $1 ${TEMP_FILE} ; then + + echo -n "Creating virtual node (jail) ${1}..." + jail -c vnet name=${1} host.hostname=${1} \ + path=${JAIL_PATH} persist + jexec ${1} sysctl -w net.inet.ip.forwarding=1 + jexec ${1} sysctl -w net.inet6.ip6.forwarding=1 + echo "done" + + # Write name of the jail to temp file. Clean-up + # procedure will use this name to remove jail. + + echo "node ${1}" >> ${TEMP_FILE} + fi + +} + + +# Stop routine. +virtual_chain_stop() { + + if [ ! -e ${TEMP_FILE} ]; then + echo "Nothing to stop! ${TEMP_FILE}: temp file not found" + else + + echo -n "Shutdown bridge interface.." + OBJECTS=`cat ${TEMP_FILE} | grep bridge | awk '{print $2}'` + for BRIDGE in ${OBJECTS}; do + ngctl shutdown ${BRIDGE}: >/dev/null 2>&1 + done + echo "done" + + echo -n "Shutdown all eiface interfaces..." + OBJECTS=`cat ${TEMP_FILE} | grep interface | awk '{print $2}'` + for INTERFACE in ${OBJECTS}; do + ngctl shutdown ${INTERFACE}: >/dev/null 2>&1 + done + echo "done" + + echo -n "Removing all jails..." + OBJECTS=`cat ${TEMP_FILE} | grep node | awk '{print $2}'` + for NODE in ${OBJECTS}; do + jail -r ${NODE} + done + echo "done" + + echo "Removing tempfile ${TEMP_FILE}" + rm ${TEMP_FILE} + fi + echo "Virtual LAN objects removed succesfully!" + +} + +virtual_chain_usage() { + echo "usage: $0 start [target_topology]" + echo " : $0 [ stop | help ]" +} + + +# Main entry point. + + +case $# in + 1) + case $1 in + start) + echo -n "Creating default target topology:" + echo " ${TARGET_TOPOLOGY}" + virtual_chain_start + ;; + stop) + + if [ ! -e ${TEMP_FILE} ]; then + echo -n "Noting to stop! ${TEMP_FILE}:" + echo " temp file not found" + else + virtual_chain_stop + fi + ;; + help) + virtual_chain_usage + exit 1 + ;; + *) + virtual_chain_usage + exit 1 + + esac + ;; + 2) + case $1 in + start) + TARGET_TOPOLOGY=$2 + echo -n "Creating target topology:" + echo "${TARGET_TOPOLOGY}" + virtual_chain_start + ;; + *) + virtual_chain_usage + exit 1 + esac + ;; + + *) + virtual_chain_usage + exit 1 +esac + Added: head/share/examples/netgraph/virtual.lan ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/examples/netgraph/virtual.lan Sun Oct 24 22:59:38 2010 (r214306) @@ -0,0 +1,360 @@ +#!/bin/sh +# +# Copyright (c) 2010, Yavuz Gokirmak +# +# All rights reserved. +# +# This source code may be used, modified, copied, distributed, and +# sold, in both source and binary form provided that the above +# copyright and these terms are retained, verbatim, as the first +# lines of this file. Under no circumstances is the author +# responsible for the proper functioning of the software nor does +# the author assume any responsibility for damages incurred with +# its use. +# +# $FreeBSD$ + +# +# This script adds virtual nodes to one of the physical interfaces +# visible on your local area network (LAN). Virtual nodes seems real +# to external observers. +# If traceroute is executed to one of virtual nodes, the IP +# address of the physical interface will not be seen in the output. +# Virtual nodes are generated via jails and network connections are +# established using ng_bridge(4) and ng_eiface(4) node types. +# +# To use this script: +# +# 0. Make your own copy of this example script. +# +# 1. Edit the definition of ${ETHER_INTF} as described below +# to define your real interface connected to the LAN. Virtual nodes +# will placed on the same physical network as this interface. +# +# 2. Edit the definition of ${TARGET_TOPOLOGY} to define your virtual +# nodes. Virtual topology definition includes node names and their +# IP address. Target top. sytax: ( node1|ip1/24 node2|ip2/24 ... ) +# Example 1: ( n1|122.122.122.12/24, n2|122.122.122.13/24 ...) +# Example 2: ( n1|2001:b90::14a/125, n1|2001:b90::14b/125 ...) +# +# 3. Run this script with "start" as the command line argument. +# +# 4. Stop bridging by running this script with "stop" as the +# command line argument. +# +# 5. This cript uses a template file in order to carry information +# between start and stop calls. +# In the start call, the netgraph interfaces and jails are created. +# At the stop phase, all created objects should be removed. +# DO NOT delete the temporary file between the start and stop phases. +# +# To add virtual nodes for multiple independent LANs, create multiple +# copies of this script with different variable definitions. +# +# Target Topology: +# +# +# +---------------+ +---------------+ +---------------+ +# | n0 (vimage) | | n1 (vimage) | | nk (vimage) | +# | | | | | | +# | +-----------+ | | +-----------+ | | +-----------+ | +# | | ngeth0 | | | | ngeth1 | | | | ngethk | | +# | |(ng_eiface)| | | |(ng_eiface)| | | |(ng_eiface)| | +# | +--+-----+--+ | | +--+-----+--+ | | +--+-----+--+ | +# | |ether| | | |ether| | | |ether| | +# | +--X--+ | | +--X--+ | | +---X-+ | +# +-----+ +--------\------+ +--------\------+ +-------/-------+ +# |upper|----\ \ip_addr \ip_addr /ip_addr +# +-+-----+--+ \ \ \ \ +# | em0 | \ +--------+ +-+ \ +# |(ng_ether)| +-----------+ \ \ \ +# +-+-----+--+ \ \ / \ +# |lower| +---------\ \ \ / / +# +--X--+ / O--X--O O-X---O O---X-O O--X--O O---X---O +# \ | |link0| |link1| |link2| |link3| |linkk+2| +# \ / +-O-----O-O-----O-O-----O-O-----O-----O-------O-+ +# +---+ | | +# | bridge (ng_bridge) | +# +-----------------------------------------------+ +# +# + +# Give the name of ethernet interface. Virtual nodes will be seen as +# local neighbours of this interface. + +ETHER_INTF="em0" + +# List the names of virtual nodes and their IP addresses. Use ':' +# character to seperate node name from node IP address and netmask. + +TARGET_TOPOLOGY="c1|10.0.2.20/24 c2|10.0.2.21/24 c3|10.0.2.22/24" + +# MAC manifacturer prefix. This can be modified according to needs. +MAC_PREFIX="00:1d:92" + +# Temporary file is important for proper execution of script. +TEMP_FILE="/var/tmp/.virtual.lan.tmp" + +# Set root directory for jails to be created. +JAIL_PATH="/usr/jails/node" + + +#################################################################### +#### Nothing below this point should need to be modified. #### +#################################################################### + + +# Start/restart routine. +virtual_lan_start() { + + # Load netgraph KLD's as necessary. + + for KLD in ng_ether ng_bridge ng_eiface; do + if ! kldstat -v | grep -qw ${KLD}; then + echo -n "Loading ${KLD}.ko... " + kldload ${KLD} || exit 1 + echo "done" + fi + done + + # Reset all interfaces and jails. If temporary file can not be found + # script assumes that there is no previous configuration. + + if [ ! -e ${TEMP_FILE} ]; then + echo "No previous configuration(${TEMP_FILE}) found to clean-up." + else + echo -n "Cleaning previous configuration..." + virtual_lan_stop + echo "done" + fi + + # Create temporary file for usage. This file includes generated + # interface names and jail names. All bridges, interfaces and jails + # are written to file while created. In clean-up process written + # objects are cleaned (i.e removed) from system. + + if [ -e ${TEMP_FILE} ]; then + touch ${TEMP_FILE} + fi + + echo -n "Verifying ethernet interface existence..." + # Verify ethernet interface exist. + if ! ngctl info ${ETHER_INTF}: >/dev/null 2>&1; then + echo "Error: interface ${ETHER_INTF} does not exist" + exit 1 + fi + ifconfig ${ETHER_INTF} up || exit 1 + echo "done" + + # Get current number of bridge interfaces in the system. This number + # is used to create a name for new bridge. + BRIDGE_COUNT=`ngctl l | grep bridge | wc -l | sed -e "s/ //g"` + BRIDGE_NAME="bridge${BRIDGE_COUNT}" + + # Create new ng_bridge(4) node and attach it to the ethernet interface. + # Connect ng_ether:lower hook to bridge:link0 when creating bridge and + # connect ng_ether:upper hook to bridge:link1 after bridge name is set. + + echo "Creating bridge interface: ${BRIDGE_NAME}..." + ngctl mkpeer ${ETHER_INTF}: bridge lower link0 || exit 1 + ngctl name ${ETHER_INTF}:lower ${BRIDGE_NAME} || exit 1 + ngctl connect ${ETHER_INTF}: ${BRIDGE_NAME}: upper link1 || exit 1 + echo "Bridge ${BRIDGE_NAME} is created and ${ETHER_INTF} is connected." + + # In the above code block two hooks are connected to bridge interface, + # therefore LINKNUM is set to 2 indicating total number of connected + # hooks on the bridge interface. + LINKNUM=2 + + # Write name of the bridge to temp file. Clean-up procedure will use + # this name to shutdown bridge interface. + echo "bridge ${BRIDGE_NAME}" > ${TEMP_FILE} + + + # Attach other interfaces as well. + for NODE in ${TARGET_TOPOLOGY}; do + + # Virtual nodes are defined in TARGET_TOPOLOGY variable. They + # have the form of 'nodeName|IPaddr'. Below two lines split + # node definition to get node name and node IP. + + NODE_NAME=`echo ${NODE} | awk -F"|" '{print $1}'` + NODE_IP=`echo ${NODE} | awk -F"|" '{print $2}'` + + # Create virtual node (jail) with given name and using + # JAIL_PATH as root directory for jail. + + echo -n "Creating virtual node (jail) ${NODE_NAME}..." + jail -c vnet name=${NODE_NAME} host.hostname=${NODE_NAME} \ + path=${JAIL_PATH} persist + echo "done" + + # Write name of the jail to temp file. Clean-up procedure will + # use this name to remove jail. + + echo "node ${NODE_NAME}" >> ${TEMP_FILE} + + # Create a ng_eiface object for virtual node. ng_eiface + # object has a hook that can be connected to one of bridge + # links. After creating interface get its automatically + # generated name for further usage. + + echo "Creating eiface interface for virtual node ${NODE_NAME}." + ngctl mkpeer eiface ether ether + EIFACE=`ngctl l | grep ngeth | tail -n 1| awk '{print $2}'` + echo "Interface ${EIFACE} is created." + + # Write name of the interface to temp file. Clean-up procedure + # will use this name to shutdown interface. + + echo "interface ${EIFACE}" >> ${TEMP_FILE} + + # Move virtual interface to virtual node. Note that Interface + # name will not be changed at the end of this movement. Moved + # interface can be seen at the output of ifconfig command in + # jail: 'jexec jailname ifconfig' + + echo "Moving ${EIFACE} to ${NODE_NAME}" + ifconfig ${EIFACE} vnet ${NODE_NAME} + + # Make lo0 interface localhost. + jexec ${NODE_NAME} ifconfig lo0 localhost + + # Generate a random mac address for virtual interface. First + # three octets can be changed by user. Last three octets are + # generated randomly. + M4=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \ + awk '{ print $1 % 256 }'` + M5=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \ + awk '{ print $1 % 256 }'` + M6=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \ + awk '{ print $1 % 256 }'` + + MAC=`printf ${MAC_PREFIX}:%02x:%02x:%02x ${M4} ${M5} ${M6}` + + # Set the link address (mac address) of virtual interface in + # virtual node to randomly generated MAC. + echo "Setting MAC address of ${EIFACE} to '${MAC}'" + jexec ${NODE_NAME} ifconfig ${EIFACE} link $MAC + + # Either IPv4 or IPv6 can be used in this script. Ifconfig + # IP setting syntax differs slightly for two IP versions. + # For version 4 'inet' keyword is used whereas for version 6 + # 'inet6' is used. Below line tries to decide which IP version + # is given and sets IPVER to 'inet' or 'inet6'. + + IPVER=`echo ${NODE_IP} | awk -F"." '{ split($4,last,"/"); \ + if( NF==4 && $1>0 && $1<256 && $2<256 && $3<256 && \ + last[1]<256) print "inet"; else print "inet6"}'` + + # Set IP address of virtual interface in virtual node. + echo "Setting IP address of ${EIFACE} to '${NODE_IP}'" + jexec ${NODE_NAME} ifconfig ${EIFACE} ${IPVER} ${NODE_IP} + + # Connect virtual interface to bridge interface. Syntax is : + # ngctl connect INTERFACE: BRIDGE: INTERFACE_HOOK EMPTY_LINK. + # Interface has one hook named 'ether' and below line connects + # ether hook to bridge's first unconnected link. + + echo -n "Connecting ${EIFACE}:ether to ${BRIDGE_NAME}:link${LINKNUM}..." + ngctl connect ${EIFACE}: ${BRIDGE_NAME}: ether link${LINKNUM} \ + || exit 1 + echo "done" + + # Now, bridge has one more connected link thus link count is + # incremented. + LINKNUM=`expr ${LINKNUM} + 1` + done + echo "Virtual LAN established succesfully!" + +} + +# Stop routine. +virtual_lan_stop() { + + if [ ! -e ${TEMP_FILE} ]; then + echo "Nothing to stop! ${TEMP_FILE}: temp file not found" + else + + echo -n "Shutdown bridge interface.." + OBJECTS=`cat ${TEMP_FILE} | grep bridge | awk '{print $2}'` + for BRIDGE in ${OBJECTS}; do + ngctl shutdown ${BRIDGE}: >/dev/null 2>&1 + done + echo "done" + + echo -n "Shutdown all eiface interfaces..." + OBJECTS=`cat ${TEMP_FILE} | grep interface | awk '{print $2}'` + for INTERFACE in ${OBJECTS}; do + ngctl shutdown ${INTERFACE}: >/dev/null 2>&1 + done + echo "done" + + echo -n "Removing all jails..." + OBJECTS=`cat ${TEMP_FILE} | grep node | awk '{print $2}'` + for NODE in ${OBJECTS}; do + jail -r ${NODE} + done + echo "done" + + echo "Removing tempfile ${TEMP_FILE}" + rm ${TEMP_FILE} + fi + echo "Virtual LAN objects removed succesfully!" + +} + +virtual_lan_usage() { + echo "usage: $0 start [target_topology]" + echo " : $0 [ stop | help ]" +} + + +# Main entry point. + +case $# in + 1) + case $1 in + start) + echo -n "Creating default target topology:" + echo " ${TARGET_TOPOLOGY}" + virtual_lan_start + ;; + stop) + + if [ ! -e ${TEMP_FILE} ]; then + echo -n "Noting to stop! ${TEMP_FILE}:" + echo " temp file not found" + else + virtual_lan_stop + fi + ;; + help) + virtual_lan_usage + exit 1 + ;; + *) + virtual_lan_usage + exit 1 + + esac + ;; + 2) + case $1 in + start) + TARGET_TOPOLOGY=$2 + echo -n "Creating target topology:" + echo "${TARGET_TOPOLOGY}" + virtual_lan_start + ;; + *) + virtual_lan_usage + exit 1 + esac + ;; + + *) + virtual_lan_usage + exit 1 +esac +