4 # Copyright 1998 VMware, Inc. All rights reserved.
7 # vmnet: Manages the services needed to run VMware networking
9 # description: Manages the services needed to run VMware networking
28 vmware_etc_dir=/etc/vmware
29 vmware_locations="$vmware_etc_dir"/locations
30 vmnet_cfg="$vmware_etc_dir"/vmnet.conf
32 for f in $vmware_locations $vmnet_cfg; do
36 echo "FATAL: Unable to read $f"
41 # System wide functions
42 . /etc/rc.d/init.d/functions
45 # Create a temporary directory
48 # They are a lot of small utility programs to create temporary files in a
49 # secure way, but none of them is standard. So I wrote this --hpreg
51 local dirname="$1" # OUT
52 local prefix="$2" # IN
58 # Don't overwrite existing user data
59 # -> Create a directory with a name that didn't exist before
61 # This may never succeed (if we are racing with a malicious process), but at
65 while [ "$loop" = 'yes' ]; do
66 # Check the validity of the temporary directory. We do this in the loop
67 # because it can change over time
68 if [ ! -d "$tmp" ]; then
69 echo 'Error: "'"$tmp"'" is not a directory.'
73 if [ ! -w "$tmp" -o ! -x "$tmp" ]; then
74 echo 'Error: "'"$tmp"'" should be writable and executable.'
79 # -> Don't give write access to other users (so that they can not use this
80 # directory to launch a symlink attack)
81 if mkdir -m 0755 "$tmp"'/'"$prefix$serial" >/dev/null 2>&1; then
84 serial=`expr "$serial" + 1`
85 if [ "`expr "$serial" % 200`" = '0' ]; then
86 echo 'Warning: The "'"$tmp"'" directory may be under attack.'
91 eval "$dirname"'="$tmp"'"'"'/'"'"'"$prefix$serial"'
98 # Compute the subnet address associated to a couple IP/netmask
103 # Split quad-dotted addresses into bytes
104 # There is no double quote around the back-quoted expression on purpose
105 # There is no double quote around $ip and $netmask on purpose
106 set -- `IFS='.'; echo $ip $netmask`
107 echo $(($1 & $5)).$(($2 & $6)).$(($3 & $7)).$(($4 & $8))
110 # Compute the broadcast address associated to a couple IP/netmask
115 # Split quad-dotted addresses into bytes
116 # There is no double quote around the back-quoted expression on purpose
117 # There is no double quote around $ip and $netmask on purpose
118 set -- `IFS='.'; echo $ip $netmask`
119 echo $(($1 | (255 - $5))).$(($2 | (255 - $6))).$(($3 | (255 - $7))).$(($4 | (255 - $8)))
122 # Count the number of running virtual machines by looking at the number of references
123 # to the $driver module.
125 # Beware of module dependancies here. An exact match is important
126 /sbin/lsmod | awk 'BEGIN {n = 0;} {if ($1 == "'"$driver"'") n = $3;} END {print n;}'
129 # Check if there is an IP route for a given subnet via a given interface
130 # Return true if there is _NO_ such route
132 local subnet="$1" # IN
135 # Beware, there may be several identical routes
136 [ "`/sbin/route -n | grep '^'"$subnet"'.*'"$intf"'$'`" = '' ]
143 # . Each daemon must be started from its own directory to avoid busy devices
144 # . Each PID file doesn't need to be added to the installer database, because
145 # it is going to be automatically removed when it becomes stale (after a
146 # reboot). It must go directly under /var/run, or some distributions
147 # (RedHat 6.0) won't clean it
150 # Terminate a process synchronously
151 vmware_synchrone_kill() {
153 local signal="$2" # IN
156 kill -"$signal" "$pid"
157 # Wait a bit to see if the dirty job has really been done
158 for second in 0 1 2 3 4 5 6 7 8 9 10; do
159 if [ ! -d /proc/"$pid" ]; then
169 # Kill the process associated to a pidfile
170 vmware_stop_pidfile() {
171 local pidfile="$1" # IN
174 pid=`cat "$pidfile" 2>/dev/null`
175 if [ "$pid" = '' ]; then
176 # The file probably does not exist or is empty. Success
179 # Keep only the first number we find, because some Samba pid files are really
180 # trashy: they end with NUL characters
181 # There is no double quote around $pid on purpose
184 # First try a nice SIGTERM
185 if vmware_synchrone_kill "$pid" 15; then
188 # Then send a strong SIGKILL
189 if vmware_synchrone_kill "$pid" 9; then
195 # Start the host-only network user service
196 vmware_start_hostonly() {
197 local vHubNr="$1" # IN
198 local vHostIf="$2" # IN
200 local ifMask="$4" # IN
201 local run_dhcpd="$5" # IN
202 local run_samba="$6" # IN
205 # Do a cursory check to see if the host-only network
206 # configuration is still ok. We do this so that mobile
207 # hosts don't get setup at install time and then moved to
208 # a new locale where the host-only network config is no
211 # NB: This really needs to be done at power-on time when
212 # VM is configured to use host-only networking so that
213 # we aren't fooled by dynamic changes in the network.
215 # XXX ping takes 10 seconds to timeout if nobody answers
216 # that slows boot too much so we do this bit in the
218 if "$VM_BINDIR"/"$ping" -q "$ifIp"; then
219 echo 'Host-only networking disabled because '"$ifIp"
220 echo 'appears to be a real, physical, existing address.'
221 echo 'Please modify your host-only network configuration.'
224 cd "$VM_BINDIR" && "$VM_BINDIR"/"$netifup" \
225 -d /var/run/"$netifup"-"$vHostIf".pid /dev/vmnet"$vHubNr" "$vHostIf"
226 [ "$?" -eq 0 ] || exit 1
227 # Configure the virtual host ethernet interface and define the private IP
230 # . We provide the broadcast address explicitly because versions of ifconfig
231 # prior to 1.39 (1999-03-18) seem to miscompute it
232 # . 2.0.x kernels don't install a route when the interface is marked up, but
233 # 2.2.x kernel do. Since we want to see any errors from route we don't
234 # just discard messages from route, but instead check if the route got
235 # installed before manually adding one.
236 ifNet=`ipv4_subnet "$ifIp" "$ifMask"`
237 if ifconfig "$vHostIf" inet "$ifIp" netmask "$ifMask" \
238 broadcast "`ipv4_broadcast "$ifIp" "$ifMask"`" up \
239 && noRoutePresent "$ifNet" "$vHostIf"; then
240 route add -net "$ifNet" netmask "$ifMask" "$vHostIf"
242 if [ "$run_dhcpd" = 'yes' ]; then
243 # Start a DHCP server on a private IP network
244 # The daemon already logs its output in the system log, so we can safely
246 cd "$VM_BINDIR" && "$VM_BINDIR"/"$dhcpd" \
247 -cf "$vmware_etc_dir"/"$vHostIf"/dhcpd/dhcpd.conf \
248 -lf "$vmware_etc_dir"/"$vHostIf"/dhcpd/dhcpd.leases \
249 -pf /var/run/"$dhcpd"-"$vHostIf".pid "$vHostIf" >/dev/null 2>&1 || exit 1
251 if [ "$run_samba" = 'yes' ]; then
252 # Start a SMB name server on a private IP network
253 # Disable logging to avoid the uncontrolled creation of unmanaged files
254 cd "$VM_BINDIR" && "$VM_BINDIR"/"$nmbd" -D -l /dev/null \
255 -s "$vmware_etc_dir"/"$vHostIf"/smb/smb.conf \
256 -f /var/run/"$nmbd"-"$vHostIf".pid || exit 1
257 # Start a SMB share server on a private IP network
258 # Disable logging to avoid the uncontrolled creation of unmanaged files
259 cd "$VM_BINDIR" && "$VM_BINDIR"/"$smbd" -D -l /dev/null \
260 -s "$vmware_etc_dir"/"$vHostIf"/smb/smb.conf \
261 -f /var/run/"$smbd"-"$vHostIf".pid || exit 1
265 # Stop the host-only network user service
266 vmware_stop_hostonly() {
267 local vHostIf="$1" # IN
269 local ifMask="$3" # IN
272 # Terminate the private network
273 ifNet=`ipv4_subnet "$ifIp" "$ifMask"`
274 noRoutePresent "$ifNet" "$vHostIf" || route del -net "$ifNet" netmask "$ifMask" || exit 1
275 # To test if the interface exists, we can not just look at the exitcode
276 # because old versions of ifconfig don't exit with 1 when invoked with a
277 # non-existing interface
278 if [ "`ifconfig "$vHostIf" 2>/dev/null`" != '' ]; then
279 ifconfig "$vHostIf" down || exit 1
281 vmware_stop_pidfile /var/run/"$netifup"-"$vHostIf".pid || exit 1
284 # See how we were called.
287 if [ -f /var/lock/subsys/"$subsys" ]; then
288 msg_already_running "VMware Workstation networking"
290 # Try to load parport_pc. Failure is allowed as it does not exist
292 /sbin/modprobe parport_pc >/dev/null 2>&1
293 if [ "$VM_NETWORKING" = 'yes' ]; then
294 msg_starting 'Virtual ethernet'
297 [ "$?" -eq 0 ] && ok || fail
299 while [ $vHubNr -lt 9 ]; do
300 eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"'
301 eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"'
302 eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"'
303 if [ -n "$interface" ]; then
304 # Connect a physical host ethernet interface to a virtual ethernet hub
305 msg_starting 'Bridged networking on /dev/vmnet'"$vHubNr"
307 cd "$VM_BINDIR" && "$VM_BINDIR"/"$bridge" \
308 -d /var/run/"$bridge"-"$vHubNr".pid /dev/vmnet"$vHubNr" "$interface"
309 [ "$?" -eq 0 ] && ok || fail
310 elif [ -n "$hostaddr" -a -n "$netmask" ]; then
311 eval 'samba="$VNET_'"$vHubNr"'_SAMBA"'
312 msg_starting 'Host-only networking on /dev/vmnet'"$vHubNr"
314 vmware_start_hostonly "$vHubNr" 'vmnet'"$vHubNr" "$hostaddr" \
315 "$netmask" 'yes' "$samba"
316 [ "$?" -eq 0 ] && ok || fail
317 eval 'nat="$VNET_'"$vHubNr"'_NAT"'
318 if [ "$nat" = 'yes' ]; then
319 # Start the NAT network user service
320 msg_starting 'NAT networking on /dev/vmnet'"$vHubNr"
322 cd "$VM_BINDIR" && "$VM_BINDIR"/"$natd" \
323 -d /var/run/"$natd"-"$vHubNr".pid \
324 -m /var/run/"$natd"-"$vHubNr".mac \
325 -c "$vmware_etc_dir"/vmnet"$vHubNr"/nat/nat.conf >/dev/null 2>&1
326 [ "$?" -eq 0 ] && ok || fail
329 vHubNr=$(($vHubNr + 1))
332 touch /var/lock/subsys/"$subsys"
336 if [ "`countVMs`" -gt 0 ]; then
337 echo 'At least one instance of VMware Workstation is still running.'
338 echo 'Please stop all running instances of VMware Workstation first.'
341 if [ ! -f /var/lock/subsys/"$subsys" ]; then
342 msg_not_running "VMware Workstation networking"
344 # Try to unload parport_pc. Failure is allowed as it does not exist
345 # on kernels 2.0, and some other process could be using it.
346 /sbin/modprobe -r parport_pc >/dev/null 2>&1
347 if [ "$VM_NETWORKING" = "yes" ]; then
348 # NB: must kill off processes using vmnet before
351 while [ $vHubNr -lt 9 ]; do
352 eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"'
353 eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"'
354 eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"'
355 if [ -n "$interface" ]; then
356 # Disconnect a physical host ethernet interface from a virtual ethernet hub
357 msg_stopping "Bridged networking on /dev/vmnet$vHubNr"
359 vmware_stop_pidfile /var/run/"$bridge"-"$vHubNr".pid
360 [ "$?" -eq 0 ] && ok || fail
361 elif [ -n "$hostaddr" -a -n "$netmask" ]; then
362 # Stop a DHCP server on a private IP network
363 msg_stopping "DHCP server on /dev/vmnet$vHubNr"
365 vmware_stop_pidfile /var/run/"$dhcpd"-"vmnet$vHubNr".pid
366 [ "$?" -eq 0 ] && ok || fail
367 eval 'samba="$VNET_'"$vHubNr"'_SAMBA"'
368 if [ "$samba" = "yes" ]; then
369 # Stop a SMB share server on a private IP network
370 msg_stopping 'SMB share server on /dev/vmnet'"$vHubNr"
372 vmware_stop_pidfile /var/run/"$smbd"-'vmnet'"$vHubNr".pid
373 [ "$?" -eq 0 ] && ok || fail
374 # Stop a SMB name server on a private IP network
375 msg_stopping 'SMB name server on /dev/vmnet'"$vHubNr"
377 vmware_stop_pidfile /var/run/"$nmbd"-'vmnet'"$vHubNr".pid
378 [ "$?" -eq 0 ] && ok || fail
380 eval 'nat="$VNET_'"$vHubNr"'_NAT"'
381 if [ "$nat" = "yes" ]; then
382 # Stop the NAT network user service
383 msg_stopping 'NAT networking on /dev/vmnet'"$vHubNr"
385 vmware_stop_pidfile /var/run/"$natd"-"$vHubNr".pid
386 [ "$?" -eq 0 ] && ok || fail
388 msg_stopping 'Host-only networking on /dev/vmnet'"$vHubNr"
390 vmware_stop_hostonly 'vmnet'"$vHubNr" "$hostaddr" "$netmask"
391 [ "$?" -eq 0 ] && ok || fail
394 vHubNr=$(($vHubNr + 1))
396 msg_stopping 'Virtual machine monitor'
398 if /sbin/lsmod | grep -q ^"$driver"; then
399 /sbin/rmmod "$driver"
401 [ "$?" -eq "0" ] && ok || fail
402 msg_stopping 'Virtual ethernet'
404 if /sbin/lsmod | grep -q ^"$vnet"; then
407 [ "$?" -eq "0" ] && ok || fail
409 rm -f /var/lock/subsys/"$subsys"
412 if [ "`countVMs`" -gt 0 ]; then
413 echo 'At least one instance of VMware Workstation is still running.'
416 if [ "$VM_NETWORKING" = "yes" ]; then
421 if [ "$VM_NETWORKING" = "yes" ]; then
422 echo -n "Module $vnet "
423 /sbin/modprobe "$vnet" >/dev/null 2>&1 && echo installed || echo "not installed"
427 "$0" stop && "$0" start
430 echo "Usage: `basename "$0"` {start|stop|status|restart}"