]> git.ipfire.org Git - people/stevee/network.git/blame - src/functions/functions.zone
network fix parameter passing when using ""
[people/stevee/network.git] / src / functions / functions.zone
CommitLineData
1848564d
MT
1#!/bin/bash
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2010 Michael Tremer & Christian Schmidt #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
1c6a4e30 22zone_dir() {
1848564d
MT
23 local zone=${1}
24
d2a21d01 25 echo "${NETWORK_ZONE_DIR}/zones/${zone}"
1848564d
MT
26}
27
1c6a4e30 28zone_exists() {
1848564d 29 local zone=${1}
711ffac1
MT
30 assert isset zone
31
1848564d
MT
32 [ -d "$(zone_dir ${zone})" ]
33}
34
1c6a4e30 35zone_match() {
1848564d
MT
36 local match
37
38 local i
39 for i in ${VALID_ZONES}; do
40 match="${match}|${i}[0-9]{1,5}"
41 done
42
43 echo "${match:1:${#match}}"
44}
45
1c6a4e30 46zone_name_is_valid() {
1848564d 47 local zone=${1}
4fedddef
MT
48
49 # Don't accept empty strings.
50 [ -z "${zone}" ] && return ${EXIT_FALSE}
711ffac1 51
1848564d
MT
52 [[ ${zone} =~ $(zone_match) ]]
53}
54
1c6a4e30 55zone_is_local() {
1848564d
MT
56 local zone=${1}
57
7de0637a 58 [[ "${zone:0:${#ZONE_LOCAL}}" = "${ZONE_LOCAL}" ]]
5e42d659
MT
59}
60
1c6a4e30 61zone_is_nonlocal() {
5e42d659
MT
62 local zone=${1}
63
7de0637a 64 [[ "${zone:0:${#ZONE_NONLOCAL}}" = "${ZONE_NONLOCAL}" ]]
1848564d
MT
65}
66
1c6a4e30 67zone_get_hook() {
1848564d 68 local zone=${1}
711ffac1
MT
69 assert isset zone
70
1848564d
MT
71 config_get_hook $(zone_dir ${zone})/settings
72}
73
1c6a4e30 74zone_start() {
5bb2429a
MT
75 # This function will bring up the zone
76 # 'asynchronously' with help of systemd.
77
78 local zone=${1}
79 assert zone_exists ${zone}
80
1d08b9b3 81 service_start "network@${zone}.service"
5bb2429a
MT
82}
83
1c6a4e30 84zone_start_auto() {
2a969c27
MT
85 local zone="${1}"
86 assert zone_exists "${zone}"
87
88 # If the zone has already been started, we
89 # will reload it so the current configuration
90 # is re-applied.
91 if zone_is_active "${zone}"; then
92 zone_reload "${zone}"
93 return ${?}
94
95 # If the zone is still down, but in auto-start mode,
96 # we will start it.
97 elif zone_is_enabled "${zone}"; then
98 zone_start "${zone}"
99 return ${?}
100 fi
101
102 # Otherwise, nothing will be done.
103 return ${EXIT_OK}
104}
105
1c6a4e30 106zone_stop() {
5bb2429a
MT
107 # This function will bring down the zone
108 # 'asynchronously' with help of systemd.
109
110 local zone=${1}
111 assert zone_exists ${zone}
112
1d08b9b3 113 service_stop "network@${zone}.service"
5bb2429a
MT
114}
115
1c6a4e30 116zone_reload() {
e6fd23fd
MT
117 local zone="${1}"
118 assert zone_exists "${zone}"
119
120 service_reload "network@${zone}.service"
121}
122
1c6a4e30 123zone_hotplug_event() {
fb8c7c92 124 local zone="${1}"
2a969c27 125 assert isset zone
fb8c7c92 126
2a969c27 127 hotplug_assert_in_hotplug_event
fb8c7c92 128
2a969c27 129 zone_cmd "hotplug" "${zone}"
fb8c7c92
MT
130}
131
1c6a4e30 132zone_enable() {
5c5b8e36
SS
133 # This function will enable the zone
134 # with help of systemd.
135
136 local zone="${1}"
137 assert zone_exists "${zone}"
138
139 # Enable service for the zone
140 service_enable "network@${zone}.service"
141 local ret=$?
142
143 if [ ${ret} -eq ${EXIT_OK} ]; then
144 log INFO "Auto-start enabled for zone ${zone}"
145 return ${EXIT_OK}
146 fi
147
148 log ERROR "Could not enable zone ${zone}: ${ret}"
149 return ${ret}
150}
151
1c6a4e30 152zone_disable() {
5c5b8e36
SS
153 # This function will disable the zone
154 # with help of systemd.
155
156 local zone="${1}"
157 assert zone_exists "${zone}"
158
159 # Disable service for the zone
160 service_disable "network@${zone}.service"
161 local ret=$?
162
163 if [ ${ret} -eq ${EXIT_OK} ]; then
164 log INFO "Auto-start disabled for zone ${zone}"
165 return ${EXIT_OK}
166 fi
167
168 log ERROR "Could not disable zone ${zone}: ${ret}"
169 return ${ret}
170}
171
1c6a4e30 172zone_is_enabled() {
5c5b8e36
SS
173 local zone="${1}"
174 assert isset zone
175
176 # Ask systemd if the zone is enabled.
177 if service_is_enabled "network@${zone}.service"; then
178 return ${EXIT_TRUE}
179 fi
180
181 return ${EXIT_FALSE}
182}
183
1c6a4e30 184zone_is_active() {
e6fd23fd
MT
185 local zone="${1}"
186 assert isset zone
187
188 if service_is_active "network@${zone}.service"; then
189 return ${EXIT_TRUE}
190 fi
191
192 return ${EXIT_FALSE}
193}
194
1c6a4e30 195zone_is_enabled_or_active() {
2a969c27
MT
196 local zone="${1}"
197 assert isset zone
198
199 zone_is_enabled "${zone}" || zone_is_active "${zone}"
200}
201
1c6a4e30 202zone_cmd() {
2a969c27
MT
203 local cmd="${1}"
204 local port="${2}"
205 shift 2
206
207 assert isset cmd
208 assert isset zone
209
210 local hook="$(zone_get_hook ${zone})"
211 assert isset hook
212
2212045f 213 hook_exec zone "${hook}" "${cmd}" "${zone}" "$@"
2a969c27
MT
214}
215
1c6a4e30 216zone_new() {
1848564d
MT
217 local zone=${1}
218 local hook=${2}
219 shift 2
220
221 if ! zone_name_is_valid ${zone}; then
222 error "Zone name '${zone}' is not valid."
223 return ${EXIT_ERROR}
224 fi
225
226 if zone_exists ${zone}; then
227 error "Zone '${zone}' does already exist."
228 return ${EXIT_ERROR}
229 fi
230
d61a01d4 231 if ! hook_zone_exists ${hook}; then
1848564d
MT
232 error "Hook '${hook}' does not exist."
233 return ${EXIT_ERROR}
234 fi
235
236 mkdir -p $(zone_dir ${zone})
237
a5ebb169
MT
238 # Create directories for configs and ports
239 mkdir -p $(zone_dir ${zone})/{configs,ports}
943e3f7e 240
2212045f 241 hook_zone_exec "${hook}" "new" "${zone}" "$@"
1848564d
MT
242 local ret=$?
243
cf0fc8ab 244 # Maybe the zone new hook did not exit correctly.
1848564d 245 # If this is the case we remove the created zone immediately.
a63e51c6 246 if [ "${ret}" != "${EXIT_OK}" ]; then
285f779f 247 zone_destroy "${zone}"
5c5b8e36 248 return ${EXIT_ERROR}
1848564d 249 fi
5c5b8e36
SS
250
251 # Automatically enable zone.
252 zone_enable "${zone}"
ac694a6a
MT
253
254 # Bring up the zone immediately after
255 zone_start "${zone}"
1848564d
MT
256}
257
1c6a4e30 258zone_edit() {
1848564d
MT
259 local zone=${1}
260 shift
261
262 if ! zone_exists ${zone}; then
263 error "Zone '${zone}' does not exist."
264 return ${EXIT_ERROR}
265 fi
266
2472e0ea 267 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
268 if [ -z "${hook}" ]; then
269 error "Config file did not provide any hook."
270 return ${EXIT_ERROR}
271 fi
272
d61a01d4 273 if ! hook_zone_exists ${hook}; then
1848564d
MT
274 error "Hook '${hook}' does not exist."
275 return ${EXIT_ERROR}
276 fi
277
2212045f 278 hook_zone_exec ${hook} edit ${zone} "$@"
1848564d
MT
279}
280
2bb20bbd
SS
281zone_rename() {
282 assert [ $# -eq 2 ]
283
284 local zone="${1}"
285 local name="${2}"
286
287 assert zone_exists "${zone}"
2bb20bbd
SS
288 assert not zone_exists "${name}"
289
290 # The zone must be shut down before, is then renamed and
291 # potentially brought up again
292
293 # Save if the zone is running right now
294 zone_is_active "${zone}"
295 local zone_was_active="${?}"
296
297 # Save if the zone is enabled (i.e. auto-start)
298 zone_is_enabled "${zone}"
299 local zone_was_enabled="${?}"
300
301 # Stop the zone
302 zone_stop "${zone}"
303
304 # Disable the zone
305 zone_disable "${zone}"
306
307 # Rename the configuration files
308 mv -f "$(zone_dir "${zone}")" "$(zone_dir "${name}")"
309
310 # Enable the zone if it was enabled before
311 [ ${zone_was_enabled} -eq ${EXIT_TRUE} ] && zone_enable "${name}"
312
313 # Start the zone if it was up before
314 [ ${zone_was_active} -eq ${EXIT_TRUE} ] && zone_start "${name}"
315
316 log INFO "Zone ${zone} was renamed to ${name}"
317 return ${EXIT_OK}
318}
319
69ace22b 320
1c6a4e30 321zone_destroy() {
cf0fc8ab 322 local zone="${1}"
69ace22b 323
285f779f
MT
324 # Cannot delete a zone that does not exist
325 if ! zone_exists "${zone}"; then
326 log ERROR "Zone ${zone} does not exist"
327 return ${EXIT_ERROR}
328 fi
69ace22b 329
285f779f 330 log INFO "Destroying zone ${zone}"
1848564d 331
69ace22b 332 # Force the zone down.
d5c9bd17 333 zone_is_active "${zone}" && zone_stop "${zone}"
1848564d 334
285f779f 335 # Disable zone auto-start
5c5b8e36
SS
336 zone_disable "${zone}"
337
cf0fc8ab 338 rm -rf "$(zone_dir "${zone}")"
1848564d
MT
339}
340
1c6a4e30 341zone_up() {
1848564d
MT
342 local zone=${1}
343 shift
344
345 if ! zone_exists ${zone}; then
346 error "Zone '${zone}' does not exist."
347 return ${EXIT_ERROR}
348 fi
349
2472e0ea 350 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
351 if [ -z "${hook}" ]; then
352 error "Config file did not provide any hook."
353 return ${EXIT_ERROR}
354 fi
355
d61a01d4 356 if ! hook_zone_exists ${hook}; then
1848564d
MT
357 error "Hook '${hook}' does not exist."
358 return ${EXIT_ERROR}
359 fi
360
059469a8
MT
361 zone_db ${zone} starting
362
2212045f 363 hook_zone_exec ${hook} up ${zone} "$@"
d61a01d4 364
059469a8 365 zone_db ${zone} started
de3cecef
MT
366
367 # Execute all triggers after the zone got up
368 triggers_execute_all "up" ZONE="${zone}"
1848564d
MT
369}
370
1c6a4e30 371zone_down() {
1848564d
MT
372 local zone=${1}
373 shift
374
375 if ! zone_exists ${zone}; then
376 error "Zone '${zone}' does not exist."
377 return ${EXIT_ERROR}
378 fi
379
2472e0ea 380 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
381 if [ -z "${hook}" ]; then
382 error "Config file did not provide any hook."
383 return ${EXIT_ERROR}
384 fi
385
d61a01d4 386 if ! hook_zone_exists ${hook}; then
1848564d
MT
387 error "Hook '${hook}' does not exist."
388 return ${EXIT_ERROR}
389 fi
390
059469a8
MT
391 zone_db ${zone} stopping
392
2212045f 393 hook_zone_exec ${hook} down ${zone} "$@"
059469a8
MT
394
395 zone_db ${zone} stopped
69ace22b 396
de3cecef
MT
397 # Execute all triggers after the zone went down
398 triggers_execute_all "down" ZONE="${zone}"
1848564d
MT
399}
400
1c6a4e30 401zone_status() {
2472e0ea
MT
402 local zone="${1}"
403 assert isset zone
1848564d
MT
404 shift
405
2472e0ea 406 if ! zone_exists "${zone}"; then
1848564d
MT
407 error "Zone '${zone}' does not exist."
408 return ${EXIT_ERROR}
409 fi
410
2472e0ea 411 local hook="$(zone_get_hook "${zone}")"
1848564d
MT
412 if [ -z "${hook}" ]; then
413 error "Config file did not provide any hook."
414 return ${EXIT_ERROR}
415 fi
416
2472e0ea 417 if ! hook_zone_exists "${hook}"; then
1848564d
MT
418 error "Hook '${hook}' does not exist."
419 return ${EXIT_ERROR}
420 fi
421
2472e0ea 422 hook_zone_exec "${hook}" "status" "${zone}" "$@"
1848564d
MT
423}
424
f5ee091e
MT
425zone_identify() {
426 assert [ $# -ge 1 ]
427
428 local zone="${1}"
429 shift
430
431 assert zone_exists "${zone}"
432
433 log INFO "Identifying zone ${zone}"
434 local pids
435
436 local pid
437 local port
438 for port in $(zone_get_ports "${zone}"); do
439 # Identify all the ports
2212045f 440 port_identify "${port}" --background "$@"
f5ee091e
MT
441
442 # Save the PIDs of the subprocesses
443 list_append pids "$(cmd_background_get_pid)"
444 done
445
446 # Wait until all port_identfy processes have finished
447 for pid in ${pids}; do
448 cmd_background_result "${pid}"
449 done
450
451 return ${EXIT_OK}
452}
453
1c6a4e30 454zone_get_ports() {
711ffac1
MT
455 local zone=${1}
456
457 assert isset zone
458
459 local port
943e3f7e 460 for port in $(zone_dir ${zone})/ports/*; do
711ffac1 461 port=$(basename ${port})
711ffac1
MT
462
463 if port_exists ${port}; then
464 echo "${port}"
465 fi
466 done
467}
468
1c6a4e30 469zone_get_ports_num() {
529141df
MT
470 local zone="${1}"
471 assert isset zone
472
473 local counter=0
474 local port
475 for port in $(zone_dir "${zone}")/ports/*; do
476 port="$(basename "${port}")"
477
478 if port_exists "${port}"; then
479 counter=$(( ${counter} + 1 ))
480 fi
481 done
482
483 echo "${counter}"
484 return ${EXIT_OK}
485}
486
1c6a4e30 487zone_has_port() {
3a7fef62
MT
488 # Check, if the given port is configured
489 # in this zone.
490
491 local zone=${1}
492 local port=${2}
493 shift 2
494
495 assert isset zone
496 assert isset port
497
498 [ -e "$(zone_dir ${zone})/ports/${port}" ]
499}
500
1c6a4e30 501zone_config() {
ea699552
MT
502 local zone="${1}"
503 local cmd="${2}"
a5ebb169
MT
504 shift 2
505
506 assert isset zone
ea699552
MT
507 assert isset cmd
508 assert zone_exists "${zone}"
a5ebb169 509
ea699552 510 case "${cmd}" in
2a6b2397
MT
511 new)
512 zone_config_new "${zone}" "$@"
513 ;;
514 destroy)
e9582016
JS
515 # usually ${1} is a valid hid
516 local hid=${1}
517 shift 1
518
519 # We convert the hid into an id
520 local id=$(zone_config_convert_hid_to_id ${zone} ${hid})
521
522 # If id isset the hid is valid and we can go on with the id
523 if isset id; then
524 zone_config_destroy "${zone}" "${id}" "$@"
525
526 # If we can't get a valid hid we check if we got a valid id
ea37ec0b 527 else
e9582016
JS
528 if zone_config_id_is_valid ${zone} ${hid}; then
529 zone_config_destroy "${zone}" ${hid} "$@"
530 else
531 log ERROR "${id} is not a valid id or hid"
532 fi
ea37ec0b 533 fi
a5ebb169 534 ;;
a5d2c758
JS
535 list)
536 zone_config_list "${zone}" "$@"
537 ;;
a5ebb169 538 *)
e9582016
JS
539 # usually ${1} is a valid hid
540 local hid=${cmd}
541 local cmd=${1}
542 shift 1
543
544 local id=$(zone_config_convert_hid_to_id ${zone} ${hid})
545
546 # If id isset the hid is valid and we can go on with the id
547 if isset id && [[ ${cmd} == "edit" ]]; then
548 zone_config_edit "${zone}" "${id}" "$@"
e6a03d56 549
e9582016 550 # If we didn't get a valid hid we check if we got a valid id
e6a03d56 551 else
e9582016
JS
552 if zone_config_id_is_valid ${zone} ${id} && [[ ${cmd} == "edit" ]]; then
553 shift 1
554 zone_config_edit "${zone}" "${id}" "$@"
555 else
556 # in ${hid} is saved the command after network zone ${zone} config
557 error "Unrecognized argument: ${hid}"
558 cli_usage root-zone-config-subcommands
559 exit ${EXIT_ERROR}
560 fi
e6a03d56 561 fi
a5ebb169
MT
562 ;;
563 esac
564}
565
1c6a4e30 566zone_config_cmd() {
ea699552 567 assert [ $# -gt 2 ]
a5ebb169 568
ea699552
MT
569 local cmd="${1}"
570 local zone="${2}"
571 shift 2
572
573 local hook="$(zone_get_hook "${zone}")"
a5ebb169
MT
574 assert isset hook
575
ea699552
MT
576 hook_zone_exec "${hook}" "config_${cmd}" "${zone}" "$@"
577}
578
2a6b2397 579zone_config_new() {
44b8ade9
SS
580 local zone="${1}"
581 shift
582
583 # Create a new configuration, but exit when that was
584 # not successful.
585 zone_config_cmd "new" "${zone}" "$@" || return ${?}
586
587 # If the config could be created, we will try to bring
588 # it up if the zone is up, too.
589 if zone_is_up "${zone}"; then
590 zone_configs_up "${zone}"
591 fi
ea699552
MT
592}
593
2a6b2397
MT
594zone_config_destroy() {
595 zone_config_cmd "destroy" "$@"
ea699552
MT
596}
597
2a6b2397
MT
598zone_config_edit() {
599 zone_config_cmd "edit" "$@"
ea699552
MT
600}
601
a5d2c758
JS
602zone_config_list() {
603 # This function list in an nice way all configs of a zone
604 local zone=${1}
605 assert isset zone
606
607 # Print a nice header
fc36aaf4
JS
608 local format="%-3s %-20s %-20s"
609 print "${format}" "ID" "HOOK" "HID"
a5d2c758
JS
610
611 local config
612 local hook
613 local id
fc36aaf4 614 local hid
a5d2c758
JS
615
616 # Print for all config:
617 # id and hook
a5d2c758
JS
618 for config in $(zone_configs_list "${zone}"); do
619 id=${config##*.}
620 hook=$(zone_config_get_hook "${zone}" "${config}")
fc36aaf4 621 hid=$(zone_config_get_hid "${zone}" "${config}")
a5d2c758 622 assert isset hook
fc36aaf4 623 print "${format}" "${id}" "${hook}" "${hid}"
a5d2c758
JS
624 done
625}
626
1c6a4e30 627zone_config_show() {
ea699552 628 zone_config_cmd "show" "$@"
a5ebb169
MT
629}
630
d2998dc2
JS
631# Returns a list of all used ids for a zone
632zone_config_list_ids() {
633 assert [ $# -eq 1 ]
634
635 local zone=${1}
636 local config
637 local ids
638
639 for config in $(zone_configs_list ${zone}); do
640 list_append ids "$(config_get_id_from_config ${config})"
641 done
642
643 echo ${ids}
644}
645
450afe05
JS
646# List all hids of a zone
647zone_config_list_hids() {
648 assert [ $# -eq 1 ]
649
650 local zone=${1}
651
652 local config
653 for config in $(zone_configs_list ${zone}); do
654 zone_config_get_hid "${zone}" "${config}"
655 done
656}
657
658# get the hid from a given config
659zone_config_get_hid() {
660 assert [ $# -eq 2 ]
661
662 local zone=${1}
663 local config=${2}
664
665 local hook="$(zone_config_get_hook "${zone}" "${config}")"
666
667 hook_exec "config" "${hook}" "hid" "${zone}" "${config}"
668}
669
670# Checks if a hid is valid for a given zone
671zone_config_hid_is_valid() {
672 assert [ $# -eq 2]
673
674 local zone=${1}
675 local hid=${2}
676
677 local _hid
678 for _hid in $(zone_config_list_hids "${zone}"); do
679 if [[ ${_hid} = ${hid} ]]; then
680 return ${EXIT_TRUE}
681 fi
682 done
683
684 return ${EXIT_FALSE}
685}
686
687# This function converts a hid to a id
688zone_config_convert_hid_to_id() {
689 assert [ $# -eq 2 ]
690
691 local zone=${1}
692 local hid=${2}
693
694 local config
695 for config in $(zone_configs_list ${zone}); do
696 # Get hook from config
697 local hook="$(zone_config_get_hook "${zone}" "${config}")"
698
699 if [[ "$(hook_exec "config" "${hook}" "hid" "${zone}" "${config}")" == "${hid}" ]]; then
700 config_get_id_from_config "${config}"
701 return ${EXIT_TRUE}
702 fi
703 done
704
705 return ${EXIT_FALSE}
706}
707
1c6a4e30 708zone_show() {
1848564d
MT
709 local zone=${1}
710
711 echo "${zone}"
712 echo " Type: $(zone_get_hook ${zone})"
713 echo
714}
715
1c6a4e30 716zones_show() {
1848564d
MT
717 local zone
718
2212045f 719 for zone in $(zones_get "$@"); do
1848564d
MT
720 zone_show ${zone}
721 done
722}
723
1c6a4e30 724zones_get_all() {
1848564d 725 local zone
d61a01d4 726 for zone in $(zone_dir)/*; do
1848564d
MT
727 zone=$(basename ${zone})
728 zone_exists ${zone} || continue
729
730 echo "${zone}"
03170817 731 done
1848564d
MT
732}
733
1ca5fe9f
JS
734zones_get_next_free() {
735 # This function return the next free zones.
736 # Example net0 upl0 upl1 are configured so the next free zones are:
737 # net1 upl2
738 local i
739 local zone_name
740 for zone_name in ${VALID_ZONES}; do
741 i=0
742
743 while true; do
744 local zone="${zone_name}${i}"
745 if ! zone_exists ${zone}; then
746 echo "${zone}"
747 break
748 fi
749 i=$(( i + 1 ))
750 done
751 done
752}
753
1c6a4e30 754zones_get_local() {
1848564d
MT
755 local zone
756 for zone in $(zones_get_all); do
757 zone_is_local ${zone} && echo "${zone}"
758 done
759}
760
1c6a4e30 761zones_get_nonlocal() {
1848564d
MT
762 local zone
763 for zone in $(zones_get_all); do
5e42d659 764 zone_is_nonlocal ${zone} && echo "${zone}"
1848564d
MT
765 done
766}
767
1c6a4e30 768zones_get() {
1848564d
MT
769 local local=1
770 local remote=1
771
772 local zones
773
774 while [ $# -gt 0 ]; do
775 case "${1}" in
776 --local-only)
777 local=1
778 remote=0
779 ;;
780 --remote-only)
781 local=0
782 remote=1
783 ;;
784 --all)
785 local=1
786 remote=1
787 ;;
788 *)
789 if zone_name_is_valid ${1}; then
790 zones="${zones} ${1}"
791 else
792 warning "Unrecognized argument '${1}'"
793 fi
794 ;;
795 esac
796 shift
797 done
798
799 if [ -n "${zones}" ]; then
800 local zone
801 for zone in ${zones}; do
802 zone_exists ${zone} && echo "${zone}"
803 done
804 exit ${EXIT_OK}
805 fi
806
807 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
808 zones_get_all
809 elif [ ${local} -eq 1 ]; then
810 zones_get_local
811 elif [ ${remote} -eq 1 ]; then
812 zones_get_nonlocal
813 fi
814}
815
1c6a4e30 816zone_ports_list() {
1848564d
MT
817 local zone=${1}
818
819 local port
a5ebb169 820 for port in $(zone_dir ${zone})/ports/*; do
1848564d
MT
821 [ -e "${port}" ] || continue
822
823 echo $(basename ${port})
03170817 824 done
1848564d
MT
825}
826
1c6a4e30 827zone_port_attach() {
ac694a6a
MT
828 local zone="${1}"
829 assert isset zone
830
831 local port="${2}"
832 assert isset port
833
834 shift 2
835
836 # Check if the port actually exists.
837 if ! port_exists "${port}"; then
838 error "Cannot attach port '${port}' which does not exist"
839 return ${EXIT_ERROR}
840 fi
841
842 # Check if the port is already connected to this or any other zone.
843 local z
844 for z in $(zones_get_all); do
845 if zone_has_port "${z}" "${port}"; then
846 error "Port '${port}' is already attached to zone '${z}'"
847 return ${EXIT_ERROR}
848 fi
849 done
850
851 local hook="$(zone_get_hook "${zone}")"
852 assert isset hook
853
f5ee091e 854 # Make the port briefly flash if supported
01a079e0
MT
855 if device_exists ${port}; then
856 port_identify "${port}" --background
857 fi
f5ee091e 858
ac694a6a
MT
859 hook_zone_exec "${hook}" "port_attach" "${zone}" "${port}" "$@"
860 local ret="${?}"
861
862 case "${ret}" in
863 ${EXIT_OK})
864 log INFO "${port} has been attached to ${zone}"
865
866 # Automatically connect the port
abba34c1 867 zone_port_start "${zone}" "${port}"
ac694a6a
MT
868 ;;
869 *)
870 log CRITICAL "${port} could not be attached to ${zone}"
871 ;;
872 esac
873
874 return ${ret}
875}
876
1c6a4e30 877zone_port_edit() {
ac694a6a
MT
878 local zone="${1}"
879 assert isset zone
880
881 local port="${2}"
882 assert isset port
883
884 shift 2
885
886 # Check if the port actually exists.
887 if ! port_exists "${port}"; then
888 error "Port '${port}' does not exist"
889 return ${EXIT_ERROR}
890 fi
891
892 # Check if the zone actually has this port.
893 if ! zone_has_port "${zone}" "${port}"; then
894 error "Port '${port}' is not attached to zone '${zone}'"
895 return ${EXIT_ERROR}
896 fi
897
898 local hook=$(zone_get_hook "${zone}")
899 assert isset hook
900
901 hook_zone_exec "${hook}" "port_edit" "${zone}" "${port}" "$@"
902}
903
1c6a4e30 904zone_port_detach() {
ac694a6a
MT
905 local zone="${1}"
906 assert isset zone
907
908 local port="${2}"
909 assert isset port
910
1848564d
MT
911 shift 2
912
ac694a6a
MT
913 # Check if the zone actually has this port.
914 if ! zone_has_port "${zone}" "${port}"; then
915 error "Port '${port}' is not attached to zone '${zone}'"
916 return ${EXIT_ERROR}
917 fi
918
919 local hook=$(zone_get_hook "${zone}")
920 assert isset hook
921
f5ee091e
MT
922 # Make the port briefly flash if supported
923 port_identify "${port}" --background
924
ac694a6a
MT
925 hook_zone_exec "${hook}" "port_detach" "${zone}" "${port}" "$@"
926 local ret="${?}"
927
928 case "${ret}" in
929 ${EXIT_OK})
930 log INFO "${port} has been detached from ${zone}"
931
932 # Bring down the port if needed
abba34c1 933 zone_port_stop "${zone}" "${port}"
ac694a6a
MT
934 ;;
935 *)
936 log CRITICAL "${port} could not be detached from ${zone}"
937 ;;
938 esac
939
940 return ${ret}
941}
942
1c6a4e30 943zone_port_cmd() {
ac694a6a 944 local cmd="${1}"
711ffac1 945 assert isset cmd
ac694a6a
MT
946
947 local zone="${2}"
711ffac1 948 assert isset zone
1848564d 949
ac694a6a
MT
950 local port="${3}"
951 assert isset port
1848564d 952
ac694a6a
MT
953 shift 3
954
955 local hook="$(zone_get_hook "${zone}")"
956 assert isset hook
957
958 # Dispatch command to hook
2212045f 959 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" "$@"
ac694a6a
MT
960}
961
1c6a4e30 962zone_port_create() {
2212045f 963 zone_port_cmd "port_create" "$@"
ac694a6a
MT
964}
965
1c6a4e30 966zone_port_remove() {
2212045f 967 zone_port_cmd "port_remove" "$@"
ac694a6a
MT
968}
969
1c6a4e30 970zone_port_up() {
2212045f 971 zone_port_cmd "port_up" "$@"
ac694a6a
MT
972}
973
1c6a4e30 974zone_port_down() {
2212045f 975 zone_port_cmd "port_down" "$@"
ac694a6a
MT
976}
977
abba34c1
MT
978# The next two functions automagically bring up and down
979# port that are attached to a bridge or similar.
980# The problem that is tried to overcome here is that there
981# are ports which exist all the time (like ethernet ports)
982# and therefore do not dispatch a hotplug event when
983# port_create is called.
984
1c6a4e30 985zone_port_start() {
abba34c1
MT
986 local zone="${1}"
987 local port="${2}"
988
989 if zone_is_active "${zone}"; then
990 if device_exists "${port}"; then
991 zone_port_up "${zone}" "${port}"
992 return ${?}
993 else
994 zone_port_create "${zone}" "${port}"
995 return ${?}
996 fi
997 fi
998
999 return ${EXIT_OK}
1000}
1001
1c6a4e30 1002zone_port_stop() {
abba34c1
MT
1003 local zone="${1}"
1004 local port="${2}"
1005
1006 # Shut down the port if necessary
1007 if zone_is_active "${zone}" && port_is_up "${port}"; then
1008 zone_port_down "${zone}" "${port}"
1009 fi
1010
1011 # Remove the port
1012 zone_port_remove "${zone}" "${port}"
1013}
1014
1c6a4e30 1015zone_port_status() {
2212045f 1016 zone_port_cmd "port_status" "$@"
ac694a6a
MT
1017}
1018
1c6a4e30 1019zone_ports_cmd() {
ac694a6a
MT
1020 local cmd="${1}"
1021 assert isset cmd
1022
1023 local zone="${2}"
1024 assert isset zone
1025
1026 shift 2
1027
1028 local hook="$(zone_get_hook "${zone}")"
711ffac1
MT
1029
1030 local port
1031 for port in $(zone_get_ports ${zone}); do
2212045f 1032 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" "$@"
1848564d
MT
1033 done
1034}
1035
1c6a4e30 1036zone_ports_create() {
2212045f 1037 zone_ports_cmd "port_create" "$@"
1ba6a2bb
MT
1038}
1039
1c6a4e30 1040zone_ports_remove() {
2212045f 1041 zone_ports_cmd "port_remove" "$@"
1ba6a2bb
MT
1042}
1043
1c6a4e30 1044zone_ports_up() {
2212045f 1045 zone_ports_cmd "port_up" "$@"
1848564d
MT
1046}
1047
1c6a4e30 1048zone_ports_down() {
2212045f 1049 zone_ports_cmd "port_down" "$@"
711ffac1
MT
1050}
1051
1c6a4e30 1052zone_ports_status() {
2212045f 1053 zone_ports_cmd "port_status" "$@"
1848564d
MT
1054}
1055
1c6a4e30 1056zone_configs_cmd() {
2472e0ea 1057 assert [ $# -ge 2 ]
ea699552
MT
1058
1059 local cmd="${1}"
1060 local zone="${2}"
1848564d
MT
1061 shift 2
1062
ea699552 1063 assert zone_exists "${zone}"
1848564d 1064
1848564d 1065 local config
2472e0ea
MT
1066 for config in $(zone_configs_list "${zone}"); do
1067 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1068 assert isset config_hook
1069
2212045f 1070 hook_config_exec "${config_hook}" "${cmd}" "${zone}" "${config}" "$@"
1848564d
MT
1071 done
1072}
1073
1c6a4e30 1074zone_configs_up() {
2212045f 1075 zone_configs_cmd "up" "$@"
1848564d
MT
1076}
1077
1c6a4e30 1078zone_configs_down() {
2212045f 1079 zone_configs_cmd "down" "$@"
1848564d
MT
1080}
1081
1c6a4e30 1082zone_configs_status() {
2212045f 1083 zone_configs_cmd "status" "$@"
ea699552
MT
1084}
1085
1c6a4e30 1086zone_configs_list() {
ea699552
MT
1087 local zone=${1}
1088
1089 local config
1090 for config in $(zone_dir ${zone})/configs/*; do
1091 [ -e "${config}" ] || continue
1092
1093 basename ${config}
1094 done
a5ebb169
MT
1095}
1096
0afedf0d
JS
1097zone_config_get_new_id() {
1098 # This functions returns the next free id for a zone
1099
1100 assert [ $# -eq 1 ]
1101 local zone=${1}
1102
1103 local zone_path=$(zone_dir ${zone})
1104 local i=0
1105
1106 while true; do
1107 if [ ! -f ${zone_path}/configs/*.${i} ]; then
1108 echo "${i}"
1109 return ${EXIT_OK}
1110 fi
1111 (( i++ ))
1112 done
1113}
1114
6727e4be
JS
1115zone_config_check_same_setting() {
1116 # This functions checks if a config hook
1117 # with the same setting is already configured for this zone.
1118 # Returns True when yes and False when no.
1119
1120 assert [ $# -eq 4 ]
1121
1122 local zone=${1}
1123 local hook=${2}
1124 local key=${3}
1125 local value=${4}
1126
1127 # The key should be local for this function
1128 local ${key}
1129 local config
1130
1131 for config in $(zone_configs_list ${zone}); do
1132 # Check if the config is from the given hook, when not continue
1133 if [[ $(zone_config_get_hook "${zone}" "${config}") != ${hook} ]]; then
1134 continue
1135 fi
1136 # Get the value of the key for a given function
1137 zone_config_settings_read "${zone}" "${config}" \
1138 --ignore-superfluous-settings "${key}"
1139 # Check if the value of the config and the passed value are eqal
1140 if [[ "${value}" == "${!key}" ]]; then
1141 return ${EXIT_TRUE}
1142 fi
1143 done
1144
1145 return ${EXIT_FALSE}
1146}
1147
1c6a4e30 1148zone_config_get_hook() {
2472e0ea
MT
1149 assert [ $# -eq 2 ]
1150
1151 local zone="${1}"
1152 assert isset zone
1153
1154 local config="${2}"
1155 assert isset config
1156
1157 local HOOK
1158 zone_config_settings_read "${zone}" "${config}" \
1159 --ignore-superfluous-settings HOOK
1160
1161 print "${HOOK}"
1162}
1163
41f8233d
JS
1164zone_config_hook_is_configured() {
1165 # Checks if a zone has already at least one config with the given hook.
1166 # Returns True when yes and False when no
1167
1168 assert [ $# -eq 2 ]
1169 local zone=${1}
1170 local hook=${2}
1171
1172 local config
1173 for config in $(zone_configs_list "${zone}"); do
1174 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1175 assert isset config_hook
1176 if [[ ${hook} == ${config_hook} ]]; then
1177 return ${EXIT_TRUE}
1178 fi
1179
1180 done
1181
1182 # If we get here the zone has no config with the given hook
1183 return ${EXIT_FALSE}
1184}
1185
f158dc66
JS
1186zone_config_id_is_valid() {
1187 # This function checks if a given id is valid for a zone
1188 # Return True when yes and false when no
1189
1190 assert [ $# -eq 2 ]
1191 local zone=${1}
1192 local id=${2}
1193
1194 local zone_path=$(zone_dir ${zone})
1195
1196 [ -f ${zone_path}/configs/*.${id} ];
1197}
1198
450afe05
JS
1199# This function checks if a given hid is valid for a zone
1200# Return True when yes and false when no
1201zone_config_hid_is_valid() {
1202 assert [ $# -eq 2 ]
1203 local zone=${1}
1204 local hid=${2}
1205
1206 local _hid
1207 for _hid in $(zone_config_list_hids ${zone}); do
1208 if [[ ${_hid} == ${hid} ]]; then
1209 return ${EXIT_TRUE}
1210 fi
1211 done
1212
1213 return ${EXIT_FALSE}
1214}
1215
cdf4266d
JS
1216zone_config_get_hook_from_id() {
1217 # Returns the hook for a given id
1218 assert [ $# -eq 2 ]
1219 local zone=${1}
1220 local id=${2}
1221
1222 local config
1223 for config in $(zone_configs_list "${zone}"); do
1224 if [[ ${config} == *.${id} ]]; then
1225 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
1226 assert isset config_hook
1227 print "${config_hook}"
1228 return "${EXIT_OK}"
1229 fi
1230 done
1231
1232 # If we get here the zone has no config with the given id
1233 return ${EXIT_ERROR}
1234}
1235
1c6a4e30 1236zone_has_ip() {
2212045f 1237 device_has_ip "$@"
4231f419
MT
1238}
1239
1c6a4e30 1240zone_db() {
059469a8
MT
1241 local zone=${1}
1242 local action=${2}
1243 shift 2
1244
1245 case "${action}" in
1246 starting|started|stopping|stopped)
1247 db_connection_update ${zone} ${action}
1248 ;;
1249 esac
1250}
5e42d659 1251
1c6a4e30 1252zone_is_up() {
5e42d659
MT
1253 local zone=${1}
1254
1255 device_is_up ${zone}
1256}
1257
1c6a4e30 1258zone_is_down() {
2212045f 1259 ! zone_is_up "$@"
5e42d659 1260}
711ffac1 1261
1c6a4e30 1262zone_get_supported_port_hooks() {
711ffac1
MT
1263 local zone=${1}
1264
1265 local hook=$(zone_get_hook ${zone})
1266
1267 hook_zone_ports_get_all ${hook}
1268}
1269
1c6a4e30 1270zone_get_supported_config_hooks() {
ea699552 1271 hook_config_get_all
a5ebb169
MT
1272}
1273
1c6a4e30 1274zone_file() {
711ffac1
MT
1275 local zone=${1}
1276
1277 assert isset zone
1278
1279 echo "$(zone_dir ${zone})/settings"
1280}
1281
1c6a4e30 1282zone_settings_read() {
711ffac1 1283 local zone=${1}
711ffac1 1284 assert isset zone
52acd25f
MT
1285 shift
1286
1287 local args
1288 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
1289 list_append args ${HOOK_SETTINGS}
1290 else
2212045f 1291 list_append args "$@"
52acd25f 1292 fi
711ffac1 1293
bfd6c282
MT
1294 # Save the HOOK variable.
1295 local hook="${HOOK}"
1296
52acd25f 1297 settings_read "$(zone_file "${zone}")" ${args}
bfd6c282
MT
1298
1299 # Restore hook.
1300 HOOK="${hook}"
711ffac1
MT
1301}
1302
1c6a4e30 1303zone_settings_write() {
1e6f187e 1304 local zone="${1}"
711ffac1
MT
1305 assert isset zone
1306
1e6f187e
MT
1307 local args
1308 if function_exists "hook_check_settings"; then
1309 list_append args "--check=\"hook_check_settings\""
1310 fi
1311 list_append args ${HOOK_SETTINGS}
1312
1313 settings_write "$(zone_file ${zone})" ${args}
711ffac1
MT
1314}
1315
1c6a4e30 1316zone_settings_set() {
711ffac1
MT
1317 local zone=${1}
1318 shift
1319 local args="$@"
1320
1321 assert isset zone
1322
1323 (
e9df08ad 1324 zone_settings_read ${zone}
711ffac1
MT
1325
1326 for arg in ${args}; do
1327 eval "${arg}"
1328 done
1329
e9df08ad 1330 zone_settings_write ${zone}
711ffac1
MT
1331 )
1332}
6b3f9c85 1333
1c6a4e30 1334zone_settings_get() {
6b3f9c85
MT
1335 local zone=${1}
1336 local key=${2}
1337
1338 assert isset zone
1339 assert isset key
1340
1341 (
1e6f187e
MT
1342 zone_settings_read "${zone}" "${key}" \
1343 --ignore-superfluous-settings
6b3f9c85
MT
1344
1345 echo "${!key}"
1346 )
1347}
e9df08ad 1348
1c6a4e30 1349zone_config_settings_read() {
c8132752 1350 assert [ $# -ge 2 ]
e9df08ad
MT
1351
1352 local zone="${1}"
1353 local config="${2}"
1354 shift 2
1355
c8132752
MT
1356 local args
1357 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1358 list_append args ${HOOK_CONFIG_SETTINGS}
1359 else
2212045f 1360 list_append args "$@"
c8132752
MT
1361 fi
1362
e9df08ad 1363 local path="$(zone_dir "${zone}")/configs/${config}"
c8132752 1364 settings_read "${path}" ${args}
e9df08ad
MT
1365}
1366
1c6a4e30 1367zone_config_settings_write() {
c8132752 1368 assert [ $# -ge 2 ]
e9df08ad
MT
1369
1370 local zone="${1}"
0959b0b9
JS
1371 local hook="${2}"
1372 local id=${3}
1373
1374 if ! isset id; then
1375 id=$(zone_config_get_new_id ${zone})
1376 log DEBUG "ID for the config is: ${id}"
1377 fi
e9df08ad 1378
c8132752
MT
1379 local args
1380 if function_exists "hook_check_config_settings"; then
1381 list_append args "--check=\"hook_check_config_settings\""
1382 fi
1383 list_append args ${HOOK_CONFIG_SETTINGS}
1384
0959b0b9 1385 local path="$(zone_dir "${zone}")/configs/${hook}.${id}"
c8132752 1386 settings_write "${path}" ${args}
e9df08ad
MT
1387}
1388
ea96cf52
JS
1389zone_config_settings_destroy() {
1390 # This function deletes the config file for a given zone and config
1391 assert [ $# -ge 2 ]
1392 local zone="${1}"
1393 local config="${2}"
1394
1395 local path="$(zone_dir "${zone}")/configs/${config}"
1396
1397 # Check if path is valid
1398 if [ ! -f ${path} ]; then
1399 log ERROR "Path: '${path}' is not valid"
1400 return ${EXIT_ERROR}
1401 fi
1402
1403 log DEBUG "Deleting config file ${path}"
1404 rm -f "${path}"
1405
1406}
1c6a4e30 1407zone_port_settings_read() {
ac694a6a 1408 assert [ $# -ge 2 ]
e9df08ad
MT
1409
1410 local zone="${1}"
1411 local port="${2}"
1412 shift 2
1413
ac694a6a
MT
1414 local args
1415 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1416 list_append args ${HOOK_PORT_SETTINGS}
1417 else
2212045f 1418 list_append args "$@"
ac694a6a
MT
1419 fi
1420
e9df08ad 1421 local path="$(zone_dir "${zone}")/ports/${port}"
ac694a6a 1422 settings_read "${path}" ${args}
e9df08ad
MT
1423}
1424
1c6a4e30 1425zone_port_settings_write() {
02236ca6 1426 assert [ $# -ge 2 ]
e9df08ad
MT
1427
1428 local zone="${1}"
1429 local port="${2}"
1430 shift 2
1431
1e6f187e
MT
1432 local args
1433 if function_exists "hook_check_port_settings"; then
1434 list_append args "--check=\"hook_check_port_settings\""
1435 fi
ac694a6a 1436 list_append args ${HOOK_PORT_SETTINGS}
1e6f187e 1437
e9df08ad 1438 local path="$(zone_dir "${zone}")/ports/${port}"
1e6f187e 1439 settings_write "${path}" ${args}
e9df08ad
MT
1440}
1441
1c6a4e30 1442zone_port_settings_remove() {
e9df08ad
MT
1443 assert [ $# -eq 2 ]
1444
1445 local zone="${1}"
1446 local port="${2}"
1447
1448 local path="$(zone_dir "${zone}")/ports/${port}"
1449 settings_remove "${path}"
1450}
410d2e85
JS
1451
1452zone_get_color() {
1453 # This function return the color of a zone
1454 assert [ $# -eq 1 ]
1455
1456 local name=${1}
1457 color_read "zone" ${name}
1458}
5de34b4c
JS
1459
1460zone_get_description_title() {
1461 assert [ $# -eq 1 ]
1462
1463 local name=${1}
1464 description_title_read $(description_format_filename "zone" "${name}")
1465}