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