Deleted Added
full compact
jail (272865) jail (278484)
1#!/bin/sh
2#
1#!/bin/sh
2#
3# $FreeBSD: stable/10/etc/rc.d/jail 272865 2014-10-09 23:41:11Z hrs $
3# $FreeBSD: stable/10/etc/rc.d/jail 278484 2015-02-10 01:05:51Z jamie $
4#
5
6# PROVIDE: jail
7# REQUIRE: LOGIN FILESYSTEMS
8# BEFORE: securelevel
9# KEYWORD: nojail shutdown
10
11. /etc/rc.subr
12
13name="jail"
14rcvar="jail_enable"
15
16start_cmd="jail_start"
17start_postcmd="jail_warn"
18stop_cmd="jail_stop"
19config_cmd="jail_config"
20console_cmd="jail_console"
21status_cmd="jail_status"
22extra_commands="config console status"
23: ${jail_conf:=/etc/jail.conf}
24: ${jail_program:=/usr/sbin/jail}
25: ${jail_consolecmd:=/usr/bin/login -f root}
26: ${jail_jexec:=/usr/sbin/jexec}
27: ${jail_jls:=/usr/sbin/jls}
28
29need_dad_wait=
30
4#
5
6# PROVIDE: jail
7# REQUIRE: LOGIN FILESYSTEMS
8# BEFORE: securelevel
9# KEYWORD: nojail shutdown
10
11. /etc/rc.subr
12
13name="jail"
14rcvar="jail_enable"
15
16start_cmd="jail_start"
17start_postcmd="jail_warn"
18stop_cmd="jail_stop"
19config_cmd="jail_config"
20console_cmd="jail_console"
21status_cmd="jail_status"
22extra_commands="config console status"
23: ${jail_conf:=/etc/jail.conf}
24: ${jail_program:=/usr/sbin/jail}
25: ${jail_consolecmd:=/usr/bin/login -f root}
26: ${jail_jexec:=/usr/sbin/jexec}
27: ${jail_jls:=/usr/sbin/jls}
28
29need_dad_wait=
30
31# extact_var jail name param num defval
31# extract_var jail name param num defval
32# Extract value from ${jail_$jail_$name} or ${jail_$name} and
33# set it to $param. If not defined, $defval is used.
34# When $num is [0-9]*, ${jail_$jail_$name$num} are looked up and
35# $param is set by using +=.
36# When $num is YN or NY, the value is interpret as boolean.
37extract_var()
38{
39 local i _j _name _param _num _def _name1 _name2
40 _j=$1
41 _name=$2
42 _param=$3
43 _num=$4
44 _def=$5
45
46 case $_num in
47 YN)
48 _name1=jail_${_j}_${_name}
49 _name2=jail_${_name}
50 eval $_name1=\"\${$_name1:-\${$_name2:-$_def}}\"
51 if checkyesno $_name1; then
52 echo " $_param = 1;"
53 else
54 echo " $_param = 0;"
55 fi
56 ;;
57 NY)
58 _name1=jail_${_j}_${_name}
59 _name2=jail_${_name}
60 eval $_name1=\"\${$_name1:-\${$_name2:-$_def}}\"
61 if checkyesno $_name1; then
62 echo " $_param = 0;"
63 else
64 echo " $_param = 1;"
65 fi
66 ;;
67 [0-9]*)
68 i=$_num
69 while : ; do
70 _name1=jail_${_j}_${_name}${i}
71 _name2=jail_${_name}${i}
72 eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
73 if [ -n "$_tmpargs" ]; then
74 echo " $_param += \"$_tmpargs\";"
75 else
76 break;
77 fi
78 i=$(($i + 1))
79 done
80 ;;
81 *)
82 _name1=jail_${_j}_${_name}
83 _name2=jail_${_name}
84 eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
85 if [ -n "$_tmpargs" ]; then
86 echo " $_param = \"$_tmpargs\";"
87 fi
88 ;;
89 esac
90}
91
92# parse_options _j
93# Parse options and create a temporary configuration file if necessary.
94#
95parse_options()
96{
97 local _j _p
98 _j=$1
99
100 _confwarn=0
101 if [ -z "$_j" ]; then
102 warn "parse_options: you must specify a jail"
103 return
104 fi
105 eval _jconf=\"\${jail_${_j}_conf:-/etc/jail.${_j}.conf}\"
106 eval _rootdir=\"\$jail_${_j}_rootdir\"
107 eval _hostname=\"\$jail_${_j}_hostname\"
108 if [ -z "$_rootdir" -o \
109 -z "$_hostname" ]; then
110 if [ -r "$_jconf" ]; then
111 _conf="$_jconf"
112 return 0
113 elif [ -r "$jail_conf" ]; then
114 _conf="$jail_conf"
115 return 0
116 else
117 warn "Invalid configuration for $_j " \
118 "(no jail.conf, no hostname, or no path). " \
119 "Jail $_j was ignored."
120 fi
121 return 1
122 fi
123 eval _ip=\"\$jail_${_j}_ip\"
124 if [ -z "$_ip" ] && ! check_kern_features vimage; then
125 warn "no ipaddress specified and no vimage support. " \
126 "Jail $_j was ignored."
127 return 1
128 fi
129 _conf=/var/run/jail.${_j}.conf
130 #
131 # To relieve confusion, show a warning message.
132 #
133 _confwarn=1
134 if [ -r "$jail_conf" -o -r "$_jconf" ]; then
135 if ! checkyesno jail_parallel_start; then
136 warn "$_conf is created and used for jail $_j."
137 fi
138 fi
139 /usr/bin/install -m 0644 -o root -g wheel /dev/null $_conf || return 1
140
141 eval : \${jail_${_j}_flags:=${jail_flags}}
142 eval _exec=\"\$jail_${_j}_exec\"
143 eval _exec_start=\"\$jail_${_j}_exec_start\"
144 eval _exec_stop=\"\$jail_${_j}_exec_stop\"
145 if [ -n "${_exec}" ]; then
146 # simple/backward-compatible execution
147 _exec_start="${_exec}"
148 _exec_stop=""
149 else
150 # flexible execution
151 if [ -z "${_exec_start}" ]; then
152 _exec_start="/bin/sh /etc/rc"
153 if [ -z "${_exec_stop}" ]; then
154 _exec_stop="/bin/sh /etc/rc.shutdown"
155 fi
156 fi
157 fi
158 eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
159 eval _parameters=\"\${jail_${_j}_parameters:-${jail_parameters}}\"
160 eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab:-/etc/fstab.$_j}}\"
161 (
162 date +"# Generated by rc.d/jail at %Y-%m-%d %H:%M:%S"
163 echo "$_j {"
164 extract_var $_j hostname host.hostname - ""
165 extract_var $_j rootdir path - ""
166 if [ -n "$_ip" ]; then
167 extract_var $_j interface interface - ""
168 jail_handle_ips_option $_ip $_interface
169 alias=0
170 while : ; do
171 eval _x=\"\$jail_${_j}_ip_multi${alias}\"
172 [ -z "$_x" ] && break
173
174 jail_handle_ips_option $_x $_interface
175 alias=$(($alias + 1))
176 done
177 case $need_dad_wait in
178 1)
179 # Sleep to let DAD complete before
180 # starting services.
181 echo " exec.start += \"sleep " \
182 $(($(${SYSCTL_N} net.inet6.ip6.dad_count) + 1)) \
183 "\";"
184 ;;
185 esac
186 # These are applicable only to non-vimage jails.
187 extract_var $_j fib exec.fib - ""
188 extract_var $_j socket_unixiproute_only \
189 allow.raw_sockets NY YES
190 else
191 echo " vnet;"
192 extract_var $_j vnet_interface vnet.interface - ""
193 fi
194
195 echo " exec.clean;"
196 echo " exec.system_user = \"root\";"
197 echo " exec.jail_user = \"root\";"
198 extract_var $_j exec_prestart exec.prestart 0 ""
199 extract_var $_j exec_poststart exec.poststart 0 ""
200 extract_var $_j exec_prestop exec.prestop 0 ""
201 extract_var $_j exec_poststop exec.poststop 0 ""
202
203 echo " exec.start += \"$_exec_start\";"
204 extract_var $_j exec_afterstart exec.start 1 ""
205 echo " exec.stop = \"$_exec_stop\";"
206
207 extract_var $_j consolelog exec.consolelog - \
208 /var/log/jail_${_j}_console.log
209
210 if [ -r $_fstab ]; then
211 echo " mount.fstab = \"$_fstab\";"
212 fi
213
214 eval : \${jail_${_j}_devfs_enable:=${jail_devfs_enable:-NO}}
215 if checkyesno jail_${_j}_devfs_enable; then
216 echo " mount.devfs;"
217 eval _ruleset=\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}
218 case $_ruleset in
219 "") ;;
220 [0-9]*) echo " devfs_ruleset = \"$_ruleset\";" ;;
221 devfsrules_jail)
222 # XXX: This is the default value,
223 # Let jail(8) to use the default because
224 # mount(8) only accepts an integer.
225 # This should accept a ruleset name.
226 ;;
227 *) warn "devfs_ruleset must be an integer." ;;
228 esac
229 fi
230 eval : \${jail_${_j}_fdescfs_enable:=${jail_fdescfs_enable:-NO}}
231 if checkyesno jail_${_j}_fdescfs_enable; then
232 echo " mount.fdescfs;"
233 fi
234 eval : \${jail_${_j}_procfs_enable:=${jail_procfs_enable:-NO}}
235 if checkyesno jail_${_j}_procfs_enable; then
32# Extract value from ${jail_$jail_$name} or ${jail_$name} and
33# set it to $param. If not defined, $defval is used.
34# When $num is [0-9]*, ${jail_$jail_$name$num} are looked up and
35# $param is set by using +=.
36# When $num is YN or NY, the value is interpret as boolean.
37extract_var()
38{
39 local i _j _name _param _num _def _name1 _name2
40 _j=$1
41 _name=$2
42 _param=$3
43 _num=$4
44 _def=$5
45
46 case $_num in
47 YN)
48 _name1=jail_${_j}_${_name}
49 _name2=jail_${_name}
50 eval $_name1=\"\${$_name1:-\${$_name2:-$_def}}\"
51 if checkyesno $_name1; then
52 echo " $_param = 1;"
53 else
54 echo " $_param = 0;"
55 fi
56 ;;
57 NY)
58 _name1=jail_${_j}_${_name}
59 _name2=jail_${_name}
60 eval $_name1=\"\${$_name1:-\${$_name2:-$_def}}\"
61 if checkyesno $_name1; then
62 echo " $_param = 0;"
63 else
64 echo " $_param = 1;"
65 fi
66 ;;
67 [0-9]*)
68 i=$_num
69 while : ; do
70 _name1=jail_${_j}_${_name}${i}
71 _name2=jail_${_name}${i}
72 eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
73 if [ -n "$_tmpargs" ]; then
74 echo " $_param += \"$_tmpargs\";"
75 else
76 break;
77 fi
78 i=$(($i + 1))
79 done
80 ;;
81 *)
82 _name1=jail_${_j}_${_name}
83 _name2=jail_${_name}
84 eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
85 if [ -n "$_tmpargs" ]; then
86 echo " $_param = \"$_tmpargs\";"
87 fi
88 ;;
89 esac
90}
91
92# parse_options _j
93# Parse options and create a temporary configuration file if necessary.
94#
95parse_options()
96{
97 local _j _p
98 _j=$1
99
100 _confwarn=0
101 if [ -z "$_j" ]; then
102 warn "parse_options: you must specify a jail"
103 return
104 fi
105 eval _jconf=\"\${jail_${_j}_conf:-/etc/jail.${_j}.conf}\"
106 eval _rootdir=\"\$jail_${_j}_rootdir\"
107 eval _hostname=\"\$jail_${_j}_hostname\"
108 if [ -z "$_rootdir" -o \
109 -z "$_hostname" ]; then
110 if [ -r "$_jconf" ]; then
111 _conf="$_jconf"
112 return 0
113 elif [ -r "$jail_conf" ]; then
114 _conf="$jail_conf"
115 return 0
116 else
117 warn "Invalid configuration for $_j " \
118 "(no jail.conf, no hostname, or no path). " \
119 "Jail $_j was ignored."
120 fi
121 return 1
122 fi
123 eval _ip=\"\$jail_${_j}_ip\"
124 if [ -z "$_ip" ] && ! check_kern_features vimage; then
125 warn "no ipaddress specified and no vimage support. " \
126 "Jail $_j was ignored."
127 return 1
128 fi
129 _conf=/var/run/jail.${_j}.conf
130 #
131 # To relieve confusion, show a warning message.
132 #
133 _confwarn=1
134 if [ -r "$jail_conf" -o -r "$_jconf" ]; then
135 if ! checkyesno jail_parallel_start; then
136 warn "$_conf is created and used for jail $_j."
137 fi
138 fi
139 /usr/bin/install -m 0644 -o root -g wheel /dev/null $_conf || return 1
140
141 eval : \${jail_${_j}_flags:=${jail_flags}}
142 eval _exec=\"\$jail_${_j}_exec\"
143 eval _exec_start=\"\$jail_${_j}_exec_start\"
144 eval _exec_stop=\"\$jail_${_j}_exec_stop\"
145 if [ -n "${_exec}" ]; then
146 # simple/backward-compatible execution
147 _exec_start="${_exec}"
148 _exec_stop=""
149 else
150 # flexible execution
151 if [ -z "${_exec_start}" ]; then
152 _exec_start="/bin/sh /etc/rc"
153 if [ -z "${_exec_stop}" ]; then
154 _exec_stop="/bin/sh /etc/rc.shutdown"
155 fi
156 fi
157 fi
158 eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
159 eval _parameters=\"\${jail_${_j}_parameters:-${jail_parameters}}\"
160 eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab:-/etc/fstab.$_j}}\"
161 (
162 date +"# Generated by rc.d/jail at %Y-%m-%d %H:%M:%S"
163 echo "$_j {"
164 extract_var $_j hostname host.hostname - ""
165 extract_var $_j rootdir path - ""
166 if [ -n "$_ip" ]; then
167 extract_var $_j interface interface - ""
168 jail_handle_ips_option $_ip $_interface
169 alias=0
170 while : ; do
171 eval _x=\"\$jail_${_j}_ip_multi${alias}\"
172 [ -z "$_x" ] && break
173
174 jail_handle_ips_option $_x $_interface
175 alias=$(($alias + 1))
176 done
177 case $need_dad_wait in
178 1)
179 # Sleep to let DAD complete before
180 # starting services.
181 echo " exec.start += \"sleep " \
182 $(($(${SYSCTL_N} net.inet6.ip6.dad_count) + 1)) \
183 "\";"
184 ;;
185 esac
186 # These are applicable only to non-vimage jails.
187 extract_var $_j fib exec.fib - ""
188 extract_var $_j socket_unixiproute_only \
189 allow.raw_sockets NY YES
190 else
191 echo " vnet;"
192 extract_var $_j vnet_interface vnet.interface - ""
193 fi
194
195 echo " exec.clean;"
196 echo " exec.system_user = \"root\";"
197 echo " exec.jail_user = \"root\";"
198 extract_var $_j exec_prestart exec.prestart 0 ""
199 extract_var $_j exec_poststart exec.poststart 0 ""
200 extract_var $_j exec_prestop exec.prestop 0 ""
201 extract_var $_j exec_poststop exec.poststop 0 ""
202
203 echo " exec.start += \"$_exec_start\";"
204 extract_var $_j exec_afterstart exec.start 1 ""
205 echo " exec.stop = \"$_exec_stop\";"
206
207 extract_var $_j consolelog exec.consolelog - \
208 /var/log/jail_${_j}_console.log
209
210 if [ -r $_fstab ]; then
211 echo " mount.fstab = \"$_fstab\";"
212 fi
213
214 eval : \${jail_${_j}_devfs_enable:=${jail_devfs_enable:-NO}}
215 if checkyesno jail_${_j}_devfs_enable; then
216 echo " mount.devfs;"
217 eval _ruleset=\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}
218 case $_ruleset in
219 "") ;;
220 [0-9]*) echo " devfs_ruleset = \"$_ruleset\";" ;;
221 devfsrules_jail)
222 # XXX: This is the default value,
223 # Let jail(8) to use the default because
224 # mount(8) only accepts an integer.
225 # This should accept a ruleset name.
226 ;;
227 *) warn "devfs_ruleset must be an integer." ;;
228 esac
229 fi
230 eval : \${jail_${_j}_fdescfs_enable:=${jail_fdescfs_enable:-NO}}
231 if checkyesno jail_${_j}_fdescfs_enable; then
232 echo " mount.fdescfs;"
233 fi
234 eval : \${jail_${_j}_procfs_enable:=${jail_procfs_enable:-NO}}
235 if checkyesno jail_${_j}_procfs_enable; then
236 echo " mount += " \
237 "\"procfs ${_rootdir%/}/proc procfs rw 0 0\";"
236 echo " mount.procfs;"
238 fi
239
240 eval : \${jail_${_j}_mount_enable:=${jail_mount_enable:-NO}}
241 if checkyesno jail_${_j}_mount_enable; then
242 echo " allow.mount;" >> $_conf
243 fi
244
245 extract_var $_j set_hostname_allow allow.set_hostname YN NO
246 extract_var $_j sysvipc_allow allow.sysvipc YN NO
247 for _p in $_parameters; do
248 echo " ${_p%\;};"
249 done
250 echo "}"
251 ) >> $_conf
252
253 return 0
254}
255
256# jail_extract_address argument iface
257# The second argument is the string from one of the _ip
258# or the _multi variables. In case of a comma separated list
259# only one argument must be passed in at a time.
260# The function alters the _type, _iface, _addr and _mask variables.
261#
262jail_extract_address()
263{
264 local _i _interface
265 _i=$1
266 _interface=$2
267
268 if [ -z "${_i}" ]; then
269 warn "jail_extract_address: called without input"
270 return
271 fi
272
273 # Check if we have an interface prefix given and split into
274 # iFace and rest.
275 case "${_i}" in
276 *\|*) # ifN|.. prefix there
277 _iface=${_i%%|*}
278 _r=${_i##*|}
279 ;;
280 *) _iface=""
281 _r=${_i}
282 ;;
283 esac
284
285 # In case the IP has no interface given, check if we have a global one.
286 _iface=${_iface:-${_interface}}
287
288 # Set address, cut off any prefix/netmask/prefixlen.
289 _addr=${_r}
290 _addr=${_addr%%[/ ]*}
291
292 # Theoretically we can return here if interface is not set,
293 # as we only care about the _mask if we call ifconfig.
294 # This is not done because we may want to santize IP addresses
295 # based on _type later, and optionally change the type as well.
296
297 # Extract the prefix/netmask/prefixlen part by cutting off the address.
298 _mask=${_r}
299 _mask=`expr "${_mask}" : "${_addr}\(.*\)"`
300
301 # Identify type {inet,inet6}.
302 case "${_addr}" in
303 *\.*\.*\.*) _type="inet" ;;
304 *:*) _type="inet6" ;;
305 *) warn "jail_extract_address: type not identified"
306 ;;
307 esac
308
309 # Handle the special /netmask instead of /prefix or
310 # "netmask xxx" case for legacy IP.
311 # We do NOT support shortend class-full netmasks.
312 if [ "${_type}" = "inet" ]; then
313 case "${_mask}" in
314 /*\.*\.*\.*) _mask=" netmask ${_mask#/}" ;;
315 *) ;;
316 esac
317
318 # In case _mask is still not set use /32.
319 _mask=${_mask:-/32}
320
321 elif [ "${_type}" = "inet6" ]; then
322 # In case _mask is not set for IPv6, use /128.
323 _mask=${_mask:-/128}
324 fi
325}
326
327# jail_handle_ips_option input iface
328# Handle a single argument imput which can be a comma separated
329# list of addresses (theoretically with an option interface and
330# prefix/netmask/prefixlen).
331#
332jail_handle_ips_option()
333{
334 local _x _type _i _defif
335 _x=$1
336 _defif=$2
337
338 if [ -z "${_x}" ]; then
339 # No IP given. This can happen for the primary address
340 # of each address family.
341 return
342 fi
343
344 # Loop, in case we find a comma separated list, we need to handle
345 # each argument on its own.
346 while [ ${#_x} -gt 0 ]; do
347 case "${_x}" in
348 *,*) # Extract the first argument and strip it off the list.
349 _i=`expr "${_x}" : '^\([^,]*\)'`
350 _x=`expr "${_x}" : "^[^,]*,\(.*\)"`
351 ;;
352 *) _i=${_x}
353 _x=""
354 ;;
355 esac
356
357 _type=""
358 _addr=""
359 _mask=""
360 _iface=""
361 jail_extract_address $_i $_defif
362
363 # make sure we got an address.
364 case $_addr in
365 "") continue ;;
366 *) ;;
367 esac
368
369 # Append address to list of addresses for the jail command.
370 case $_type in
371 inet)
372 echo " ip4.addr += \"${_iface:+${_iface}|}${_addr}${_mask}\";"
373 ;;
374 inet6)
375 echo " ip6.addr += \"${_iface:+${_iface}|}${_addr}${_mask}\";"
376 need_dad_wait=1
377 ;;
378 esac
379 done
380}
381
382jail_config()
383{
384 local _j
385
386 case $1 in
387 _ALL) return ;;
388 esac
389 for _j in $@; do
390 _j=$(echo $_j | tr /. _)
391 if parse_options $_j; then
392 echo "$_j: parameters are in $_conf."
393 fi
394 done
395}
396
397jail_console()
398{
399 local _j _cmd
400
401 # One argument that is not _ALL.
402 case $#:$1 in
403 0:*|1:_ALL) err 3 "Specify a jail name." ;;
404 1:*) ;;
405 esac
406 _j=$(echo $1 | tr /. _)
407 shift
408 case $# in
409 0) eval _cmd=\${jail_${_j}_consolecmd:-$jail_consolecmd} ;;
410 *) _cmd=$@ ;;
411 esac
412 $jail_jexec $_j $_cmd
413}
414
415jail_status()
416{
417
418 $jail_jls -N
419}
420
421jail_start()
422{
423 local _j _jid _jl
424
425 if [ $# = 0 ]; then
426 return
427 fi
428 echo -n 'Starting jails:'
429 case $1 in
430 _ALL)
431 command=$jail_program
432 rc_flags=$jail_flags
433 command_args="-f $jail_conf -c"
434 _tmp=`mktemp -t jail` || exit 3
435 if $command $rc_flags $command_args >> $_tmp 2>&1; then
436 $jail_jls jid name | while read IN; do
437 set -- $IN
438 echo -n " $2"
439 echo $1 > /var/run/jail_$2.id
440 done
441 else
442 tail -1 $_tmp
443 fi
444 rm -f $_tmp
445 echo '.'
446 return
447 ;;
448 esac
449 if checkyesno jail_parallel_start; then
450 #
451 # Start jails in parallel and then check jail id when
452 # jail_parallel_start is YES.
453 #
454 _jl=
455 for _j in $@; do
456 _j=$(echo $_j | tr /. _)
457 parse_options $_j || continue
458
459 _jl="$_jl $_j"
460 eval rc_flags=\${jail_${_j}_flags:-$jail_flags}
461 eval command=\${jail_${_j}_program:-$jail_program}
462 command_args="-i -f $_conf -c $_j"
463 $command $rc_flags $command_args \
464 >/dev/null 2>&1 </dev/null &
465 done
466 sleep 1
467 for _j in $_jl; do
468 echo -n " ${_hostname:-${_j}}"
469 if _jid=$($jail_jls -j $_j jid); then
470 echo "$_jid" > /var/run/jail_${_j}.id
471 else
472 rm -f /var/run/jail_${_j}.id
473 echo " cannot start jail " \
474 "\"${_hostname:-${_j}}\": "
475 fi
476 done
477 else
478 #
479 # Start jails one-by-one when jail_parallel_start is NO.
480 #
481 for _j in $@; do
482 _j=$(echo $_j | tr /. _)
483 parse_options $_j || continue
484
485 eval rc_flags=\${jail_${_j}_flags:-$jail_flags}
486 eval command=\${jail_${_j}_program:-$jail_program}
487 command_args="-i -f $_conf -c $_j"
488 _tmp=`mktemp -t jail` || exit 3
489 if $command $rc_flags $command_args \
490 >> $_tmp 2>&1 </dev/null; then
491 echo -n " ${_hostname:-${_j}}"
492 _jid=$($jail_jls -j $_j jid)
493 echo $_jid > /var/run/jail_${_j}.id
494 else
495 rm -f /var/run/jail_${_j}.id
496 echo " cannot start jail " \
497 "\"${_hostname:-${_j}}\": "
498 cat $_tmp
499 fi
500 rm -f $_tmp
501 done
502 fi
503 echo '.'
504}
505
506jail_stop()
507{
508 local _j
509
510 if [ $# = 0 ]; then
511 return
512 fi
513 echo -n 'Stopping jails:'
514 case $1 in
515 _ALL)
516 command=$jail_program
517 rc_flags=$jail_flags
518 command_args="-f $jail_conf -r"
519 $jail_jls name | while read _j; do
520 echo -n " $_j"
521 _tmp=`mktemp -t jail` || exit 3
522 $command $rc_flags $command_args $_j >> $_tmp 2>&1
523 if $jail_jls -j $_j > /dev/null 2>&1; then
524 tail -1 $_tmp
525 else
526 rm -f /var/run/jail_${_j}.id
527 fi
528 rm -f $_tmp
529 done
530 echo '.'
531 return
532 ;;
533 esac
534 for _j in $@; do
535 _j=$(echo $_j | tr /. _)
536 parse_options $_j || continue
537 if ! $jail_jls -j $_j > /dev/null 2>&1; then
538 continue
539 fi
540 eval command=\${jail_${_j}_program:-$jail_program}
541 echo -n " ${_hostname:-${_j}}"
542 _tmp=`mktemp -t jail` || exit 3
543 $command -q -f $_conf -r $_j >> $_tmp 2>&1
544 if $jail_jls -j $_j > /dev/null 2>&1; then
545 tail -1 $_tmp
546 else
547 rm -f /var/run/jail_${_j}.id
548 fi
549 rm -f $_tmp
550 done
551 echo '.'
552}
553
554jail_warn()
555{
556
557 # To relieve confusion, show a warning message.
558 case $_confwarn in
559 1) warn "Per-jail configuration via jail_* variables " \
560 "is obsolete. Please consider to migrate to $jail_conf."
561 ;;
562 esac
563}
564
565load_rc_config $name
566case $# in
5671) run_rc_command $@ ${jail_list:-_ALL} ;;
568*) run_rc_command $@ ;;
569esac
237 fi
238
239 eval : \${jail_${_j}_mount_enable:=${jail_mount_enable:-NO}}
240 if checkyesno jail_${_j}_mount_enable; then
241 echo " allow.mount;" >> $_conf
242 fi
243
244 extract_var $_j set_hostname_allow allow.set_hostname YN NO
245 extract_var $_j sysvipc_allow allow.sysvipc YN NO
246 for _p in $_parameters; do
247 echo " ${_p%\;};"
248 done
249 echo "}"
250 ) >> $_conf
251
252 return 0
253}
254
255# jail_extract_address argument iface
256# The second argument is the string from one of the _ip
257# or the _multi variables. In case of a comma separated list
258# only one argument must be passed in at a time.
259# The function alters the _type, _iface, _addr and _mask variables.
260#
261jail_extract_address()
262{
263 local _i _interface
264 _i=$1
265 _interface=$2
266
267 if [ -z "${_i}" ]; then
268 warn "jail_extract_address: called without input"
269 return
270 fi
271
272 # Check if we have an interface prefix given and split into
273 # iFace and rest.
274 case "${_i}" in
275 *\|*) # ifN|.. prefix there
276 _iface=${_i%%|*}
277 _r=${_i##*|}
278 ;;
279 *) _iface=""
280 _r=${_i}
281 ;;
282 esac
283
284 # In case the IP has no interface given, check if we have a global one.
285 _iface=${_iface:-${_interface}}
286
287 # Set address, cut off any prefix/netmask/prefixlen.
288 _addr=${_r}
289 _addr=${_addr%%[/ ]*}
290
291 # Theoretically we can return here if interface is not set,
292 # as we only care about the _mask if we call ifconfig.
293 # This is not done because we may want to santize IP addresses
294 # based on _type later, and optionally change the type as well.
295
296 # Extract the prefix/netmask/prefixlen part by cutting off the address.
297 _mask=${_r}
298 _mask=`expr "${_mask}" : "${_addr}\(.*\)"`
299
300 # Identify type {inet,inet6}.
301 case "${_addr}" in
302 *\.*\.*\.*) _type="inet" ;;
303 *:*) _type="inet6" ;;
304 *) warn "jail_extract_address: type not identified"
305 ;;
306 esac
307
308 # Handle the special /netmask instead of /prefix or
309 # "netmask xxx" case for legacy IP.
310 # We do NOT support shortend class-full netmasks.
311 if [ "${_type}" = "inet" ]; then
312 case "${_mask}" in
313 /*\.*\.*\.*) _mask=" netmask ${_mask#/}" ;;
314 *) ;;
315 esac
316
317 # In case _mask is still not set use /32.
318 _mask=${_mask:-/32}
319
320 elif [ "${_type}" = "inet6" ]; then
321 # In case _mask is not set for IPv6, use /128.
322 _mask=${_mask:-/128}
323 fi
324}
325
326# jail_handle_ips_option input iface
327# Handle a single argument imput which can be a comma separated
328# list of addresses (theoretically with an option interface and
329# prefix/netmask/prefixlen).
330#
331jail_handle_ips_option()
332{
333 local _x _type _i _defif
334 _x=$1
335 _defif=$2
336
337 if [ -z "${_x}" ]; then
338 # No IP given. This can happen for the primary address
339 # of each address family.
340 return
341 fi
342
343 # Loop, in case we find a comma separated list, we need to handle
344 # each argument on its own.
345 while [ ${#_x} -gt 0 ]; do
346 case "${_x}" in
347 *,*) # Extract the first argument and strip it off the list.
348 _i=`expr "${_x}" : '^\([^,]*\)'`
349 _x=`expr "${_x}" : "^[^,]*,\(.*\)"`
350 ;;
351 *) _i=${_x}
352 _x=""
353 ;;
354 esac
355
356 _type=""
357 _addr=""
358 _mask=""
359 _iface=""
360 jail_extract_address $_i $_defif
361
362 # make sure we got an address.
363 case $_addr in
364 "") continue ;;
365 *) ;;
366 esac
367
368 # Append address to list of addresses for the jail command.
369 case $_type in
370 inet)
371 echo " ip4.addr += \"${_iface:+${_iface}|}${_addr}${_mask}\";"
372 ;;
373 inet6)
374 echo " ip6.addr += \"${_iface:+${_iface}|}${_addr}${_mask}\";"
375 need_dad_wait=1
376 ;;
377 esac
378 done
379}
380
381jail_config()
382{
383 local _j
384
385 case $1 in
386 _ALL) return ;;
387 esac
388 for _j in $@; do
389 _j=$(echo $_j | tr /. _)
390 if parse_options $_j; then
391 echo "$_j: parameters are in $_conf."
392 fi
393 done
394}
395
396jail_console()
397{
398 local _j _cmd
399
400 # One argument that is not _ALL.
401 case $#:$1 in
402 0:*|1:_ALL) err 3 "Specify a jail name." ;;
403 1:*) ;;
404 esac
405 _j=$(echo $1 | tr /. _)
406 shift
407 case $# in
408 0) eval _cmd=\${jail_${_j}_consolecmd:-$jail_consolecmd} ;;
409 *) _cmd=$@ ;;
410 esac
411 $jail_jexec $_j $_cmd
412}
413
414jail_status()
415{
416
417 $jail_jls -N
418}
419
420jail_start()
421{
422 local _j _jid _jl
423
424 if [ $# = 0 ]; then
425 return
426 fi
427 echo -n 'Starting jails:'
428 case $1 in
429 _ALL)
430 command=$jail_program
431 rc_flags=$jail_flags
432 command_args="-f $jail_conf -c"
433 _tmp=`mktemp -t jail` || exit 3
434 if $command $rc_flags $command_args >> $_tmp 2>&1; then
435 $jail_jls jid name | while read IN; do
436 set -- $IN
437 echo -n " $2"
438 echo $1 > /var/run/jail_$2.id
439 done
440 else
441 tail -1 $_tmp
442 fi
443 rm -f $_tmp
444 echo '.'
445 return
446 ;;
447 esac
448 if checkyesno jail_parallel_start; then
449 #
450 # Start jails in parallel and then check jail id when
451 # jail_parallel_start is YES.
452 #
453 _jl=
454 for _j in $@; do
455 _j=$(echo $_j | tr /. _)
456 parse_options $_j || continue
457
458 _jl="$_jl $_j"
459 eval rc_flags=\${jail_${_j}_flags:-$jail_flags}
460 eval command=\${jail_${_j}_program:-$jail_program}
461 command_args="-i -f $_conf -c $_j"
462 $command $rc_flags $command_args \
463 >/dev/null 2>&1 </dev/null &
464 done
465 sleep 1
466 for _j in $_jl; do
467 echo -n " ${_hostname:-${_j}}"
468 if _jid=$($jail_jls -j $_j jid); then
469 echo "$_jid" > /var/run/jail_${_j}.id
470 else
471 rm -f /var/run/jail_${_j}.id
472 echo " cannot start jail " \
473 "\"${_hostname:-${_j}}\": "
474 fi
475 done
476 else
477 #
478 # Start jails one-by-one when jail_parallel_start is NO.
479 #
480 for _j in $@; do
481 _j=$(echo $_j | tr /. _)
482 parse_options $_j || continue
483
484 eval rc_flags=\${jail_${_j}_flags:-$jail_flags}
485 eval command=\${jail_${_j}_program:-$jail_program}
486 command_args="-i -f $_conf -c $_j"
487 _tmp=`mktemp -t jail` || exit 3
488 if $command $rc_flags $command_args \
489 >> $_tmp 2>&1 </dev/null; then
490 echo -n " ${_hostname:-${_j}}"
491 _jid=$($jail_jls -j $_j jid)
492 echo $_jid > /var/run/jail_${_j}.id
493 else
494 rm -f /var/run/jail_${_j}.id
495 echo " cannot start jail " \
496 "\"${_hostname:-${_j}}\": "
497 cat $_tmp
498 fi
499 rm -f $_tmp
500 done
501 fi
502 echo '.'
503}
504
505jail_stop()
506{
507 local _j
508
509 if [ $# = 0 ]; then
510 return
511 fi
512 echo -n 'Stopping jails:'
513 case $1 in
514 _ALL)
515 command=$jail_program
516 rc_flags=$jail_flags
517 command_args="-f $jail_conf -r"
518 $jail_jls name | while read _j; do
519 echo -n " $_j"
520 _tmp=`mktemp -t jail` || exit 3
521 $command $rc_flags $command_args $_j >> $_tmp 2>&1
522 if $jail_jls -j $_j > /dev/null 2>&1; then
523 tail -1 $_tmp
524 else
525 rm -f /var/run/jail_${_j}.id
526 fi
527 rm -f $_tmp
528 done
529 echo '.'
530 return
531 ;;
532 esac
533 for _j in $@; do
534 _j=$(echo $_j | tr /. _)
535 parse_options $_j || continue
536 if ! $jail_jls -j $_j > /dev/null 2>&1; then
537 continue
538 fi
539 eval command=\${jail_${_j}_program:-$jail_program}
540 echo -n " ${_hostname:-${_j}}"
541 _tmp=`mktemp -t jail` || exit 3
542 $command -q -f $_conf -r $_j >> $_tmp 2>&1
543 if $jail_jls -j $_j > /dev/null 2>&1; then
544 tail -1 $_tmp
545 else
546 rm -f /var/run/jail_${_j}.id
547 fi
548 rm -f $_tmp
549 done
550 echo '.'
551}
552
553jail_warn()
554{
555
556 # To relieve confusion, show a warning message.
557 case $_confwarn in
558 1) warn "Per-jail configuration via jail_* variables " \
559 "is obsolete. Please consider to migrate to $jail_conf."
560 ;;
561 esac
562}
563
564load_rc_config $name
565case $# in
5661) run_rc_command $@ ${jail_list:-_ALL} ;;
567*) run_rc_command $@ ;;
568esac