]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - etc/rc.d/jail
MFC r238980:
[FreeBSD/stable/8.git] / etc / rc.d / jail
1 #!/bin/sh
2 #
3 # $FreeBSD$
4 #
5
6 # PROVIDE: jail
7 # REQUIRE: LOGIN cleanvar
8 # BEFORE: securelevel
9 # KEYWORD: nojail shutdown
10
11 # WARNING: This script deals with untrusted data (the data and
12 # processes inside the jails) and care must be taken when changing the
13 # code related to this!  If you have any doubt whether a change is
14 # correct and have security impact, please get the patch reviewed by
15 # the FreeBSD Security Team prior to commit.
16
17 . /etc/rc.subr
18
19 name="jail"
20 rcvar="jail_enable"
21 start_cmd="jail_start"
22 stop_cmd="jail_stop"
23
24 # init_variables _j
25 #       Initialize the various jail variables for jail _j.
26 #
27 init_variables()
28 {
29         _j="$1"
30
31         if [ -z "$_j" ]; then
32                 warn "init_variables: you must specify a jail"
33                 return
34         fi
35
36         eval _rootdir=\"\$jail_${_j}_rootdir\"
37         _devdir="${_rootdir}/dev"
38         _fdescdir="${_devdir}/fd"
39         _procdir="${_rootdir}/proc"
40         eval _hostname=\"\$jail_${_j}_hostname\"
41         eval _ip=\"\$jail_${_j}_ip\"
42         eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
43         eval _exec=\"\$jail_${_j}_exec\"
44
45         i=0
46         while : ; do
47                 eval _exec_prestart${i}=\"\${jail_${_j}_exec_prestart${i}:-\${jail_exec_prestart${i}}}\"
48                 [ -z "$(eval echo \"\$_exec_prestart${i}\")" ] && break
49                 i=$((i + 1))
50         done
51
52         eval _exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\"
53
54         i=1
55         while : ; do
56                 eval _exec_afterstart${i}=\"\${jail_${_j}_exec_afterstart${i}:-\${jail_exec_afterstart${i}}}\"
57                 [ -z "$(eval echo \"\$_exec_afterstart${i}\")" ] &&  break
58                 i=$((i + 1))
59         done
60
61         i=0
62         while : ; do
63                 eval _exec_poststart${i}=\"\${jail_${_j}_exec_poststart${i}:-\${jail_exec_poststart${i}}}\"
64                 [ -z "$(eval echo \"\$_exec_poststart${i}\")" ] && break
65                 i=$((i + 1))
66         done
67
68         i=0
69         while : ; do
70                 eval _exec_prestop${i}=\"\${jail_${_j}_exec_prestop${i}:-\${jail_exec_prestop${i}}}\"
71                 [ -z "$(eval echo \"\$_exec_prestop${i}\")" ] && break
72                 i=$((i + 1))
73         done
74
75         eval _exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
76
77         i=0
78         while : ; do
79                 eval _exec_poststop${i}=\"\${jail_${_j}_exec_poststop${i}:-\${jail_exec_poststop${i}}}\"
80                 [ -z "$(eval echo \"\$_exec_poststop${i}\")" ] && break
81                 i=$((i + 1))
82         done
83
84         if [ -n "${_exec}" ]; then
85                 #   simple/backward-compatible execution
86                 _exec_start="${_exec}"
87                 _exec_stop=""
88         else
89                 #   flexible execution
90                 if [ -z "${_exec_start}" ]; then
91                         _exec_start="/bin/sh /etc/rc"
92                         if [ -z "${_exec_stop}" ]; then
93                                 _exec_stop="/bin/sh /etc/rc.shutdown"
94                         fi
95                 fi
96         fi
97
98         # The default jail ruleset will be used by rc.subr if none is specified.
99         eval _ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\"
100         eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\"
101         [ -z "${_devfs}" ] && _devfs="NO"
102         eval _fdescfs=\"\${jail_${_j}_fdescfs_enable:-${jail_fdescfs_enable}}\"
103         [ -z "${_fdescfs}" ] && _fdescfs="NO"
104         eval _procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\"
105         [ -z "${_procfs}" ] && _procfs="NO"
106
107         eval _mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\"
108         [ -z "${_mount}" ] && _mount="NO"
109         # "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified.
110         eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\"
111         [ -z "${_fstab}" ] && _fstab="/etc/fstab.${_j}"
112         eval _flags=\"\${jail_${_j}_flags:-${jail_flags}}\"
113         [ -z "${_flags}" ] && _flags="-l -U root"
114         eval _consolelog=\"\${jail_${_j}_consolelog:-${jail_consolelog}}\"
115         [ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log"
116         eval _parameters=\"\${jail_${_j}_parameters:-${jail_parameters}}\"
117         [ -z "${_parameters}" ] && _parameters=""
118         eval _fib=\"\${jail_${_j}_fib:-${jail_fib}}\"
119
120         # Debugging aid
121         #
122         debug "$_j devfs enable: $_devfs"
123         debug "$_j fdescfs enable: $_fdescfs"
124         debug "$_j procfs enable: $_procfs"
125         debug "$_j mount enable: $_mount"
126         debug "$_j hostname: $_hostname"
127         debug "$_j ip: $_ip"
128         jail_show_addresses ${_j}
129         debug "$_j interface: $_interface"
130         debug "$_j fib: $_fib"
131         debug "$_j root: $_rootdir"
132         debug "$_j devdir: $_devdir"
133         debug "$_j fdescdir: $_fdescdir"
134         debug "$_j procdir: $_procdir"
135         debug "$_j ruleset: $_ruleset"
136         debug "$_j fstab: $_fstab"
137
138         i=0
139         while : ; do
140                 eval out=\"\${_exec_prestart${i}:-''}\"
141                 if [ -z "$out" ]; then
142                         break
143                 fi
144                 debug "$_j exec pre-start #${i}: ${out}"
145                 i=$((i + 1))
146         done
147
148         debug "$_j exec start: $_exec_start"
149
150         i=1
151         while : ; do
152                 eval out=\"\${_exec_afterstart${i}:-''}\"
153
154                 if [ -z "$out" ]; then
155                         break;
156                 fi
157
158                 debug "$_j exec after start #${i}: ${out}"
159                 i=$((i + 1))
160         done
161
162         i=0
163         while : ; do
164                 eval out=\"\${_exec_poststart${i}:-''}\"
165                 if [ -z "$out" ]; then
166                         break
167                 fi
168                 debug "$_j exec post-start #${i}: ${out}"
169                 i=$((i + 1))
170         done
171
172         i=0
173         while : ; do
174                 eval out=\"\${_exec_prestop${i}:-''}\"
175                 if [ -z "$out" ]; then
176                         break
177                 fi
178                 debug "$_j exec pre-stop #${i}: ${out}"
179                 i=$((i + 1))
180         done
181
182         debug "$_j exec stop: $_exec_stop"
183
184         i=0
185         while : ; do
186                 eval out=\"\${_exec_poststop${i}:-''}\"
187                 if [ -z "$out" ]; then
188                         break
189                 fi
190                 debug "$_j exec post-stop #${i}: ${out}"
191                 i=$((i + 1))
192         done
193
194         debug "$_j flags: $_flags"
195         debug "$_j consolelog: $_consolelog"
196         debug "$_j parameters: $_parameters"
197
198         if [ -z "${_hostname}" ]; then
199                 err 3 "$name: No hostname has been defined for ${_j}"
200         fi
201         if [ -z "${_rootdir}" ]; then
202                 err 3 "$name: No root directory has been defined for ${_j}"
203         fi
204 }
205
206 # set_sysctl rc_knob mib msg
207 #       If the mib sysctl is set according to what rc_knob
208 #       specifies, this function does nothing. However if
209 #       rc_knob is set differently than mib, then the mib
210 #       is set accordingly and msg is displayed followed by
211 #       an '=" sign and the word 'YES' or 'NO'.
212 #
213 set_sysctl()
214 {
215         _knob="$1"
216         _mib="$2"
217         _msg="$3"
218
219         _current=`${SYSCTL} -n $_mib 2>/dev/null`
220         if checkyesno $_knob ; then
221                 if [ "$_current" -ne 1 ]; then
222                         echo -n " ${_msg}=YES"
223                         ${SYSCTL_W} 1>/dev/null ${_mib}=1
224                 fi
225         else
226                 if [ "$_current" -ne 0 ]; then
227                         echo -n " ${_msg}=NO"
228                         ${SYSCTL_W} 1>/dev/null ${_mib}=0
229                 fi
230         fi
231 }
232
233 # is_current_mountpoint()
234 #       Is the directory mount point for a currently mounted file
235 #       system?
236 #
237 is_current_mountpoint()
238 {
239         local _dir _dir2
240
241         _dir=$1
242
243         _dir=`echo $_dir | sed -Ee 's#//+#/#g' -e 's#/$##'`
244         [ ! -d "${_dir}" ] && return 1
245         _dir2=`df ${_dir} | tail +2 | awk '{ print $6 }'`
246         [ "${_dir}" = "${_dir2}" ]
247         return $?
248 }
249
250 # is_symlinked_mountpoint()
251 #       Is a mount point, or any of its parent directories, a symlink?
252 #
253 is_symlinked_mountpoint()
254 {
255         local _dir
256
257         _dir=$1
258
259         [ -L "$_dir" ] && return 0
260         [ "$_dir" = "/" ] && return 1
261         is_symlinked_mountpoint `dirname $_dir`
262         return $?
263 }
264
265 # secure_umount
266 #       Try to unmount a mount point without being vulnerable to
267 #       symlink attacks.
268 #
269 secure_umount()
270 {
271         local _dir
272
273         _dir=$1
274
275         if is_current_mountpoint ${_dir}; then
276                 umount -f ${_dir} >/dev/null 2>&1
277         else
278                 debug "Nothing mounted on ${_dir} - not unmounting"
279         fi
280 }
281
282
283 # jail_umount_fs
284 #       This function unmounts certain special filesystems in the
285 #       currently selected jail. The caller must call the init_variables()
286 #       routine before calling this one.
287 #
288 jail_umount_fs()
289 {
290         local _device _mountpt _rest
291
292         if checkyesno _fdescfs; then
293                 if [ -d "${_fdescdir}" ] ; then
294                         secure_umount ${_fdescdir}
295                 fi
296         fi
297         if checkyesno _devfs; then
298                 if [ -d "${_devdir}" ] ; then
299                         secure_umount ${_devdir}
300                 fi
301         fi
302         if checkyesno _procfs; then
303                 if [ -d "${_procdir}" ] ; then
304                         secure_umount ${_procdir}
305                 fi
306         fi
307         if checkyesno _mount; then
308                 [ -f "${_fstab}" ] || warn "${_fstab} does not exist"
309                 tail -r ${_fstab} | while read _device _mountpt _rest; do
310                         case ":${_device}" in
311                         :#* | :)
312                                 continue
313                                 ;;
314                         esac
315                         secure_umount ${_mountpt}
316                 done
317         fi
318 }
319
320 # jail_mount_fstab()
321 #       Mount file systems from a per jail fstab while trying to
322 #       secure against symlink attacks at the mount points.
323 #
324 #       If we are certain we cannot secure against symlink attacks we
325 #       do not mount all of the file systems (since we cannot just not
326 #       mount the file system with the problematic mount point).
327 #
328 #       The caller must call the init_variables() routine before
329 #       calling this one.
330 #
331 jail_mount_fstab()
332 {
333         local _device _mountpt _rest
334
335         while read _device _mountpt _rest; do
336                 case ":${_device}" in
337                 :#* | :)
338                         continue
339                         ;;
340                 esac
341                 if is_symlinked_mountpoint ${_mountpt}; then
342                         warn "${_mountpt} has symlink as parent - not mounting from ${_fstab}"
343                         return
344                 fi
345         done <${_fstab}
346         mount -a -F "${_fstab}"
347 }
348
349 # jail_show_addresses jail
350 #       Debug print the input for the given _multi aliases
351 #       for a jail for init_variables().
352 #
353 jail_show_addresses()
354 {
355         local _j _type alias
356         _j="$1"
357         alias=0
358
359         if [ -z "${_j}" ]; then
360                 warn "jail_show_addresses: you must specify a jail"
361                 return
362         fi
363
364         while : ; do
365                 eval _addr=\"\$jail_${_j}_ip_multi${alias}\"
366                 if [ -n "${_addr}" ]; then
367                         debug "${_j} ip_multi${alias}: $_addr"
368                         alias=$((${alias} + 1))
369                 else
370                         break
371                 fi
372         done
373 }
374
375 # jail_extract_address argument
376 #       The second argument is the string from one of the _ip
377 #       or the _multi variables. In case of a comma separated list
378 #       only one argument must be passed in at a time.
379 #       The function alters the _type, _iface, _addr and _mask variables.
380 #
381 jail_extract_address()
382 {
383         local _i
384         _i=$1
385
386         if [ -z "${_i}" ]; then
387                 warn "jail_extract_address: called without input"
388                 return
389         fi
390
391         # Check if we have an interface prefix given and split into
392         # iFace and rest.
393         case "${_i}" in
394         *\|*)   # ifN|.. prefix there
395                 _iface=${_i%%|*}
396                 _r=${_i##*|}
397                 ;;
398         *)      _iface=""
399                 _r=${_i}
400                 ;;
401         esac
402
403         # In case the IP has no interface given, check if we have a global one.
404         _iface=${_iface:-${_interface}}
405
406         # Set address, cut off any prefix/netmask/prefixlen.
407         _addr=${_r}
408         _addr=${_addr%%[/ ]*}
409
410         # Theoretically we can return here if interface is not set,
411         # as we only care about the _mask if we call ifconfig.
412         # This is not done because we may want to santize IP addresses
413         # based on _type later, and optionally change the type as well.
414
415         # Extract the prefix/netmask/prefixlen part by cutting off the address.
416         _mask=${_r}
417         _mask=`expr "${_mask}" : "${_addr}\(.*\)"`
418
419         # Identify type {inet,inet6}.
420         case "${_addr}" in
421         *\.*\.*\.*)     _type="inet" ;;
422         *:*)            _type="inet6" ;;
423         *)              warn "jail_extract_address: type not identified"
424                         ;;
425         esac
426
427         # Handle the special /netmask instead of /prefix or
428         # "netmask xxx" case for legacy IP.
429         # We do NOT support shortend class-full netmasks.
430         if [ "${_type}" = "inet" ]; then
431                 case "${_mask}" in
432                 /*\.*\.*\.*)    _mask=" netmask ${_mask#/}" ;;
433                 *)              ;;
434                 esac
435
436                 # In case _mask is still not set use /32.
437                 _mask=${_mask:-/32}
438
439         elif [ "${_type}" = "inet6" ]; then
440                 # In case _maske is not set for IPv6, use /128.
441                 _mask=${_mask:-/128}
442         fi
443 }
444
445 # jail_handle_ips_option {add,del} input
446 #       Handle a single argument imput which can be a comma separated
447 #       list of addresses (theoretically with an option interface and
448 #       prefix/netmask/prefixlen).
449 #
450 jail_handle_ips_option()
451 {
452         local _x _action _type _i
453         _action=$1
454         _x=$2
455
456         if [ -z "${_x}" ]; then
457                 # No IP given. This can happen for the primary address
458                 # of each address family.
459                 return
460         fi
461
462         # Loop, in case we find a comma separated list, we need to handle
463         # each argument on its own.
464         while [ ${#_x} -gt 0 ]; do
465                 case "${_x}" in
466                 *,*)    # Extract the first argument and strip it off the list.
467                         _i=`expr "${_x}" : '^\([^,]*\)'`
468                         _x=`expr "${_x}" : "^[^,]*,\(.*\)"`
469                         ;;
470                 *)      _i=${_x}
471                         _x=""
472                         ;;
473                 esac
474
475                 _type=""
476                 _iface=""
477                 _addr=""
478                 _mask=""
479                 jail_extract_address "${_i}"
480
481                 # make sure we got an address.
482                 case "${_addr}" in
483                 "")     continue ;;
484                 *)      ;;
485                 esac
486
487                 # Append address to list of addresses for the jail command.
488                 case "${_type}" in
489                 inet)
490                         case "${_addrl}" in
491                         "")     _addrl="${_addr}" ;;
492                         *)      _addrl="${_addrl},${_addr}" ;;
493                         esac
494                         ;;
495                 inet6)
496                         case "${_addr6l}" in
497                         "")     _addr6l="${_addr}" ;;
498                         *)      _addr6l="${_addr6l},${_addr}" ;;
499                         esac
500                         ;;
501                 esac
502
503                 # Configure interface alias if requested by a given interface
504                 # and if we could correctly parse everything.
505                 case "${_iface}" in
506                 "")     continue ;;
507                 esac
508                 case "${_type}" in
509                 inet)   ;;
510                 inet6)  ipv6_address_count=$((ipv6_address_count + 1)) ;;
511                 *)      warn "Could not determine address family.  Not going" \
512                             "to ${_action} address '${_addr}' for ${_jail}."
513                         continue
514                         ;;
515                 esac
516                 case "${_action}" in
517                 add)    ifconfig ${_iface} ${_type} ${_addr}${_mask} alias
518                         ;;
519                 del)    # When removing the IP, ignore the _mask.
520                         ifconfig ${_iface} ${_type} ${_addr} -alias
521                         ;;
522                 esac
523         done
524 }
525
526 # jail_ips {add,del}
527 #       Extract the comma separated list of addresses and return them
528 #       for the jail command.
529 #       Handle more than one address via the _multi option as well.
530 #       If an interface is given also add/remove an alias for the
531 #       address with an optional netmask.
532 #
533 jail_ips()
534 {
535         local _action
536         _action=$1
537
538         case "${_action}" in
539         add)    ;;
540         del)    ;;
541         *)      warn "jail_ips: invalid action '${_action}'"
542                 return
543                 ;;
544         esac
545
546         # Handle addresses.
547         ipv6_address_count=0
548         jail_handle_ips_option ${_action} "${_ip}"
549         # Handle jail_xxx_ip_multi<N>
550         alias=0
551         while : ; do
552                 eval _x=\"\$jail_${_jail}_ip_multi${alias}\"
553                 case "${_x}" in
554                 "")     break ;;
555                 *)      jail_handle_ips_option ${_action} "${_x}"
556                         alias=$((${alias} + 1))
557                         ;;
558                 esac
559         done
560         case ${ipv6_address_count} in
561         0)      ;;
562         *)      # Sleep 1 second to let DAD complete before starting services.
563                 sleep 1
564                 ;;
565         esac
566 }
567
568 jail_start()
569 {
570         echo -n 'Configuring jails:'
571         set_sysctl jail_set_hostname_allow security.jail.set_hostname_allowed \
572             set_hostname_allow
573         set_sysctl jail_socket_unixiproute_only \
574             security.jail.socket_unixiproute_only unixiproute_only
575         set_sysctl jail_sysvipc_allow security.jail.sysvipc_allowed \
576             sysvipc_allow
577         echo '.'
578
579         echo -n 'Starting jails:'
580         _tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \
581             err 3 "$name: Can't create temp dir, exiting..."
582         for _jail in ${jail_list}
583         do
584                 init_variables $_jail
585                 if [ -f /var/run/jail_${_jail}.id ]; then
586                         echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]"
587                         continue;
588                 fi
589                 _addrl=""
590                 _addr6l=""
591                 jail_ips "add"
592                 if [ -n "${_fib}" ]; then
593                         _setfib="setfib -F '${_fib}'"
594                 else
595                         _setfib=""
596                 fi
597                 if checkyesno _mount; then
598                         info "Mounting fstab for jail ${_jail} (${_fstab})"
599                         if [ ! -f "${_fstab}" ]; then
600                                 err 3 "$name: ${_fstab} does not exist"
601                         fi
602                         jail_mount_fstab
603                 fi
604                 if checkyesno _devfs; then
605                         # If devfs is already mounted here, skip it.
606                         df -t devfs "${_devdir}" >/dev/null
607                         if [ $? -ne 0 ]; then
608                                 if is_symlinked_mountpoint ${_devdir}; then
609                                         warn "${_devdir} has symlink as parent - not starting jail ${_jail}"
610                                         continue
611                                 fi
612                                 info "Mounting devfs on ${_devdir}"
613                                 devfs_mount_jail "${_devdir}" ${_ruleset}
614                                 # Transitional symlink for old binaries
615                                 if [ ! -L "${_devdir}/log" ]; then
616                                         ln -sf ../var/run/log "${_devdir}/log"
617                                 fi
618                         fi
619
620                         # XXX - It seems symlinks don't work when there
621                         #       is a devfs(5) device of the same name.
622                         # Jail console output
623                         #       __pwd="`pwd`"
624                         #       cd "${_devdir}"
625                         #       ln -sf ../var/log/console console
626                         #       cd "$__pwd"
627                 fi
628                 if checkyesno _fdescfs; then
629                         if is_symlinked_mountpoint ${_fdescdir}; then
630                                 warn "${_fdescdir} has symlink as parent, not mounting"
631                         else
632                                 info "Mounting fdescfs on ${_fdescdir}"
633                                 mount -t fdescfs fdesc "${_fdescdir}"
634                         fi
635                 fi
636                 if checkyesno _procfs; then
637                         if is_symlinked_mountpoint ${_procdir}; then
638                                 warn "${_procdir} has symlink as parent, not mounting"
639                         else
640                                 info "Mounting procfs onto ${_procdir}"
641                                 if [ -d "${_procdir}" ] ; then
642                                         mount -t procfs proc "${_procdir}"
643                                 fi
644                         fi
645                 fi
646                 _tmp_jail=${_tmp_dir}/jail.$$
647
648                 i=0
649                 while : ; do
650                         eval out=\"\${_exec_prestart${i}:-''}\"
651                         [ -z "$out" ] && break
652                         ${out}
653                         i=$((i + 1))
654                 done
655
656                 eval ${_setfib} jail -n ${_jail} ${_flags} -i -c path=${_rootdir} host.hostname=${_hostname} \
657                         ${_addrl:+ip4.addr=\"${_addrl}\"} ${_addr6l:+ip6.addr=\"${_addr6l}\"} \
658                         ${_parameters} command=${_exec_start} > ${_tmp_jail} 2>&1 \
659                         </dev/null
660
661                 if [ "$?" -eq 0 ] ; then
662                         _jail_id=$(head -1 ${_tmp_jail})
663                         i=1
664                         while : ; do
665                                 eval out=\"\${_exec_afterstart${i}:-''}\"
666
667                                 if [ -z "$out" ]; then
668                                         break;
669                                 fi
670
671                                 jexec "${_jail_id}" ${out}
672                                 i=$((i + 1))
673                         done
674
675                         echo -n " $_hostname"
676                         tail +2 ${_tmp_jail} >${_consolelog}
677                         echo ${_jail_id} > /var/run/jail_${_jail}.id
678
679                         i=0
680                         while : ; do
681                                 eval out=\"\${_exec_poststart${i}:-''}\"
682                                 [ -z "$out" ] && break
683                                 ${out}
684                                 i=$((i + 1))
685                         done
686                 else
687                         jail_umount_fs
688                         jail_ips "del"
689                         echo " cannot start jail \"${_jail}\": "
690                         tail +2 ${_tmp_jail}
691                 fi
692                 rm -f ${_tmp_jail}
693         done
694         rmdir ${_tmp_dir}
695         echo '.'
696 }
697
698 jail_stop()
699 {
700         echo -n 'Stopping jails:'
701         for _jail in ${jail_list}
702         do
703                 if [ -f "/var/run/jail_${_jail}.id" ]; then
704                         _jail_id=$(cat /var/run/jail_${_jail}.id)
705                         if [ ! -z "${_jail_id}" ]; then
706                                 init_variables $_jail
707
708                                 i=0
709                                 while : ; do
710                                         eval out=\"\${_exec_prestop${i}:-''}\"
711                                         [ -z "$out" ] && break
712                                         ${out}
713                                         i=$((i + 1))
714                                 done
715
716                                 if [ -n "${_exec_stop}" ]; then
717                                         eval env -i /usr/sbin/jexec ${_jail_id} ${_exec_stop} \
718                                                 >> ${_consolelog} 2>&1
719                                 fi
720                                 killall -j ${_jail_id} -TERM > /dev/null 2>&1
721                                 sleep 1
722                                 killall -j ${_jail_id} -KILL > /dev/null 2>&1
723                                 jail_umount_fs
724                                 echo -n " $_hostname"
725
726                                 i=0
727                                 while : ; do
728                                         eval out=\"\${_exec_poststop${i}:-''}\"
729                                         [ -z "$out" ] && break
730                                         ${out}
731                                         i=$((i + 1))
732                                 done
733                         fi
734                         jail_ips "del"
735                         rm /var/run/jail_${_jail}.id
736                 else
737                         echo " cannot stop jail ${_jail}. No jail id in /var/run"
738                 fi
739         done
740         echo '.'
741 }
742
743 load_rc_config $name
744 cmd="$1"
745 if [ $# -gt 0 ]; then
746         shift
747 fi
748 if [ -n "$*" ]; then
749         jail_list="$*"
750 fi
751 run_rc_command "${cmd}"