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
44 # Create /dev/vmnetXX device
45 vmware_create_vmnet() {
46 local vHubNr="$1" # IN
47 local vDevice="/dev/vmnet$vHubNr"
49 if [ ! -e "$vDevice" ]; then
50 mknod -m 600 "$vDevice" c 119 "$vHubNr"
55 # Create a temporary directory
58 # They are a lot of small utility programs to create temporary files in a
59 # secure way, but none of them is standard. So I wrote this --hpreg
61 local dirname="$1" # OUT
62 local prefix="$2" # IN
68 # Don't overwrite existing user data
69 # -> Create a directory with a name that didn't exist before
71 # This may never succeed (if we are racing with a malicious process), but at
75 while [ "$loop" = 'yes' ]; do
76 # Check the validity of the temporary directory. We do this in the loop
77 # because it can change over time
78 if [ ! -d "$tmp" ]; then
79 echo 'Error: "'"$tmp"'" is not a directory.'
83 if [ ! -w "$tmp" -o ! -x "$tmp" ]; then
84 echo 'Error: "'"$tmp"'" should be writable and executable.'
89 # -> Don't give write access to other users (so that they can not use this
90 # directory to launch a symlink attack)
91 if mkdir -m 0755 "$tmp"'/'"$prefix$serial" >/dev/null 2>&1; then
94 serial=`expr "$serial" + 1`
95 if [ "`expr "$serial" % 200`" = '0' ]; then
96 echo 'Warning: The "'"$tmp"'" directory may be under attack.'
101 eval "$dirname"'="$tmp"'"'"'/'"'"'"$prefix$serial"'
108 # Compute the subnet address associated to a couple IP/netmask
113 # Split quad-dotted addresses into bytes
114 # There is no double quote around the back-quoted expression on purpose
115 # There is no double quote around $ip and $netmask on purpose
116 set -- `IFS='.'; echo $ip $netmask`
117 echo $(($1 & $5)).$(($2 & $6)).$(($3 & $7)).$(($4 & $8))
120 # Compute the broadcast address associated to a couple IP/netmask
125 # Split quad-dotted addresses into bytes
126 # There is no double quote around the back-quoted expression on purpose
127 # There is no double quote around $ip and $netmask on purpose
128 set -- `IFS='.'; echo $ip $netmask`
129 echo $(($1 | (255 - $5))).$(($2 | (255 - $6))).$(($3 | (255 - $7))).$(($4 | (255 - $8)))
132 # Count the number of running virtual machines by looking at the number of references
133 # to the $driver module.
135 # Beware of module dependancies here. An exact match is important
136 /sbin/lsmod | awk 'BEGIN {n = 0;} {if ($1 == "'"$driver"'") n = $3;} END {print n;}'
139 # Check if there is an IP route for a given subnet via a given interface
140 # Return true if there is _NO_ such route
142 local subnet="$1" # IN
145 # Beware, there may be several identical routes
146 [ "`/sbin/route -n | grep '^'"$subnet"'.*'"$intf"'$'`" = '' ]
153 # . Each daemon must be started from its own directory to avoid busy devices
154 # . Each PID file doesn't need to be added to the installer database, because
155 # it is going to be automatically removed when it becomes stale (after a
156 # reboot). It must go directly under /var/run, or some distributions
157 # (RedHat 6.0) won't clean it
160 # Terminate a process synchronously
161 vmware_synchrone_kill() {
163 local signal="$2" # IN
166 kill -"$signal" "$pid"
167 # Wait a bit to see if the dirty job has really been done
168 for second in 0 1 2 3 4 5 6 7 8 9 10; do
169 if [ ! -d /proc/"$pid" ]; then
179 # Kill the process associated to a pidfile
180 vmware_stop_pidfile() {
181 local pidfile="$1" # IN
184 pid=`cat "$pidfile" 2>/dev/null`
185 if [ "$pid" = '' ]; then
186 # The file probably does not exist or is empty. Success
189 # Keep only the first number we find, because some Samba pid files are really
190 # trashy: they end with NUL characters
191 # There is no double quote around $pid on purpose
194 # First try a nice SIGTERM
195 if vmware_synchrone_kill "$pid" 15; then
198 # Then send a strong SIGKILL
199 if vmware_synchrone_kill "$pid" 9; then
205 # Start the host-only network user service
206 vmware_start_hostonly() {
207 local vHubNr="$1" # IN
208 local vHostIf="$2" # IN
210 local ifMask="$4" # IN
211 local run_dhcpd="$5" # IN
212 local run_samba="$6" # IN
215 # Do a cursory check to see if the host-only network
216 # configuration is still ok. We do this so that mobile
217 # hosts don't get setup at install time and then moved to
218 # a new locale where the host-only network config is no
221 # NB: This really needs to be done at power-on time when
222 # VM is configured to use host-only networking so that
223 # we aren't fooled by dynamic changes in the network.
225 # XXX ping takes 10 seconds to timeout if nobody answers
226 # that slows boot too much so we do this bit in the
228 if "$VM_BINDIR"/"$ping" -q "$ifIp"; then
229 echo 'Host-only networking disabled because '"$ifIp"
230 echo 'appears to be a real, physical, existing address.'
231 echo 'Please modify your host-only network configuration.'
234 cd "$VM_BINDIR" && "$VM_BINDIR"/"$netifup" \
235 -d /var/run/"$netifup"-"$vHostIf".pid /dev/vmnet"$vHubNr" "$vHostIf"
236 [ "$?" -eq 0 ] || exit 1
237 # Configure the virtual host ethernet interface and define the private IP
240 # . We provide the broadcast address explicitly because versions of ifconfig
241 # prior to 1.39 (1999-03-18) seem to miscompute it
242 # . 2.0.x kernels don't install a route when the interface is marked up, but
243 # 2.2.x kernel do. Since we want to see any errors from route we don't
244 # just discard messages from route, but instead check if the route got
245 # installed before manually adding one.
246 ifNet=`ipv4_subnet "$ifIp" "$ifMask"`
247 if ifconfig "$vHostIf" inet "$ifIp" netmask "$ifMask" \
248 broadcast "`ipv4_broadcast "$ifIp" "$ifMask"`" up \
249 && noRoutePresent "$ifNet" "$vHostIf"; then
250 route add -net "$ifNet" netmask "$ifMask" "$vHostIf"
252 if [ "$run_dhcpd" = 'yes' ]; then
253 # Start a DHCP server on a private IP network
254 # The daemon already logs its output in the system log, so we can safely
256 cd "$VM_BINDIR" && "$VM_BINDIR"/"$dhcpd" \
257 -cf "$vmware_etc_dir"/"$vHostIf"/dhcpd/dhcpd.conf \
258 -lf "$vmware_etc_dir"/"$vHostIf"/dhcpd/dhcpd.leases \
259 -pf /var/run/"$dhcpd"-"$vHostIf".pid "$vHostIf" >/dev/null 2>&1 || exit 1
261 if [ "$run_samba" = 'yes' ]; then
262 # Start a SMB name server on a private IP network
263 # Disable logging to avoid the uncontrolled creation of unmanaged files
264 cd "$VM_BINDIR" && "$VM_BINDIR"/"$nmbd" -D -l /dev/null \
265 -s "$vmware_etc_dir"/"$vHostIf"/smb/smb.conf \
266 -f /var/run/"$nmbd"-"$vHostIf".pid || exit 1
267 # Start a SMB share server on a private IP network
268 # Disable logging to avoid the uncontrolled creation of unmanaged files
269 cd "$VM_BINDIR" && "$VM_BINDIR"/"$smbd" -D -l /dev/null \
270 -s "$vmware_etc_dir"/"$vHostIf"/smb/smb.conf \
271 -f /var/run/"$smbd"-"$vHostIf".pid || exit 1
275 # Stop the host-only network user service
276 vmware_stop_hostonly() {
277 local vHostIf="$1" # IN
279 local ifMask="$3" # IN
282 # Terminate the private network
283 ifNet=`ipv4_subnet "$ifIp" "$ifMask"`
284 noRoutePresent "$ifNet" "$vHostIf" || route del -net "$ifNet" netmask "$ifMask" || exit 1
285 # To test if the interface exists, we can not just look at the exitcode
286 # because old versions of ifconfig don't exit with 1 when invoked with a
287 # non-existing interface
288 if [ "`ifconfig "$vHostIf" 2>/dev/null`" != '' ]; then
289 ifconfig "$vHostIf" down || exit 1
291 vmware_stop_pidfile /var/run/"$netifup"-"$vHostIf".pid || exit 1
294 # See how we were called.
297 if [ -f /var/lock/subsys/"$subsys" ]; then
298 msg_already_running "VMware Workstation networking"
300 # Try to load parport_pc. Failure is allowed as it does not exist
302 /sbin/modprobe parport_pc >/dev/null 2>&1
303 msg_starting 'Virtual machine monitor'
305 /sbin/modprobe $driver
306 [ "$?" -eq "0" ] && ok || fail
307 if [ "$VM_NETWORKING" = 'yes' ]; then
308 msg_starting 'Virtual ethernet'
311 [ "$?" -eq 0 ] && ok || fail
313 while [ $vHubNr -lt 9 ]; do
314 eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"'
315 eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"'
316 eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"'
317 if [ -n "$interface" ]; then
318 vmware_create_vmnet "$vHubNr"
319 # Connect a physical host ethernet interface to a virtual ethernet hub
320 msg_starting 'Bridged networking on /dev/vmnet'"$vHubNr"
322 cd "$VM_BINDIR" && "$VM_BINDIR"/"$bridge" \
323 -d /var/run/"$bridge"-"$vHubNr".pid /dev/vmnet"$vHubNr" "$interface"
324 [ "$?" -eq 0 ] && ok || fail
325 elif [ -n "$hostaddr" -a -n "$netmask" ]; then
326 vmware_create_vmnet "$vHubNr"
327 eval 'samba="$VNET_'"$vHubNr"'_SAMBA"'
328 msg_starting 'Host-only networking on /dev/vmnet'"$vHubNr"
330 vmware_start_hostonly "$vHubNr" 'vmnet'"$vHubNr" "$hostaddr" \
331 "$netmask" 'yes' "$samba"
332 [ "$?" -eq 0 ] && ok || fail
333 eval 'nat="$VNET_'"$vHubNr"'_NAT"'
334 if [ "$nat" = 'yes' ]; then
335 # Start the NAT network user service
336 msg_starting 'NAT networking on /dev/vmnet'"$vHubNr"
338 cd "$VM_BINDIR" && "$VM_BINDIR"/"$natd" \
339 -d /var/run/"$natd"-"$vHubNr".pid \
340 -m /var/run/"$natd"-"$vHubNr".mac \
341 -c "$vmware_etc_dir"/vmnet"$vHubNr"/nat/nat.conf >/dev/null 2>&1
342 [ "$?" -eq 0 ] && ok || fail
345 vHubNr=$(($vHubNr + 1))
348 touch /var/lock/subsys/"$subsys"
352 if [ "`countVMs`" -gt 0 ]; then
353 echo 'At least one instance of VMware Workstation is still running.'
354 echo 'Please stop all running instances of VMware Workstation first.'
357 if [ ! -f /var/lock/subsys/"$subsys" ]; then
358 msg_not_running "VMware Workstation networking"
360 # Try to unload parport_pc. Failure is allowed as it does not exist
361 # on kernels 2.0, and some other process could be using it.
362 /sbin/modprobe -r parport_pc >/dev/null 2>&1
363 if [ "$VM_NETWORKING" = "yes" ]; then
364 # NB: must kill off processes using vmnet before
367 while [ $vHubNr -lt 9 ]; do
368 eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"'
369 eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"'
370 eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"'
371 if [ -n "$interface" ]; then
372 # Disconnect a physical host ethernet interface from a virtual ethernet hub
373 msg_stopping "Bridged networking on /dev/vmnet$vHubNr"
375 vmware_stop_pidfile /var/run/"$bridge"-"$vHubNr".pid
376 [ "$?" -eq 0 ] && ok || fail
377 elif [ -n "$hostaddr" -a -n "$netmask" ]; then
378 # Stop a DHCP server on a private IP network
379 msg_stopping "DHCP server on /dev/vmnet$vHubNr"
381 vmware_stop_pidfile /var/run/"$dhcpd"-"vmnet$vHubNr".pid
382 [ "$?" -eq 0 ] && ok || fail
383 eval 'samba="$VNET_'"$vHubNr"'_SAMBA"'
384 if [ "$samba" = "yes" ]; then
385 # Stop a SMB share server on a private IP network
386 msg_stopping 'SMB share server on /dev/vmnet'"$vHubNr"
388 vmware_stop_pidfile /var/run/"$smbd"-'vmnet'"$vHubNr".pid
389 [ "$?" -eq 0 ] && ok || fail
390 # Stop a SMB name server on a private IP network
391 msg_stopping 'SMB name server on /dev/vmnet'"$vHubNr"
393 vmware_stop_pidfile /var/run/"$nmbd"-'vmnet'"$vHubNr".pid
394 [ "$?" -eq 0 ] && ok || fail
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
404 msg_stopping 'Host-only networking on /dev/vmnet'"$vHubNr"
406 vmware_stop_hostonly 'vmnet'"$vHubNr" "$hostaddr" "$netmask"
407 [ "$?" -eq 0 ] && ok || fail
410 vHubNr=$(($vHubNr + 1))
412 msg_stopping 'Virtual machine monitor'
414 if /sbin/lsmod | grep -q ^"$driver"; then
415 /sbin/rmmod "$driver"
417 [ "$?" -eq "0" ] && ok || fail
418 msg_stopping 'Virtual ethernet'
420 if /sbin/lsmod | grep -q ^"$vnet"; then
423 [ "$?" -eq "0" ] && ok || fail
425 rm -f /var/lock/subsys/"$subsys"
428 if [ "`countVMs`" -gt 0 ]; then
429 echo 'At least one instance of VMware Workstation is still running.'
432 if [ "$VM_NETWORKING" = "yes" ]; then
437 if [ "$VM_NETWORKING" = "yes" ]; then
438 echo -n "Module $vnet "
439 /sbin/modprobe "$vnet" >/dev/null 2>&1 && echo installed || echo "not installed"
443 "$0" stop && "$0" start
446 echo "Usage: `basename "$0"` {start|stop|status|restart}"