Deleted Added
full compact
virtual.lan (214306) virtual.lan (222179)
1#!/bin/sh
2#
1#!/bin/sh
2#
3# Copyright (c) 2010, Yavuz Gokirmak
3# Copyright (c) 2010, Yavuz Gokirmak
4#
5# All rights reserved.
6#
7# This source code may be used, modified, copied, distributed, and
8# sold, in both source and binary form provided that the above
9# copyright and these terms are retained, verbatim, as the first
10# lines of this file. Under no circumstances is the author
11# responsible for the proper functioning of the software nor does
12# the author assume any responsibility for damages incurred with
13# its use.
14#
4#
5# All rights reserved.
6#
7# This source code may be used, modified, copied, distributed, and
8# sold, in both source and binary form provided that the above
9# copyright and these terms are retained, verbatim, as the first
10# lines of this file. Under no circumstances is the author
11# responsible for the proper functioning of the software nor does
12# the author assume any responsibility for damages incurred with
13# its use.
14#
15# $FreeBSD: head/share/examples/netgraph/virtual.lan 214306 2010-10-24 22:59:38Z julian $
16
15# $FreeBSD: head/share/examples/netgraph/virtual.lan 222179 2011-05-22 14:23:48Z uqs $
17#
16#
18# This script adds virtual nodes to one of the physical interfaces
17# This script adds virtual nodes to one of the physical interfaces
19# visible on your local area network (LAN). Virtual nodes seems real
18# visible on your local area network (LAN). Virtual nodes seems real
20# to external observers.
19# to external observers.
21# If traceroute is executed to one of virtual nodes, the IP
20# If traceroute is executed to one of virtual nodes, the IP
22# address of the physical interface will not be seen in the output.
21# address of the physical interface will not be seen in the output.
23# Virtual nodes are generated via jails and network connections are
24# established using ng_bridge(4) and ng_eiface(4) node types.
25#
26# To use this script:
27#
28# 0. Make your own copy of this example script.
29#
30# 1. Edit the definition of ${ETHER_INTF} as described below
31# to define your real interface connected to the LAN. Virtual nodes
22# Virtual nodes are generated via jails and network connections are
23# established using ng_bridge(4) and ng_eiface(4) node types.
24#
25# To use this script:
26#
27# 0. Make your own copy of this example script.
28#
29# 1. Edit the definition of ${ETHER_INTF} as described below
30# to define your real interface connected to the LAN. Virtual nodes
32# will placed on the same physical network as this interface.
31# will placed on the same physical network as this interface.
33#
32#
34# 2. Edit the definition of ${TARGET_TOPOLOGY} to define your virtual
33# 2. Edit the definition of ${TARGET_TOPOLOGY} to define your virtual
35# nodes. Virtual topology definition includes node names and their
34# nodes. Virtual topology definition includes node names and their
36# IP address. Target top. sytax: ( node1|ip1/24 node2|ip2/24 ... )
35# IP address. Target top. syntax: ( node1|ip1/24 node2|ip2/24 ... )
37# Example 1: ( n1|122.122.122.12/24, n2|122.122.122.13/24 ...)
38# Example 2: ( n1|2001:b90::14a/125, n1|2001:b90::14b/125 ...)
39#
40# 3. Run this script with "start" as the command line argument.
41#
42# 4. Stop bridging by running this script with "stop" as the
43# command line argument.
36# Example 1: ( n1|122.122.122.12/24, n2|122.122.122.13/24 ...)
37# Example 2: ( n1|2001:b90::14a/125, n1|2001:b90::14b/125 ...)
38#
39# 3. Run this script with "start" as the command line argument.
40#
41# 4. Stop bridging by running this script with "stop" as the
42# command line argument.
44#
45# 5. This cript uses a template file in order to carry information
46# between start and stop calls.
43#
44# 5. This script uses a template file in order to carry information
45# between start and stop calls.
47# In the start call, the netgraph interfaces and jails are created.
48# At the stop phase, all created objects should be removed.
49# DO NOT delete the temporary file between the start and stop phases.
50#
51# To add virtual nodes for multiple independent LANs, create multiple
52# copies of this script with different variable definitions.
53#
54# Target Topology:

--- 20 unchanged lines hidden (view full) ---

