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
27 vmware_etc_dir=/etc/vmware
28 vmnet_cfg="$vmware_etc_dir"/vmnet.conf
29 if [ -r "$vmnet_cfg" ]; then
32 echo "Warning: Unable to find VMware Workstation's main database"
38 # System wide functions
39 . /etc/rc.d/init.d/functions
42 # Create a temporary directory
45 # They are a lot of small utility programs to create temporary files in a
46 # secure way, but none of them is standard. So I wrote this --hpreg
48 local dirname="$1" # OUT
49 local prefix="$2" # IN
55 # Don't overwrite existing user data
56 # -> Create a directory with a name that didn't exist before
58 # This may never succeed (if we are racing with a malicious process), but at
62 while [ "$loop" = 'yes' ]; do
63 # Check the validity of the temporary directory. We do this in the loop
64 # because it can change over time
65 if [ ! -d "$tmp" ]; then
66 echo 'Error: "'"$tmp"'" is not a directory.'
70 if [ ! -w "$tmp" -o ! -x "$tmp" ]; then
71 echo 'Error: "'"$tmp"'" should be writable and executable.'
76 # -> Don't give write access to other users (so that they can not use this
77 # directory to launch a symlink attack)
78 if mkdir -m 0755 "$tmp"'/'"$prefix$serial" >/dev/null 2>&1; then
81 serial=`expr "$serial" + 1`
82 if [ "`expr "$serial" % 200`" = '0' ]; then
83 echo 'Warning: The "'"$tmp"'" directory may be under attack.'
88 eval "$dirname"'="$tmp"'"'"'/'"'"'"$prefix$serial"'
95 # Compute the subnet address associated to a couple IP/netmask
100 # Split quad-dotted addresses into bytes
101 # There is no double quote around the back-quoted expression on purpose
102 # There is no double quote around $ip and $netmask on purpose
103 set -- `IFS='.'; echo $ip $netmask`
104 echo $(($1 & $5)).$(($2 & $6)).$(($3 & $7)).$(($4 & $8))
107 # Compute the broadcast address associated to a couple IP/netmask
112 # Split quad-dotted addresses into bytes
113 # There is no double quote around the back-quoted expression on purpose
114 # There is no double quote around $ip and $netmask on purpose
115 set -- `IFS='.'; echo $ip $netmask`
116 echo $(($1 | (255 - $5))).$(($2 | (255 - $6))).$(($3 | (255 - $7))).$(($4 | (255 - $8)))
119 # Count the number of running virtual machines by looking at the number of references
120 # to the $driver module.
122 # Beware of module dependancies here. An exact match is important
123 /sbin/lsmod | awk 'BEGIN {n = 0;} {if ($1 == "'"$driver"'") n = $3;} END {print n;}'
126 # Check if there is an IP route for a given subnet via a given interface
127 # Return true if there is _NO_ such route
129 local subnet="$1" # IN
132 # Beware, there may be several identical routes
133 [ "`/sbin/route -n | grep '^'"$subnet"'.*'"$intf"'$'`" = '' ]
140 # . Each daemon must be started from its own directory to avoid busy devices
141 # . Each PID file doesn't need to be added to the installer database, because
142 # it is going to be automatically removed when it becomes stale (after a
143 # reboot). It must go directly under /var/run, or some distributions
144 # (RedHat 6.0) won't clean it
147 # Terminate a process synchronously
148 vmware_synchrone_kill() {
150 local signal="$2" # IN
153 kill -"$signal" "$pid"
154 # Wait a bit to see if the dirty job has really been done
155 for second in 0 1 2 3 4 5 6 7 8 9 10; do
156 if [ ! -d /proc/"$pid" ]; then
166 # Kill the process associated to a pidfile
167 vmware_stop_pidfile() {
168 local pidfile="$1" # IN
171 pid=`cat "$pidfile" 2>/dev/null`
172 if [ "$pid" = '' ]; then
173 # The file probably does not exist or is empty. Success
176 # Keep only the first number we find, because some Samba pid files are really
177 # trashy: they end with NUL characters
178 # There is no double quote around $pid on purpose
181 # First try a nice SIGTERM
182 if vmware_synchrone_kill "$pid" 15; then
185 # Then send a strong SIGKILL
186 if vmware_synchrone_kill "$pid" 9; then
192 # Start the host-only network user service
193 vmware_start_hostonly() {
194 local vHubNr="$1" # IN
195 local vHostIf="$2" # IN
197 local ifMask="$4" # IN
198 local run_dhcpd="$5" # IN
199 local run_samba="$6" # IN
202 # Do a cursory check to see if the host-only network
203 # configuration is still ok. We do this so that mobile
204 # hosts don't get setup at install time and then moved to
205 # a new locale where the host-only network config is no
208 # NB: This really needs to be done at power-on time when
209 # VM is configured to use host-only networking so that
210 # we aren't fooled by dynamic changes in the network.
212 # XXX ping takes 10 seconds to timeout if nobody answers
213 # that slows boot too much so we do this bit in the
215 if "$VMNET_BINDIR"/"$ping" -q "$ifIp"; then
216 echo 'Host-only networking disabled because '"$ifIp"
217 echo 'appears to be a real, physical, existing address.'
218 echo 'Please modify your host-only network configuration.'
221 cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$netifup" \
222 -d /var/run/"$netifup"-"$vHostIf".pid /dev/vmnet"$vHubNr" "$vHostIf"
223 [ "$?" -eq 0 ] || exit 1
224 # Configure the virtual host ethernet interface and define the private IP
227 # . We provide the broadcast address explicitly because versions of ifconfig
228 # prior to 1.39 (1999-03-18) seem to miscompute it
229 # . 2.0.x kernels don't install a route when the interface is marked up, but
230 # 2.2.x kernel do. Since we want to see any errors from route we don't
231 # just discard messages from route, but instead check if the route got
232 # installed before manually adding one.
233 ifNet=`ipv4_subnet "$ifIp" "$ifMask"`
234 if ifconfig "$vHostIf" inet "$ifIp" netmask "$ifMask" \
235 broadcast "`ipv4_broadcast "$ifIp" "$ifMask"`" up \
236 && noRoutePresent "$ifNet" "$vHostIf"; then
237 route add -net "$ifNet" netmask "$ifMask" "$vHostIf"
239 if [ "$run_dhcpd" = 'yes' ]; then
240 # Start a DHCP server on a private IP network
241 # The daemon already logs its output in the system log, so we can safely
243 cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$dhcpd" \
244 -cf "$vmware_etc_dir"/"$vHostIf"/dhcpd/dhcpd.conf \
245 -lf "$vmware_etc_dir"/"$vHostIf"/dhcpd/dhcpd.leases \
246 -pf /var/run/"$dhcpd"-"$vHostIf".pid "$vHostIf" >/dev/null 2>&1 || exit 1
248 if [ "$run_samba" = 'yes' ]; then
249 # Start a SMB name server on a private IP network
250 # Disable logging to avoid the uncontrolled creation of unmanaged files
251 cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$nmbd" -D -l /dev/null \
252 -s "$vmware_etc_dir"/"$vHostIf"/smb/smb.conf \
253 -f /var/run/"$nmbd"-"$vHostIf".pid || exit 1
254 # Start a SMB share server on a private IP network
255 # Disable logging to avoid the uncontrolled creation of unmanaged files
256 cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$smbd" -D -l /dev/null \
257 -s "$vmware_etc_dir"/"$vHostIf"/smb/smb.conf \
258 -f /var/run/"$smbd"-"$vHostIf".pid || exit 1
263 # Stop the host-only network user service
264 vmware_stop_hostonly() {
265 local vHostIf="$1" # IN
267 local ifMask="$3" # IN
270 # Terminate the private network
271 ifNet=`ipv4_subnet "$ifIp" "$ifMask"`
272 noRoutePresent "$ifNet" "$vHostIf" || route del -net "$ifNet" netmask "$ifMask" || exit 1
273 # To test if the interface exists, we can not just look at the exitcode
274 # because old versions of ifconfig don't exit with 1 when invoked with a
275 # non-existing interface
276 if [ "`ifconfig "$vHostIf" 2>/dev/null`" != '' ]; then
277 ifconfig "$vHostIf" down || exit 1
279 vmware_stop_pidfile /var/run/"$netifup"-"$vHostIf".pid || exit 1
283 # See how we were called.
286 if [ -f /var/lock/subsys/"$subsys" ]; then
287 msg_already_running "VMware Workstation networking"
291 # Try to load parport_pc. Failure is allowed as it does not exist
293 /sbin/modprobe parport_pc >/dev/null 2>&1
294 if [ "$VM_NETWORKING" = 'yes' ]; then
295 msg_starting 'Virtual ethernet'
298 [ "$?" -eq 0 ] && ok || fail
299 exitcode=`expr "$exitcode" + "$?"`
301 while [ $vHubNr -lt 256 ]; do
302 eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"'
303 eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"'
304 eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"'
305 if [ -n "$interface" ]; then
306 # Connect a physical host ethernet interface to a virtual ethernet hub
307 msg_starting 'Bridged networking on /dev/vmnet'"$vHubNr"
309 cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$bridge" \
310 -d /var/run/"$bridge"-"$vHubNr".pid /dev/vmnet"$vHubNr" "$interface"
311 [ "$?" -eq 0 ] && ok || fail
312 exitcode=`expr "$exitcode" + "$?"`
313 elif [ -n "$hostaddr" -a -n "$netmask" ]; then
314 eval 'samba="$VNET_'"$vHubNr"'_SAMBA"'
315 msg_starting 'Host-only networking on /dev/vmnet'"$vHubNr"
317 daemon vmware_start_hostonly "$vHubNr" 'vmnet'"$vHubNr" "$hostaddr" \
318 "$netmask" 'yes' "$samba"
319 [ "$?" -eq 0 ] && ok || fail
320 exitcode=`expr "$exitcode" + "$?"`
321 eval 'nat="$VNET_'"$vHubNr"'_NAT"'
322 if [ "$nat" = 'yes' ]; then
323 # Start the NAT network user service
324 msg_starting 'NAT networking on /dev/vmnet'"$vHubNr"
326 cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$natd" \
327 -d /var/run/"$natd"-"$vHubNr".pid \
328 -m /var/run/"$natd"-"$vHubNr".mac \
329 -c "$vmware_etc_dir"/vmnet"$vHubNr"/nat/nat.conf
330 [ "$?" -eq 0 ] && ok || fail
331 exitcode=`expr "$exitcode" + "$?"`
334 vHubNr=`expr $vHubNr + 1`
338 if [ "$exitcode" -gt 0 ]; then
341 touch /var/lock/subsys/"$subsys"
345 if [ "`countVMs`" -gt 0 ]; then
346 echo 'At least one instance of VMware Workstation is still running.'
347 echo 'Please stop all running instances of VMware Workstation first.'
351 if [ ! -f /var/lock/subsys/"$subsys" ]; then
352 msg_not_running "VMware Workstation networking"
356 # Try to unload parport_pc. Failure is allowed as it does not exist
357 # on kernels 2.0, and some other process could be using it.
358 /sbin/modprobe -r parport_pc >/dev/null 2>&1
359 if [ "$VM_NETWORKING" = "yes" ]; then
360 # NB: must kill off processes using vmnet before
363 while [ $vHubNr -lt 256 ]; do
364 eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"'
365 eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"'
366 eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"'
367 if [ -n "$interface" ]; then
368 # Disconnect a physical host ethernet interface from a virtual ethernet hub
369 msg_stopping "Bridged networking on /dev/vmnet$vHubNr"
371 vmware_stop_pidfile /var/run/"$bridge"-"$vHubNr".pid
372 [ "$?" -eq 0 ] && ok || fail
373 exitcode=`expr "$exitcode" + "$?"`
374 elif [ -n "$hostaddr" -a -n "$netmask" ]; then
375 # Stop a DHCP server on a private IP network
376 msg_stopping "DHCP server on /dev/vmnet$vHubNr"
378 vmware_stop_pidfile /var/run/"$dhcpd"-"vmnet$vHubNr".pid
379 [ "$?" -eq 0 ] && ok || fail
380 exitcode=`expr "$exitcode" + "$?"`
381 eval 'samba="$VNET_'"$vHubNr"'_SAMBA"'
382 if [ "$samba" = "yes" ]; then
383 # Stop a SMB share server on a private IP network
384 msg_stopping 'SMB share server on /dev/vmnet'"$vHubNr"
386 vmware_stop_pidfile /var/run/"$smbd"-'vmnet'"$vHubNr".pid
387 [ "$?" -eq 0 ] && ok || fail
388 exitcode=`expr "$exitcode" + "$?"`
389 # Stop a SMB name server on a private IP network
390 msg_stopping 'SMB name server on /dev/vmnet'"$vHubNr"
392 vmware_stop_pidfile /var/run/"$nmbd"-'vmnet'"$vHubNr".pid
393 [ "$?" -eq 0 ] && ok || fail
394 exitcode=`expr "$exitcode" + "$?"`
396 eval 'nat="$VNET_'"$vHubNr"'_NAT"'
397 if [ "$nat" = "yes" ]; then
398 # Stop the NAT network user service
399 msg_stopping 'NAT networking on /dev/vmnet'"$vHubNr"
401 vmware_stop_pidfile /var/run/"$natd"-"$vHubNr".pid
402 [ "$?" -eq 0 ] && ok || fail
403 exitcode=`expr "$exitcode" + "$?"`
405 msg_stopping 'Host-only networking on /dev/vmnet'"$vHubNr"
407 vmware_stop_hostonly 'vmnet'"$vHubNr" "$hostaddr" "$netmask"
408 [ "$?" -eq 0 ] && ok || fail
409 exitcode=`expr "$exitcode" + "$?"`
412 vHubNr=`expr $vHubNr + 1`
414 msg_stopping 'Virtual ethernet'
416 if /sbin/lsmod | grep -q ^"$vnet"; then
419 [ "$?" -eq "0" ] && ok || fail
420 exitcode=`expr "$exitcode" + "$?"`
422 [ "$exitcode" -gt 0 ] && exit 1
423 rm -f /var/lock/subsys/"$subsys"
426 if [ "`countVMs`" -gt 0 ]; then
427 echo 'At least one instance of VMware Workstation is still running.'
430 if [ "$VM_NETWORKING" = "yes" ]; then
435 if [ "$VM_NETWORKING" = "yes" ]; then
436 echo -n "Module $vnet "
437 /sbin/modprobe "$vnet" >/dev/null 2>&1 && echo installed || echo "not installed"
441 "$0" stop && "$0" start
444 echo "Usage: `basename "$0"` {start|stop|status|restart}"