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