75# \ / +-O-----O-O-----O-O-----O-O-----O-----O-------O-+
76# +---+ | |
77# | bridge (ng_bridge) |
78# +-----------------------------------------------+
79#
80#
81
82# Give the name of ethernet interface. Virtual nodes will be seen as
46# In the start call, the netgraph interfaces and jails are created.
47# At the stop phase, all created objects should be removed.
48# DO NOT delete the temporary file between the start and stop phases.
49#
50# To add virtual nodes for multiple independent LANs, create multiple
51# copies of this script with different variable definitions.
52#
53# Target Topology:

--- 20 unchanged lines hidden (view full) ---

74# \ / +-O-----O-O-----O-O-----O-O-----O-----O-------O-+
75# +---+ | |
76# | bridge (ng_bridge) |
77# +-----------------------------------------------+
78#
79#
80
81# Give the name of ethernet interface. Virtual nodes will be seen as
83# local neighbours of this interface.
82# local neighbours of this interface.
84
85ETHER_INTF="em0"
86
83
84ETHER_INTF="em0"
85
87# List the names of virtual nodes and their IP addresses. Use ':'
88# character to seperate node name from node IP address and netmask.
86# List the names of virtual nodes and their IP addresses. Use ':'
87# character to separate node name from node IP address and netmask.
89
90TARGET_TOPOLOGY="c1|10.0.2.20/24 c2|10.0.2.21/24 c3|10.0.2.22/24"
91
88
89TARGET_TOPOLOGY="c1|10.0.2.20/24 c2|10.0.2.21/24 c3|10.0.2.22/24"
90
92# MAC manifacturer prefix. This can be modified according to needs.
93MAC_PREFIX="00:1d:92"
91# MAC manufacturer prefix. This can be modified according to needs.
92MAC_PREFIX="00:1d:92"
94
93
95# Temporary file is important for proper execution of script.
94# Temporary file is important for proper execution of script.
96TEMP_FILE="/var/tmp/.virtual.lan.tmp"
97
98# Set root directory for jails to be created.
99JAIL_PATH="/usr/jails/node"
100
101
102####################################################################
103#### Nothing below this point should need to be modified. ####
104####################################################################
105
106
107# Start/restart routine.
108virtual_lan_start() {
109
110 # Load netgraph KLD's as necessary.
95TEMP_FILE="/var/tmp/.virtual.lan.tmp"
96
97# Set root directory for jails to be created.
98JAIL_PATH="/usr/jails/node"
99
100
101####################################################################
102#### Nothing below this point should need to be modified. ####
103####################################################################
104
105
106# Start/restart routine.
107virtual_lan_start() {
108
109 # Load netgraph KLD's as necessary.
111
110
112 for KLD in ng_ether ng_bridge ng_eiface; do
113 if ! kldstat -v | grep -qw ${KLD}; then
114 echo -n "Loading ${KLD}.ko... "
115 kldload ${KLD} || exit 1
116 echo "done"
117 fi
118 done
119
120 # Reset all interfaces and jails. If temporary file can not be found
111 for KLD in ng_ether ng_bridge ng_eiface; do
112 if ! kldstat -v | grep -qw ${KLD}; then
113 echo -n "Loading ${KLD}.ko... "
114 kldload ${KLD} || exit 1
115 echo "done"
116 fi
117 done
118
119 # Reset all interfaces and jails. If temporary file can not be found
121 # script assumes that there is no previous configuration.
122
120 # script assumes that there is no previous configuration.
121
123 if [ ! -e ${TEMP_FILE} ]; then
124 echo "No previous configuration(${TEMP_FILE}) found to clean-up."
125 else
126 echo -n "Cleaning previous configuration..."
127 virtual_lan_stop
128 echo "done"
122 if [ ! -e ${TEMP_FILE} ]; then
123 echo "No previous configuration(${TEMP_FILE}) found to clean-up."
124 else
125 echo -n "Cleaning previous configuration..."
126 virtual_lan_stop
127 echo "done"
129 fi
128 fi
130
129
131 # Create temporary file for usage. This file includes generated
130 # Create temporary file for usage. This file includes generated
132 # interface names and jail names. All bridges, interfaces and jails
131 # interface names and jail names. All bridges, interfaces and jails
133 # are written to file while created. In clean-up process written
134 # objects are cleaned (i.e removed) from system.
135
132 # are written to file while created. In clean-up process written
133 # objects are cleaned (i.e. removed) from system.
134
136 if [ -e ${TEMP_FILE} ]; then
137 touch ${TEMP_FILE}
138 fi
139
140 echo -n "Verifying ethernet interface existence..."
141 # Verify ethernet interface exist.
142 if ! ngctl info ${ETHER_INTF}: >/dev/null 2>&1; then
143 echo "Error: interface ${ETHER_INTF} does not exist"
144 exit 1
145 fi
146 ifconfig ${ETHER_INTF} up || exit 1
147 echo "done"
148
149 # Get current number of bridge interfaces in the system. This number
150 # is used to create a name for new bridge.
151 BRIDGE_COUNT=`ngctl l | grep bridge | wc -l | sed -e "s/ //g"`
152 BRIDGE_NAME="bridge${BRIDGE_COUNT}"
135 if [ -e ${TEMP_FILE} ]; then
136 touch ${TEMP_FILE}
137 fi
138
139 echo -n "Verifying ethernet interface existence..."
140 # Verify ethernet interface exist.
141 if ! ngctl info ${ETHER_INTF}: >/dev/null 2>&1; then
142 echo "Error: interface ${ETHER_INTF} does not exist"
143 exit 1
144 fi
145 ifconfig ${ETHER_INTF} up || exit 1
146 echo "done"
147
148 # Get current number of bridge interfaces in the system. This number
149 # is used to create a name for new bridge.
150 BRIDGE_COUNT=`ngctl l | grep bridge | wc -l | sed -e "s/ //g"`
151 BRIDGE_NAME="bridge${BRIDGE_COUNT}"
153
152
154 # Create new ng_bridge(4) node and attach it to the ethernet interface.
155 # Connect ng_ether:lower hook to bridge:link0 when creating bridge and
156 # connect ng_ether:upper hook to bridge:link1 after bridge name is set.
153 # Create new ng_bridge(4) node and attach it to the ethernet interface.
154 # Connect ng_ether:lower hook to bridge:link0 when creating bridge and
155 # connect ng_ether:upper hook to bridge:link1 after bridge name is set.
157
156
158 echo "Creating bridge interface: ${BRIDGE_NAME}..."
159 ngctl mkpeer ${ETHER_INTF}: bridge lower link0 || exit 1
160 ngctl name ${ETHER_INTF}:lower ${BRIDGE_NAME} || exit 1
161 ngctl connect ${ETHER_INTF}: ${BRIDGE_NAME}: upper link1 || exit 1
162 echo "Bridge ${BRIDGE_NAME} is created and ${ETHER_INTF} is connected."
157 echo "Creating bridge interface: ${BRIDGE_NAME}..."
158 ngctl mkpeer ${ETHER_INTF}: bridge lower link0 || exit 1
159 ngctl name ${ETHER_INTF}:lower ${BRIDGE_NAME} || exit 1
160 ngctl connect ${ETHER_INTF}: ${BRIDGE_NAME}: upper link1 || exit 1
161 echo "Bridge ${BRIDGE_NAME} is created and ${ETHER_INTF} is connected."
163
162
164 # In the above code block two hooks are connected to bridge interface,
163 # In the above code block two hooks are connected to bridge interface,
165 # therefore LINKNUM is set to 2 indicating total number of connected
166 # hooks on the bridge interface.
164 # therefore LINKNUM is set to 2 indicating total number of connected
165 # hooks on the bridge interface.
167 LINKNUM=2
168
169 # Write name of the bridge to temp file. Clean-up procedure will use
170 # this name to shutdown bridge interface.
171 echo "bridge ${BRIDGE_NAME}" > ${TEMP_FILE}
172
173
174 # Attach other interfaces as well.
175 for NODE in ${TARGET_TOPOLOGY}; do
166 LINKNUM=2
167
168 # Write name of the bridge to temp file. Clean-up procedure will use
169 # this name to shutdown bridge interface.
170 echo "bridge ${BRIDGE_NAME}" > ${TEMP_FILE}
171
172
173 # Attach other interfaces as well.
174 for NODE in ${TARGET_TOPOLOGY}; do
176
175
177 # Virtual nodes are defined in TARGET_TOPOLOGY variable. They
178 # have the form of 'nodeName|IPaddr'. Below two lines split
179 # node definition to get node name and node IP.
180
181 NODE_NAME=`echo ${NODE} | awk -F"|" '{print $1}'`
182 NODE_IP=`echo ${NODE} | awk -F"|" '{print $2}'`
183
176 # Virtual nodes are defined in TARGET_TOPOLOGY variable. They
177 # have the form of 'nodeName|IPaddr'. Below two lines split
178 # node definition to get node name and node IP.
179
180 NODE_NAME=`echo ${NODE} | awk -F"|" '{print $1}'`
181 NODE_IP=`echo ${NODE} | awk -F"|" '{print $2}'`
182
184 # Create virtual node (jail) with given name and using
183 # Create virtual node (jail) with given name and using
185 # JAIL_PATH as root directory for jail.
186
184 # JAIL_PATH as root directory for jail.
185
187 echo -n "Creating virtual node (jail) ${NODE_NAME}..."
186 echo -n "Creating virtual node (jail) ${NODE_NAME}..."
188 jail -c vnet name=${NODE_NAME} host.hostname=${NODE_NAME} \
187 jail -c vnet name=${NODE_NAME} host.hostname=${NODE_NAME} \
189 path=${JAIL_PATH} persist
188 path=${JAIL_PATH} persist
190 echo "done"
189 echo "done"
191
192 # Write name of the jail to temp file. Clean-up procedure will
190
191 # Write name of the jail to temp file. Clean-up procedure will
193 # use this name to remove jail.
192 # use this name to remove jail.
194
193
195 echo "node ${NODE_NAME}" >> ${TEMP_FILE}
196
194 echo "node ${NODE_NAME}" >> ${TEMP_FILE}
195
197 # Create a ng_eiface object for virtual node. ng_eiface
196 # Create a ng_eiface object for virtual node. ng_eiface
198 # object has a hook that can be connected to one of bridge
197 # object has a hook that can be connected to one of bridge
199 # links. After creating interface get its automatically
200 # generated name for further usage.
198 # links. After creating interface get its automatically
199 # generated name for further usage.
201
202 echo "Creating eiface interface for virtual node ${NODE_NAME}."
203 ngctl mkpeer eiface ether ether
204 EIFACE=`ngctl l | grep ngeth | tail -n 1| awk '{print $2}'`
200
201 echo "Creating eiface interface for virtual node ${NODE_NAME}."
202 ngctl mkpeer eiface ether ether
203 EIFACE=`ngctl l | grep ngeth | tail -n 1| awk '{print $2}'`
205 echo "Interface ${EIFACE} is created."
206
204 echo "Interface ${EIFACE} is created."
205
207 # Write name of the interface to temp file. Clean-up procedure
208 # will use this name to shutdown interface.
206 # Write name of the interface to temp file. Clean-up procedure
207 # will use this name to shutdown interface.
209
208
210 echo "interface ${EIFACE}" >> ${TEMP_FILE}
209 echo "interface ${EIFACE}" >> ${TEMP_FILE}
211
212 # Move virtual interface to virtual node. Note that Interface
210
211 # Move virtual interface to virtual node. Note that Interface
213 # name will not be changed at the end of this movement. Moved
214 # interface can be seen at the output of ifconfig command in
215 # jail: 'jexec jailname ifconfig'
216
212 # name will not be changed at the end of this movement. Moved
213 # interface can be seen at the output of ifconfig command in
214 # jail: 'jexec jailname ifconfig'
215
217 echo "Moving ${EIFACE} to ${NODE_NAME}"
216 echo "Moving ${EIFACE} to ${NODE_NAME}"
218 ifconfig ${EIFACE} vnet ${NODE_NAME}
217 ifconfig ${EIFACE} vnet ${NODE_NAME}
219
218
220 # Make lo0 interface localhost.
221 jexec ${NODE_NAME} ifconfig lo0 localhost
222
223 # Generate a random mac address for virtual interface. First
224 # three octets can be changed by user. Last three octets are
219 # Make lo0 interface localhost.
220 jexec ${NODE_NAME} ifconfig lo0 localhost
221
222 # Generate a random mac address for virtual interface. First
223 # three octets can be changed by user. Last three octets are
225 # generated randomly.
224 # generated randomly.
226 M4=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \
227 awk '{ print $1 % 256 }'`
228 M5=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \
229 awk '{ print $1 % 256 }'`
230 M6=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \
231 awk '{ print $1 % 256 }'`
232
233 MAC=`printf ${MAC_PREFIX}:%02x:%02x:%02x ${M4} ${M5} ${M6}`
234
235 # Set the link address (mac address) of virtual interface in
236 # virtual node to randomly generated MAC.
237 echo "Setting MAC address of ${EIFACE} to '${MAC}'"
238 jexec ${NODE_NAME} ifconfig ${EIFACE} link $MAC
239
225 M4=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \
226 awk '{ print $1 % 256 }'`
227 M5=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \
228 awk '{ print $1 % 256 }'`
229 M6=`od -An -N2 -i /dev/random | sed -e 's/ //g' | \
230 awk '{ print $1 % 256 }'`
231
232 MAC=`printf ${MAC_PREFIX}:%02x:%02x:%02x ${M4} ${M5} ${M6}`
233
234 # Set the link address (mac address) of virtual interface in
235 # virtual node to randomly generated MAC.
236 echo "Setting MAC address of ${EIFACE} to '${MAC}'"
237 jexec ${NODE_NAME} ifconfig ${EIFACE} link $MAC
238
240 # Either IPv4 or IPv6 can be used in this script. Ifconfig
239 # Either IPv4 or IPv6 can be used in this script. Ifconfig
241 # IP setting syntax differs slightly for two IP versions.
242 # For version 4 'inet' keyword is used whereas for version 6
243 # 'inet6' is used. Below line tries to decide which IP version
240 # IP setting syntax differs slightly for two IP versions.
241 # For version 4 'inet' keyword is used whereas for version 6
242 # 'inet6' is used. Below line tries to decide which IP version
244 # is given and sets IPVER to 'inet' or 'inet6'.
243 # is given and sets IPVER to 'inet' or 'inet6'.
245
246 IPVER=`echo ${NODE_IP} | awk -F"." '{ split($4,last,"/"); \
247 if( NF==4 && $1>0 && $1<256 && $2<256 && $3<256 && \
248 last[1]<256) print "inet"; else print "inet6"}'`
244
245 IPVER=`echo ${NODE_IP} | awk -F"." '{ split($4,last,"/"); \
246 if( NF==4 && $1>0 && $1<256 && $2<256 && $3<256 && \
247 last[1]<256) print "inet"; else print "inet6"}'`
249
248
250 # Set IP address of virtual interface in virtual node.
251 echo "Setting IP address of ${EIFACE} to '${NODE_IP}'"
252 jexec ${NODE_NAME} ifconfig ${EIFACE} ${IPVER} ${NODE_IP}
249 # Set IP address of virtual interface in virtual node.
250 echo "Setting IP address of ${EIFACE} to '${NODE_IP}'"
251 jexec ${NODE_NAME} ifconfig ${EIFACE} ${IPVER} ${NODE_IP}
253
252
254 # Connect virtual interface to bridge interface. Syntax is :
255 # ngctl connect INTERFACE: BRIDGE: INTERFACE_HOOK EMPTY_LINK.
256 # Interface has one hook named 'ether' and below line connects
253 # Connect virtual interface to bridge interface. Syntax is :
254 # ngctl connect INTERFACE: BRIDGE: INTERFACE_HOOK EMPTY_LINK.
255 # Interface has one hook named 'ether' and below line connects
257 # ether hook to bridge's first unconnected link.
258
256 # ether hook to bridge's first unconnected link.
257
259 echo -n "Connecting ${EIFACE}:ether to ${BRIDGE_NAME}:link${LINKNUM}..."
260 ngctl connect ${EIFACE}: ${BRIDGE_NAME}: ether link${LINKNUM} \
261 || exit 1
262 echo "done"
263
264 # Now, bridge has one more connected link thus link count is
258 echo -n "Connecting ${EIFACE}:ether to ${BRIDGE_NAME}:link${LINKNUM}..."
259 ngctl connect ${EIFACE}: ${BRIDGE_NAME}: ether link${LINKNUM} \
260 || exit 1
261 echo "done"
262
263 # Now, bridge has one more connected link thus link count is
265 # incremented.
264 # incremented.
266 LINKNUM=`expr ${LINKNUM} + 1`
267 done
265 LINKNUM=`expr ${LINKNUM} + 1`
266 done
268 echo "Virtual LAN established succesfully!"
267 echo "Virtual LAN established successfully!"
269
270}
271
272# Stop routine.
273virtual_lan_stop() {
274
275 if [ ! -e ${TEMP_FILE} ]; then
276 echo "Nothing to stop! ${TEMP_FILE}: temp file not found"
277 else
278
268
269}
270
271# Stop routine.
272virtual_lan_stop() {
273
274 if [ ! -e ${TEMP_FILE} ]; then
275 echo "Nothing to stop! ${TEMP_FILE}: temp file not found"
276 else
277
279 echo -n "Shutdown bridge interface.."
278 echo -n "Shutdown bridge interface.."
280 OBJECTS=`cat ${TEMP_FILE} | grep bridge | awk '{print $2}'`
281 for BRIDGE in ${OBJECTS}; do
282 ngctl shutdown ${BRIDGE}: >/dev/null 2>&1
283 done
284 echo "done"
279 OBJECTS=`cat ${TEMP_FILE} | grep bridge | awk '{print $2}'`
280 for BRIDGE in ${OBJECTS}; do
281 ngctl shutdown ${BRIDGE}: >/dev/null 2>&1
282 done
283 echo "done"
285
286 echo -n "Shutdown all eiface interfaces..."
284
285 echo -n "Shutdown all eiface interfaces..."
287 OBJECTS=`cat ${TEMP_FILE} | grep interface | awk '{print $2}'`
288 for INTERFACE in ${OBJECTS}; do
289 ngctl shutdown ${INTERFACE}: >/dev/null 2>&1
290 done
291 echo "done"
286 OBJECTS=`cat ${TEMP_FILE} | grep interface | awk '{print $2}'`
287 for INTERFACE in ${OBJECTS}; do
288 ngctl shutdown ${INTERFACE}: >/dev/null 2>&1
289 done
290 echo "done"
292
293 echo -n "Removing all jails..."
291
292 echo -n "Removing all jails..."
294 OBJECTS=`cat ${TEMP_FILE} | grep node | awk '{print $2}'`
295 for NODE in ${OBJECTS}; do
296 jail -r ${NODE}
297 done
298 echo "done"
293 OBJECTS=`cat ${TEMP_FILE} | grep node | awk '{print $2}'`
294 for NODE in ${OBJECTS}; do
295 jail -r ${NODE}
296 done
297 echo "done"
299
300 echo "Removing tempfile ${TEMP_FILE}"
298
299 echo "Removing tempfile ${TEMP_FILE}"
301 rm ${TEMP_FILE}
302 fi
300 rm ${TEMP_FILE}
301 fi
303 echo "Virtual LAN objects removed succesfully!"
302 echo "Virtual LAN objects removed successfully!"
304
305}
306
307virtual_lan_usage() {
308 echo "usage: $0 start [target_topology]"
309 echo " : $0 [ stop | help ]"
310}
311

--- 10 unchanged lines hidden (view full) ---

322 ;;
323 stop)
324
325 if [ ! -e ${TEMP_FILE} ]; then
326 echo -n "Noting to stop! ${TEMP_FILE}:"
327 echo " temp file not found"
328 else
329 virtual_lan_stop
303
304}
305
306virtual_lan_usage() {
307 echo "usage: $0 start [target_topology]"
308 echo " : $0 [ stop | help ]"
309}
310

--- 10 unchanged lines hidden (view full) ---

321 ;;
322 stop)
323
324 if [ ! -e ${TEMP_FILE} ]; then
325 echo -n "Noting to stop! ${TEMP_FILE}:"
326 echo " temp file not found"
327 else
328 virtual_lan_stop
330 fi
329 fi
331 ;;
332 help)
333 virtual_lan_usage
334 exit 1
335 ;;
336 *)
337 virtual_lan_usage
338 exit 1

--- 22 unchanged lines hidden ---
330 ;;
331 help)
332 virtual_lan_usage
333 exit 1
334 ;;
335 *)
336 virtual_lan_usage
337 exit 1

--- 22 unchanged lines hidden ---