]>
Commit | Line | Data |
---|---|---|
29328d5b | 1 | #!/bin/sh |
36b33dd9 | 2 | |
29328d5b | 3 | # |
4 | # Copyright 1998 VMware, Inc. All rights reserved. | |
5 | # | |
6 | ||
d18baea8 | 7 | # vmnet: Manages the services needed to run VMware networking |
29328d5b | 8 | # |
d18baea8 | 9 | # description: Manages the services needed to run VMware networking |
a2c5e0b7 | 10 | # |
11 | # chkconfig: 5 90 8 | |
12 | # | |
13 | # probe: true | |
14 | # hide: true | |
15 | ||
a19ca04e | 16 | subsys=vmnet |
345c7964 | 17 | driver=vmmon |
18 | vnet=vmnet | |
19 | bridge=vmnet-bridge | |
20 | dhcpd=vmnet-dhcpd | |
21 | netifup=vmnet-netifup | |
22 | natd=vmnet-natd | |
23 | ping=vmware-ping | |
24 | smbd=vmware-smbd | |
25 | nmbd=vmware-nmbd | |
29328d5b | 26 | |
36b33dd9 | 27 | vmware_etc_dir=/etc/vmware |
2e3c2f73 | 28 | vmnet_cfg="$vmware_etc_dir"/vmnet.conf |
29 | if [ -r "$vmnet_cfg" ]; then | |
30 | . "$vmnet_cfg" | |
31 | else | |
36b33dd9 | 32 | echo "Warning: Unable to find VMware Workstation's main database" |
2e3c2f73 | 33 | echo "($vmnet_cfg)." |
36b33dd9 | 34 | echo |
35 | exit 1 | |
36 | fi | |
37 | ||
38 | # System wide functions | |
39 | . /etc/rc.d/init.d/functions | |
40 | ||
29328d5b | 41 | # |
345c7964 | 42 | # Create a temporary directory |
29328d5b | 43 | # |
44 | ||
345c7964 | 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 | |
47 | make_tmp_dir() { | |
48 | local dirname="$1" # OUT | |
49 | local prefix="$2" # IN | |
50 | local tmp | |
51 | local serial | |
52 | local loop | |
53 | ||
54 | tmp="${TMPDIR:-/tmp}" | |
345c7964 | 55 | # Don't overwrite existing user data |
56 | # -> Create a directory with a name that didn't exist before | |
57 | # | |
58 | # This may never succeed (if we are racing with a malicious process), but at | |
59 | # least it is secure | |
60 | serial=0 | |
61 | loop='yes' | |
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.' | |
67 | echo | |
68 | exit 1 | |
69 | fi | |
70 | if [ ! -w "$tmp" -o ! -x "$tmp" ]; then | |
71 | echo 'Error: "'"$tmp"'" should be writable and executable.' | |
72 | echo | |
73 | exit 1 | |
74 | fi | |
75 | # Be secure | |
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 | |
79 | loop='no' | |
80 | else | |
81 | serial=`expr "$serial" + 1` | |
82 | if [ "`expr "$serial" % 200`" = '0' ]; then | |
83 | echo 'Warning: The "'"$tmp"'" directory may be under attack.' | |
84 | echo | |
85 | fi | |
86 | fi | |
87 | done | |
88 | eval "$dirname"'="$tmp"'"'"'/'"'"'"$prefix$serial"' | |
89 | } | |
29328d5b | 90 | |
29328d5b | 91 | # |
36b33dd9 | 92 | # Utilities |
29328d5b | 93 | # |
345c7964 | 94 | |
29328d5b | 95 | # Compute the subnet address associated to a couple IP/netmask |
96 | ipv4_subnet() { | |
345c7964 | 97 | local ip="$1" |
98 | local netmask="$2" | |
29328d5b | 99 | |
345c7964 | 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)) | |
29328d5b | 105 | } |
106 | ||
107 | # Compute the broadcast address associated to a couple IP/netmask | |
108 | ipv4_broadcast() { | |
345c7964 | 109 | local ip="$1" |
110 | local netmask="$2" | |
29328d5b | 111 | |
345c7964 | 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))) | |
29328d5b | 117 | } |
118 | ||
36b33dd9 | 119 | # Count the number of running virtual machines by looking at the number of references |
120 | # to the $driver module. | |
29328d5b | 121 | countVMs() { |
345c7964 | 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;}' | |
29328d5b | 124 | } |
125 | ||
29328d5b | 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 | |
128 | noRoutePresent() { | |
345c7964 | 129 | local subnet="$1" # IN |
130 | local intf="$2" # IN | |
29328d5b | 131 | |
345c7964 | 132 | # Beware, there may be several identical routes |
133 | [ "`/sbin/route -n | grep '^'"$subnet"'.*'"$intf"'$'`" = '' ] | |
29328d5b | 134 | } |
135 | ||
29328d5b | 136 | |
29328d5b | 137 | # Macro definitions |
138 | # | |
139 | # Note: | |
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 | |
145 | # | |
146 | ||
147 | # Terminate a process synchronously | |
148 | vmware_synchrone_kill() { | |
345c7964 | 149 | local pid="$1" # IN |
150 | local signal="$2" # IN | |
151 | local second | |
152 | ||
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 | |
157 | # Success | |
158 | return 0 | |
159 | fi | |
160 | sleep 1 | |
161 | done | |
162 | # Timeout | |
163 | return 1 | |
29328d5b | 164 | } |
165 | ||
166 | # Kill the process associated to a pidfile | |
167 | vmware_stop_pidfile() { | |
345c7964 | 168 | local pidfile="$1" # IN |
169 | local pid | |
29328d5b | 170 | |
345c7964 | 171 | pid=`cat "$pidfile" 2>/dev/null` |
172 | if [ "$pid" = '' ]; then | |
173 | # The file probably does not exist or is empty. Success | |
174 | return 0 | |
175 | fi | |
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 | |
179 | set -- $pid | |
180 | pid="$1" | |
181 | # First try a nice SIGTERM | |
182 | if vmware_synchrone_kill "$pid" 15; then | |
183 | return 0 | |
184 | fi | |
185 | # Then send a strong SIGKILL | |
186 | if vmware_synchrone_kill "$pid" 9; then | |
187 | return 0 | |
188 | fi | |
189 | return 1 | |
29328d5b | 190 | } |
191 | ||
29328d5b | 192 | # Start the host-only network user service |
193 | vmware_start_hostonly() { | |
345c7964 | 194 | local vHubNr="$1" # IN |
195 | local vHostIf="$2" # IN | |
196 | local ifIp="$3" # IN | |
197 | local ifMask="$4" # IN | |
198 | local run_dhcpd="$5" # IN | |
199 | local run_samba="$6" # IN | |
200 | local ifNet | |
201 | ||
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 | |
206 | # longer valid. | |
207 | # | |
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. | |
211 | # | |
212 | # XXX ping takes 10 seconds to timeout if nobody answers | |
213 | # that slows boot too much so we do this bit in the | |
214 | # background. | |
2e3c2f73 | 215 | if "$VMNET_BINDIR"/"$ping" -q "$ifIp"; then |
345c7964 | 216 | echo 'Host-only networking disabled because '"$ifIp" |
217 | echo 'appears to be a real, physical, existing address.' | |
36b33dd9 | 218 | echo 'Please modify your host-only network configuration.' |
345c7964 | 219 | exit 1 |
220 | fi | |
2e3c2f73 | 221 | cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$netifup" \ |
345c7964 | 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 | |
225 | # network | |
226 | # | |
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" | |
238 | fi | |
239 | if [ "$run_dhcpd" = 'yes' ]; then | |
36b33dd9 | 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 | |
242 | # trash it | |
2e3c2f73 | 243 | cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$dhcpd" \ |
36b33dd9 | 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 | |
345c7964 | 247 | fi |
248 | if [ "$run_samba" = 'yes' ]; then | |
36b33dd9 | 249 | # Start a SMB name server on a private IP network |
250 | # Disable logging to avoid the uncontrolled creation of unmanaged files | |
2e3c2f73 | 251 | cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$nmbd" -D -l /dev/null \ |
36b33dd9 | 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 | |
2e3c2f73 | 256 | cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$smbd" -D -l /dev/null \ |
36b33dd9 | 257 | -s "$vmware_etc_dir"/"$vHostIf"/smb/smb.conf \ |
258 | -f /var/run/"$smbd"-"$vHostIf".pid || exit 1 | |
345c7964 | 259 | fi |
29328d5b | 260 | } |
261 | ||
262 | # Stop the host-only network user service | |
263 | vmware_stop_hostonly() { | |
345c7964 | 264 | local vHostIf="$1" # IN |
265 | local ifIp="$2" # IN | |
266 | local ifMask="$3" # IN | |
267 | local ifNet | |
268 | ||
269 | # Terminate the private network | |
270 | ifNet=`ipv4_subnet "$ifIp" "$ifMask"` | |
271 | noRoutePresent "$ifNet" "$vHostIf" || route del -net "$ifNet" netmask "$ifMask" || exit 1 | |
272 | # To test if the interface exists, we can not just look at the exitcode | |
273 | # because old versions of ifconfig don't exit with 1 when invoked with a | |
274 | # non-existing interface | |
275 | if [ "`ifconfig "$vHostIf" 2>/dev/null`" != '' ]; then | |
276 | ifconfig "$vHostIf" down || exit 1 | |
277 | fi | |
278 | vmware_stop_pidfile /var/run/"$netifup"-"$vHostIf".pid || exit 1 | |
29328d5b | 279 | } |
280 | ||
29328d5b | 281 | # See how we were called. |
282 | case "$1" in | |
283 | start) | |
2e3c2f73 | 284 | if [ -f /var/lock/subsys/"$subsys" ]; then |
285 | msg_already_running "VMware Workstation networking" | |
286 | exit 1 | |
287 | fi | |
345c7964 | 288 | # Try to load parport_pc. Failure is allowed as it does not exist |
289 | # on kernels 2.0 | |
290 | /sbin/modprobe parport_pc >/dev/null 2>&1 | |
2e3c2f73 | 291 | if [ "$VM_NETWORKING" = 'yes' ]; then |
a5a25ae1 | 292 | msg_starting 'Virtual ethernet' |
293 | busy | |
345c7964 | 294 | /sbin/modprobe $vnet |
a5a25ae1 | 295 | [ "$?" -eq 0 ] && ok || fail |
a5a25ae1 | 296 | vHubNr=0 |
3c42bb59 | 297 | while [ $vHubNr -lt 8 ]; do |
2e3c2f73 | 298 | eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"' |
299 | eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"' | |
300 | eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"' | |
a5a25ae1 | 301 | if [ -n "$interface" ]; then |
345c7964 | 302 | # Connect a physical host ethernet interface to a virtual ethernet hub |
a5a25ae1 | 303 | msg_starting 'Bridged networking on /dev/vmnet'"$vHubNr" |
304 | busy | |
2e3c2f73 | 305 | cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$bridge" \ |
345c7964 | 306 | -d /var/run/"$bridge"-"$vHubNr".pid /dev/vmnet"$vHubNr" "$interface" |
a5a25ae1 | 307 | [ "$?" -eq 0 ] && ok || fail |
a5a25ae1 | 308 | elif [ -n "$hostaddr" -a -n "$netmask" ]; then |
2e3c2f73 | 309 | eval 'samba="$VNET_'"$vHubNr"'_SAMBA"' |
345c7964 | 310 | msg_starting 'Host-only networking on /dev/vmnet'"$vHubNr" |
311 | busy | |
2e3c2f73 | 312 | daemon vmware_start_hostonly "$vHubNr" 'vmnet'"$vHubNr" "$hostaddr" \ |
313 | "$netmask" 'yes' "$samba" | |
345c7964 | 314 | [ "$?" -eq 0 ] && ok || fail |
2e3c2f73 | 315 | eval 'nat="$VNET_'"$vHubNr"'_NAT"' |
a5a25ae1 | 316 | if [ "$nat" = 'yes' ]; then |
36b33dd9 | 317 | # Start the NAT network user service |
345c7964 | 318 | msg_starting 'NAT networking on /dev/vmnet'"$vHubNr" |
319 | busy | |
2e3c2f73 | 320 | cd "$VMNET_BINDIR" && "$VMNET_BINDIR"/"$natd" \ |
36b33dd9 | 321 | -d /var/run/"$natd"-"$vHubNr".pid \ |
322 | -m /var/run/"$natd"-"$vHubNr".mac \ | |
323 | -c "$vmware_etc_dir"/vmnet"$vHubNr"/nat/nat.conf | |
345c7964 | 324 | [ "$?" -eq 0 ] && ok || fail |
a5a25ae1 | 325 | fi |
326 | fi | |
e103a664 | 327 | vHubNr=$(($vHubNr + 1)) |
a5a25ae1 | 328 | done |
29328d5b | 329 | |
330 | fi | |
29328d5b | 331 | touch /var/lock/subsys/"$subsys" |
332 | ;; | |
333 | ||
334 | stop) | |
335 | if [ "`countVMs`" -gt 0 ]; then | |
36b33dd9 | 336 | echo 'At least one instance of VMware Workstation is still running.' |
337 | echo 'Please stop all running instances of VMware Workstation first.' | |
345c7964 | 338 | echo |
2e3c2f73 | 339 | exit 1 |
29328d5b | 340 | fi |
2e3c2f73 | 341 | if [ ! -f /var/lock/subsys/"$subsys" ]; then |
342 | msg_not_running "VMware Workstation networking" | |
343 | exit 1 | |
344 | fi | |
345c7964 | 345 | # Try to unload parport_pc. Failure is allowed as it does not exist |
346 | # on kernels 2.0, and some other process could be using it. | |
347 | /sbin/modprobe -r parport_pc >/dev/null 2>&1 | |
2e3c2f73 | 348 | if [ "$VM_NETWORKING" = "yes" ]; then |
a5a25ae1 | 349 | # NB: must kill off processes using vmnet before |
350 | # unloading module | |
351 | vHubNr=0 | |
3c42bb59 | 352 | while [ $vHubNr -lt 8 ]; do |
2e3c2f73 | 353 | eval 'interface="$VNET_'"$vHubNr"'_INTERFACE"' |
354 | eval 'hostaddr="$VNET_'"$vHubNr"'_HOSTONLY_HOSTADDR"' | |
355 | eval 'netmask="$VNET_'"$vHubNr"'_HOSTONLY_NETMASK"' | |
a5a25ae1 | 356 | if [ -n "$interface" ]; then |
345c7964 | 357 | # Disconnect a physical host ethernet interface from a virtual ethernet hub |
a5a25ae1 | 358 | msg_stopping "Bridged networking on /dev/vmnet$vHubNr" |
359 | busy | |
345c7964 | 360 | vmware_stop_pidfile /var/run/"$bridge"-"$vHubNr".pid |
a5a25ae1 | 361 | [ "$?" -eq 0 ] && ok || fail |
a5a25ae1 | 362 | elif [ -n "$hostaddr" -a -n "$netmask" ]; then |
36b33dd9 | 363 | # Stop a DHCP server on a private IP network |
345c7964 | 364 | msg_stopping "DHCP server on /dev/vmnet$vHubNr" |
365 | busy | |
36b33dd9 | 366 | vmware_stop_pidfile /var/run/"$dhcpd"-"vmnet$vHubNr".pid |
345c7964 | 367 | [ "$?" -eq 0 ] && ok || fail |
2e3c2f73 | 368 | eval 'samba="$VNET_'"$vHubNr"'_SAMBA"' |
a5a25ae1 | 369 | if [ "$samba" = "yes" ]; then |
36b33dd9 | 370 | # Stop a SMB share server on a private IP network |
345c7964 | 371 | msg_stopping 'SMB share server on /dev/vmnet'"$vHubNr" |
372 | busy | |
36b33dd9 | 373 | vmware_stop_pidfile /var/run/"$smbd"-'vmnet'"$vHubNr".pid |
345c7964 | 374 | [ "$?" -eq 0 ] && ok || fail |
36b33dd9 | 375 | # Stop a SMB name server on a private IP network |
345c7964 | 376 | msg_stopping 'SMB name server on /dev/vmnet'"$vHubNr" |
377 | busy | |
36b33dd9 | 378 | vmware_stop_pidfile /var/run/"$nmbd"-'vmnet'"$vHubNr".pid |
345c7964 | 379 | [ "$?" -eq 0 ] && ok || fail |
a5a25ae1 | 380 | fi |
2e3c2f73 | 381 | eval 'nat="$VNET_'"$vHubNr"'_NAT"' |
a5a25ae1 | 382 | if [ "$nat" = "yes" ]; then |
36b33dd9 | 383 | # Stop the NAT network user service |
345c7964 | 384 | msg_stopping 'NAT networking on /dev/vmnet'"$vHubNr" |
385 | busy | |
36b33dd9 | 386 | vmware_stop_pidfile /var/run/"$natd"-"$vHubNr".pid |
345c7964 | 387 | [ "$?" -eq 0 ] && ok || fail |
a5a25ae1 | 388 | fi |
345c7964 | 389 | msg_stopping 'Host-only networking on /dev/vmnet'"$vHubNr" |
390 | busy | |
a5a25ae1 | 391 | vmware_stop_hostonly 'vmnet'"$vHubNr" "$hostaddr" "$netmask" |
345c7964 | 392 | [ "$?" -eq 0 ] && ok || fail |
a5a25ae1 | 393 | |
394 | fi | |
e103a664 | 395 | vHubNr=$(($vHubNr + 1)) |
a5a25ae1 | 396 | done |
397 | msg_stopping 'Virtual ethernet' | |
398 | busy | |
36b33dd9 | 399 | if /sbin/lsmod | grep -q ^"$vnet"; then |
345c7964 | 400 | /sbin/rmmod "$vnet" |
401 | fi | |
a5a25ae1 | 402 | [ "$?" -eq "0" ] && ok || fail |
29328d5b | 403 | fi |
29328d5b | 404 | rm -f /var/lock/subsys/"$subsys" |
405 | ;; | |
29328d5b | 406 | status) |
407 | if [ "`countVMs`" -gt 0 ]; then | |
36b33dd9 | 408 | echo 'At least one instance of VMware Workstation is still running.' |
a5a25ae1 | 409 | echo |
29328d5b | 410 | fi |
2e3c2f73 | 411 | if [ "$VM_NETWORKING" = "yes" ]; then |
a5a25ae1 | 412 | status "$bridge" |
413 | status "$dhcpd" | |
414 | status "$netifup" | |
29328d5b | 415 | fi |
2e3c2f73 | 416 | if [ "$VM_NETWORKING" = "yes" ]; then |
a5a25ae1 | 417 | echo -n "Module $vnet " |
418 | /sbin/modprobe "$vnet" >/dev/null 2>&1 && echo installed || echo "not installed" | |
29328d5b | 419 | fi |
420 | ;; | |
29328d5b | 421 | restart) |
422 | "$0" stop && "$0" start | |
423 | ;; | |
29328d5b | 424 | *) |
425 | echo "Usage: `basename "$0"` {start|stop|status|restart}" | |
426 | exit 1 | |
427 | esac | |
428 | ||
429 | exit 0 |