]> git.ipfire.org Git - people/stevee/network.git/blob - src/functions/functions.zone
4874f388dad7ac3584603316c32384fa4f724e21
[people/stevee/network.git] / src / functions / functions.zone
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
22 function zone_dir() {
23 local zone=${1}
24
25 echo "${NETWORK_ZONE_DIR}/zones/${zone}"
26 }
27
28 function zone_exists() {
29 local zone=${1}
30 assert isset zone
31
32 [ -d "$(zone_dir ${zone})" ]
33 }
34
35 function zone_match() {
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
46 function zone_name_is_valid() {
47 local zone=${1}
48
49 # Don't accept empty strings.
50 [ -z "${zone}" ] && return ${EXIT_FALSE}
51
52 [[ ${zone} =~ $(zone_match) ]]
53 }
54
55 function zone_is_local() {
56 local zone=${1}
57
58 [[ "${zone:0:${#ZONE_LOCAL}}" = "${ZONE_LOCAL}" ]]
59 }
60
61 function zone_is_nonlocal() {
62 local zone=${1}
63
64 [[ "${zone:0:${#ZONE_NONLOCAL}}" = "${ZONE_NONLOCAL}" ]]
65 }
66
67 function zone_get_hook() {
68 local zone=${1}
69 assert isset zone
70
71 config_get_hook $(zone_dir ${zone})/settings
72 }
73
74 function zone_start() {
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
81 service_start "network@${zone}.service"
82 }
83
84 function zone_start_auto() {
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
106 function zone_stop() {
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
113 service_stop "network@${zone}.service"
114 }
115
116 function zone_reload() {
117 local zone="${1}"
118 assert zone_exists "${zone}"
119
120 service_reload "network@${zone}.service"
121 }
122
123 function zone_hotplug_event() {
124 local zone="${1}"
125 assert isset zone
126
127 hotplug_assert_in_hotplug_event
128
129 zone_cmd "hotplug" "${zone}"
130 }
131
132 function zone_enable() {
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
152 function zone_disable() {
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
172 function zone_is_enabled() {
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
184 function zone_is_active() {
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
195 function zone_is_enabled_or_active() {
196 local zone="${1}"
197 assert isset zone
198
199 zone_is_enabled "${zone}" || zone_is_active "${zone}"
200 }
201
202 function zone_cmd() {
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
213 hook_exec zone "${hook}" "${cmd}" "${zone}" $@
214 }
215
216 function zone_new() {
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
231 if ! hook_zone_exists ${hook}; then
232 error "Hook '${hook}' does not exist."
233 return ${EXIT_ERROR}
234 fi
235
236 mkdir -p $(zone_dir ${zone})
237
238 # Create directories for configs and ports
239 mkdir -p $(zone_dir ${zone})/{configs,ports}
240
241 hook_zone_exec "${hook}" "new" "${zone}" $@
242 local ret=$?
243
244 # Maybe the zone new hook did not exit correctly.
245 # If this is the case we remove the created zone immediately.
246 if [ "${ret}" = "${EXIT_ERROR}" ]; then
247 zone_destroy_now "${zone}"
248 return ${EXIT_ERROR}
249 fi
250
251 # Automatically enable zone.
252 zone_enable "${zone}"
253
254 # Bring up the zone immediately after
255 zone_start "${zone}"
256 }
257
258 function zone_edit() {
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
267 # Check if the zone is tagged for removal.
268 if zone_has_destroy_tag ${zone}; then
269 error "You cannot edit a zone that is tagged for removal."
270 return ${EXIT_ERROR}
271 fi
272
273 local hook="$(zone_get_hook "${zone}")"
274 if [ -z "${hook}" ]; then
275 error "Config file did not provide any hook."
276 return ${EXIT_ERROR}
277 fi
278
279 if ! hook_zone_exists ${hook}; then
280 error "Hook '${hook}' does not exist."
281 return ${EXIT_ERROR}
282 fi
283
284 hook_zone_exec ${hook} edit ${zone} $@
285 }
286
287
288 function zone_destroy() {
289 local zone="${1}"
290 assert zone_exists "${zone}"
291
292 # Make the zone for removal.
293 touch "$(zone_dir "${zone}")/.destroy"
294
295 log INFO "Zone '${zone}' has been tagged for removal."
296 }
297
298 function zone_has_destroy_tag() {
299 local zone="${1}"
300 assert zone_exists "${zone}"
301
302 [ -e "$(zone_dir "${zone}")/.destroy" ]
303 }
304
305 # This function will remove the given zone
306 # RIGHT NOW. Use zone_destroy to remove it
307 # at the next status change.
308 function zone_destroy_now() {
309 local zone="${1}"
310 assert zone_exists "${zone}"
311
312 log INFO "Removing zone '${zone}' right now."
313
314 # Force the zone down.
315 zone_is_active "${zone}" && zone_stop "${zone}"
316
317 # Disable zone.
318 zone_disable "${zone}"
319
320 rm -rf "$(zone_dir "${zone}")"
321 }
322
323 function zone_up() {
324 local zone=${1}
325 shift
326
327 if ! zone_exists ${zone}; then
328 error "Zone '${zone}' does not exist."
329 return ${EXIT_ERROR}
330 fi
331
332 # Check if a zone has got the remove tag.
333 if zone_has_destroy_tag ${zone}; then
334 error "Cannot bring up any zone which is to be removed."
335 return ${EXIT_ERROR}
336 fi
337
338 local hook="$(zone_get_hook "${zone}")"
339 if [ -z "${hook}" ]; then
340 error "Config file did not provide any hook."
341 return ${EXIT_ERROR}
342 fi
343
344 if ! hook_zone_exists ${hook}; then
345 error "Hook '${hook}' does not exist."
346 return ${EXIT_ERROR}
347 fi
348
349 zone_db ${zone} starting
350
351 hook_zone_exec ${hook} up ${zone} $@
352
353 zone_db ${zone} started
354 }
355
356 function zone_down() {
357 local zone=${1}
358 shift
359
360 if ! zone_exists ${zone}; then
361 error "Zone '${zone}' does not exist."
362 return ${EXIT_ERROR}
363 fi
364
365 local hook="$(zone_get_hook "${zone}")"
366 if [ -z "${hook}" ]; then
367 error "Config file did not provide any hook."
368 return ${EXIT_ERROR}
369 fi
370
371 if ! hook_zone_exists ${hook}; then
372 error "Hook '${hook}' does not exist."
373 return ${EXIT_ERROR}
374 fi
375
376 zone_db ${zone} stopping
377
378 hook_zone_exec ${hook} down ${zone} $@
379
380 zone_db ${zone} stopped
381
382 # Remove the zone, if it has got a remove tag.
383 if zone_has_destroy_tag "${zone}"; then
384 zone_destroy_now "${zone}"
385 fi
386 }
387
388 function zone_status() {
389 local zone="${1}"
390 assert isset zone
391 shift
392
393 if ! zone_exists "${zone}"; then
394 error "Zone '${zone}' does not exist."
395 return ${EXIT_ERROR}
396 fi
397
398 local hook="$(zone_get_hook "${zone}")"
399 if [ -z "${hook}" ]; then
400 error "Config file did not provide any hook."
401 return ${EXIT_ERROR}
402 fi
403
404 if ! hook_zone_exists "${hook}"; then
405 error "Hook '${hook}' does not exist."
406 return ${EXIT_ERROR}
407 fi
408
409 hook_zone_exec "${hook}" "status" "${zone}" "$@"
410
411 # Show that the zone it to be removed soon.
412 if zone_has_destroy_tag ${zone}; then
413 warning "This zone is tagged for removal."
414 fi
415 }
416
417 function zone_get_ports() {
418 local zone=${1}
419
420 assert isset zone
421
422 local port
423 for port in $(zone_dir ${zone})/ports/*; do
424 port=$(basename ${port})
425
426 if port_exists ${port}; then
427 echo "${port}"
428 fi
429 done
430 }
431
432 function zone_get_ports_num() {
433 local zone="${1}"
434 assert isset zone
435
436 local counter=0
437 local port
438 for port in $(zone_dir "${zone}")/ports/*; do
439 port="$(basename "${port}")"
440
441 if port_exists "${port}"; then
442 counter=$(( ${counter} + 1 ))
443 fi
444 done
445
446 echo "${counter}"
447 return ${EXIT_OK}
448 }
449
450 function zone_has_port() {
451 # Check, if the given port is configured
452 # in this zone.
453
454 local zone=${1}
455 local port=${2}
456 shift 2
457
458 assert isset zone
459 assert isset port
460
461 [ -e "$(zone_dir ${zone})/ports/${port}" ]
462 }
463
464 function zone_config() {
465 local zone="${1}"
466 local cmd="${2}"
467 shift 2
468
469 assert isset zone
470 assert isset cmd
471 assert zone_exists "${zone}"
472
473 case "${cmd}" in
474 create)
475 zone_config_create "${zone}" "$@"
476 ;;
477 edit)
478 zone_config_edit "${zone}" "$@"
479 ;;
480 remove)
481 zone_config_remove "${zone}" "$@"
482 ;;
483 *)
484 error "Unrecognized argument: ${cmd}"
485 cli_usage root-zone-config-subcommands
486 exit ${EXIT_ERROR}
487 ;;
488 esac
489 }
490
491 function zone_config_cmd() {
492 assert [ $# -gt 2 ]
493
494 local cmd="${1}"
495 local zone="${2}"
496 shift 2
497
498 local hook="$(zone_get_hook "${zone}")"
499 assert isset hook
500
501 hook_zone_exec "${hook}" "config_${cmd}" "${zone}" "$@"
502 }
503
504 function zone_config_create() {
505 zone_config_cmd "create" "$@"
506 }
507
508 function zone_config_edit() {
509 zone_config_cmd "edit" "$@"
510 }
511
512 function zone_config_remove() {
513 zone_config_cmd "remove" "$@"
514 }
515
516 function zone_config_show() {
517 zone_config_cmd "show" "$@"
518 }
519
520 function zone_show() {
521 local zone=${1}
522
523 echo "${zone}"
524 echo " Type: $(zone_get_hook ${zone})"
525 echo
526 }
527
528 function zones_show() {
529 local zone
530
531 for zone in $(zones_get $@); do
532 zone_show ${zone}
533 done
534 }
535
536 function zones_get_all() {
537 local zone
538 for zone in $(zone_dir)/*; do
539 zone=$(basename ${zone})
540 zone_exists ${zone} || continue
541
542 echo "${zone}"
543 done
544 }
545
546 function zones_get_local() {
547 local zone
548 for zone in $(zones_get_all); do
549 zone_is_local ${zone} && echo "${zone}"
550 done
551 }
552
553 function zones_get_nonlocal() {
554 local zone
555 for zone in $(zones_get_all); do
556 zone_is_nonlocal ${zone} && echo "${zone}"
557 done
558 }
559
560 function zones_get() {
561 local local=1
562 local remote=1
563
564 local zones
565
566 while [ $# -gt 0 ]; do
567 case "${1}" in
568 --local-only)
569 local=1
570 remote=0
571 ;;
572 --remote-only)
573 local=0
574 remote=1
575 ;;
576 --all)
577 local=1
578 remote=1
579 ;;
580 *)
581 if zone_name_is_valid ${1}; then
582 zones="${zones} ${1}"
583 else
584 warning "Unrecognized argument '${1}'"
585 fi
586 ;;
587 esac
588 shift
589 done
590
591 if [ -n "${zones}" ]; then
592 local zone
593 for zone in ${zones}; do
594 zone_exists ${zone} && echo "${zone}"
595 done
596 exit ${EXIT_OK}
597 fi
598
599 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
600 zones_get_all
601 elif [ ${local} -eq 1 ]; then
602 zones_get_local
603 elif [ ${remote} -eq 1 ]; then
604 zones_get_nonlocal
605 fi
606 }
607
608 function zone_ports_list() {
609 local zone=${1}
610
611 local port
612 for port in $(zone_dir ${zone})/ports/*; do
613 [ -e "${port}" ] || continue
614
615 echo $(basename ${port})
616 done
617 }
618
619 function zone_port_attach() {
620 local zone="${1}"
621 assert isset zone
622
623 local port="${2}"
624 assert isset port
625
626 shift 2
627
628 # Check if the port actually exists.
629 if ! port_exists "${port}"; then
630 error "Cannot attach port '${port}' which does not exist"
631 return ${EXIT_ERROR}
632 fi
633
634 # Check if the port is already connected to this or any other zone.
635 local z
636 for z in $(zones_get_all); do
637 if zone_has_port "${z}" "${port}"; then
638 error "Port '${port}' is already attached to zone '${z}'"
639 return ${EXIT_ERROR}
640 fi
641 done
642
643 local hook="$(zone_get_hook "${zone}")"
644 assert isset hook
645
646 hook_zone_exec "${hook}" "port_attach" "${zone}" "${port}" "$@"
647 local ret="${?}"
648
649 case "${ret}" in
650 ${EXIT_OK})
651 log INFO "${port} has been attached to ${zone}"
652
653 # Automatically connect the port
654 zone_port_start "${zone}" "${port}"
655 ;;
656 *)
657 log CRITICAL "${port} could not be attached to ${zone}"
658 ;;
659 esac
660
661 return ${ret}
662 }
663
664 function zone_port_edit() {
665 local zone="${1}"
666 assert isset zone
667
668 local port="${2}"
669 assert isset port
670
671 shift 2
672
673 # Check if the port actually exists.
674 if ! port_exists "${port}"; then
675 error "Port '${port}' does not exist"
676 return ${EXIT_ERROR}
677 fi
678
679 # Check if the zone actually has this port.
680 if ! zone_has_port "${zone}" "${port}"; then
681 error "Port '${port}' is not attached to zone '${zone}'"
682 return ${EXIT_ERROR}
683 fi
684
685 local hook=$(zone_get_hook "${zone}")
686 assert isset hook
687
688 hook_zone_exec "${hook}" "port_edit" "${zone}" "${port}" "$@"
689 }
690
691 function zone_port_detach() {
692 local zone="${1}"
693 assert isset zone
694
695 local port="${2}"
696 assert isset port
697
698 shift 2
699
700 # Check if the zone actually has this port.
701 if ! zone_has_port "${zone}" "${port}"; then
702 error "Port '${port}' is not attached to zone '${zone}'"
703 return ${EXIT_ERROR}
704 fi
705
706 local hook=$(zone_get_hook "${zone}")
707 assert isset hook
708
709 hook_zone_exec "${hook}" "port_detach" "${zone}" "${port}" "$@"
710 local ret="${?}"
711
712 case "${ret}" in
713 ${EXIT_OK})
714 log INFO "${port} has been detached from ${zone}"
715
716 # Bring down the port if needed
717 zone_port_stop "${zone}" "${port}"
718 ;;
719 *)
720 log CRITICAL "${port} could not be detached from ${zone}"
721 ;;
722 esac
723
724 return ${ret}
725 }
726
727 function zone_port_cmd() {
728 local cmd="${1}"
729 assert isset cmd
730
731 local zone="${2}"
732 assert isset zone
733
734 local port="${3}"
735 assert isset port
736
737 shift 3
738
739 local hook="$(zone_get_hook "${zone}")"
740 assert isset hook
741
742 # Dispatch command to hook
743 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
744 }
745
746 function zone_port_create() {
747 zone_port_cmd "port_create" $@
748 }
749
750 function zone_port_remove() {
751 zone_port_cmd "port_remove" $@
752 }
753
754 function zone_port_up() {
755 zone_port_cmd "port_up" $@
756 }
757
758 function zone_port_down() {
759 zone_port_cmd "port_down" $@
760 }
761
762 # The next two functions automagically bring up and down
763 # port that are attached to a bridge or similar.
764 # The problem that is tried to overcome here is that there
765 # are ports which exist all the time (like ethernet ports)
766 # and therefore do not dispatch a hotplug event when
767 # port_create is called.
768
769 function zone_port_start() {
770 local zone="${1}"
771 local port="${2}"
772
773 if zone_is_active "${zone}"; then
774 if device_exists "${port}"; then
775 zone_port_up "${zone}" "${port}"
776 return ${?}
777 else
778 zone_port_create "${zone}" "${port}"
779 return ${?}
780 fi
781 fi
782
783 return ${EXIT_OK}
784 }
785
786 function zone_port_stop() {
787 local zone="${1}"
788 local port="${2}"
789
790 # Shut down the port if necessary
791 if zone_is_active "${zone}" && port_is_up "${port}"; then
792 zone_port_down "${zone}" "${port}"
793 fi
794
795 # Remove the port
796 zone_port_remove "${zone}" "${port}"
797 }
798
799 function zone_port_status() {
800 zone_port_cmd "port_status" $@
801 }
802
803 function zone_ports_cmd() {
804 local cmd="${1}"
805 assert isset cmd
806
807 local zone="${2}"
808 assert isset zone
809
810 shift 2
811
812 local hook="$(zone_get_hook "${zone}")"
813
814 local port
815 for port in $(zone_get_ports ${zone}); do
816 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" $@
817 done
818 }
819
820 function zone_ports_create() {
821 zone_ports_cmd "port_create" $@
822 }
823
824 function zone_ports_remove() {
825 zone_ports_cmd "port_remove" $@
826 }
827
828 function zone_ports_up() {
829 zone_ports_cmd "port_up" $@
830 }
831
832 function zone_ports_down() {
833 zone_ports_cmd "port_down" $@
834 }
835
836 function zone_ports_status() {
837 zone_ports_cmd "port_status" $@
838 }
839
840 function zone_configs_cmd() {
841 assert [ $# -ge 2 ]
842
843 local cmd="${1}"
844 local zone="${2}"
845 shift 2
846
847 assert zone_exists "${zone}"
848
849 local config
850 for config in $(zone_configs_list "${zone}"); do
851 local config_hook="$(zone_config_get_hook "${zone}" "${config}")"
852 assert isset config_hook
853
854 hook_config_exec "${config_hook}" "${cmd}" "${zone}" "${config}" $@
855 done
856 }
857
858 function zone_configs_up() {
859 zone_configs_cmd "up" $@
860 }
861
862 function zone_configs_down() {
863 zone_configs_cmd "down" $@
864 }
865
866 function zone_configs_status() {
867 zone_configs_cmd "status" $@
868 }
869
870 function zone_configs_list() {
871 local zone=${1}
872
873 local config
874 for config in $(zone_dir ${zone})/configs/*; do
875 [ -e "${config}" ] || continue
876
877 basename ${config}
878 done
879 }
880
881 function zone_config_get_hook() {
882 assert [ $# -eq 2 ]
883
884 local zone="${1}"
885 assert isset zone
886
887 local config="${2}"
888 assert isset config
889
890 local HOOK
891 zone_config_settings_read "${zone}" "${config}" \
892 --ignore-superfluous-settings HOOK
893
894 print "${HOOK}"
895 }
896
897 function zone_has_ip() {
898 device_has_ip $@
899 }
900
901 function zone_db() {
902 local zone=${1}
903 local action=${2}
904 shift 2
905
906 case "${action}" in
907 starting|started|stopping|stopped)
908 db_connection_update ${zone} ${action}
909 ;;
910 esac
911 }
912
913 function zone_is_up() {
914 local zone=${1}
915
916 device_is_up ${zone}
917 }
918
919 function zone_is_down() {
920 ! zone_is_up $@
921 }
922
923 function zone_get_supported_port_hooks() {
924 local zone=${1}
925
926 local hook=$(zone_get_hook ${zone})
927
928 hook_zone_ports_get_all ${hook}
929 }
930
931 function zone_get_supported_config_hooks() {
932 hook_config_get_all
933 }
934
935 function zone_file() {
936 local zone=${1}
937
938 assert isset zone
939
940 echo "$(zone_dir ${zone})/settings"
941 }
942
943 function zone_settings_read() {
944 local zone=${1}
945 assert isset zone
946 shift
947
948 local args
949 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
950 list_append args ${HOOK_SETTINGS}
951 else
952 list_append args $@
953 fi
954
955 # Save the HOOK variable.
956 local hook="${HOOK}"
957
958 settings_read "$(zone_file "${zone}")" ${args}
959
960 # Restore hook.
961 HOOK="${hook}"
962 }
963
964 function zone_settings_write() {
965 local zone="${1}"
966 assert isset zone
967
968 local args
969 if function_exists "hook_check_settings"; then
970 list_append args "--check=\"hook_check_settings\""
971 fi
972 list_append args ${HOOK_SETTINGS}
973
974 settings_write "$(zone_file ${zone})" ${args}
975 }
976
977 function zone_settings_set() {
978 local zone=${1}
979 shift
980 local args="$@"
981
982 assert isset zone
983
984 (
985 zone_settings_read ${zone}
986
987 for arg in ${args}; do
988 eval "${arg}"
989 done
990
991 zone_settings_write ${zone}
992 )
993 }
994
995 function zone_settings_get() {
996 local zone=${1}
997 local key=${2}
998
999 assert isset zone
1000 assert isset key
1001
1002 (
1003 zone_settings_read "${zone}" "${key}" \
1004 --ignore-superfluous-settings
1005
1006 echo "${!key}"
1007 )
1008 }
1009
1010 function zone_config_settings_read() {
1011 assert [ $# -ge 2 ]
1012
1013 local zone="${1}"
1014 local config="${2}"
1015 shift 2
1016
1017 local args
1018 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1019 list_append args ${HOOK_CONFIG_SETTINGS}
1020 else
1021 list_append args $@
1022 fi
1023
1024 local path="$(zone_dir "${zone}")/configs/${config}"
1025 settings_read "${path}" ${args}
1026 }
1027
1028 function zone_config_settings_write() {
1029 assert [ $# -ge 2 ]
1030
1031 local zone="${1}"
1032 local config="${2}"
1033 shift 2
1034
1035 local args
1036 if function_exists "hook_check_config_settings"; then
1037 list_append args "--check=\"hook_check_config_settings\""
1038 fi
1039 list_append args ${HOOK_CONFIG_SETTINGS}
1040
1041 local path="$(zone_dir "${zone}")/configs/${config}"
1042 settings_write "${path}" ${args}
1043 }
1044
1045 function zone_port_settings_read() {
1046 assert [ $# -ge 2 ]
1047
1048 local zone="${1}"
1049 local port="${2}"
1050 shift 2
1051
1052 local args
1053 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1054 list_append args ${HOOK_PORT_SETTINGS}
1055 else
1056 list_append args $@
1057 fi
1058
1059 local path="$(zone_dir "${zone}")/ports/${port}"
1060 settings_read "${path}" ${args}
1061 }
1062
1063 function zone_port_settings_write() {
1064 assert [ $# -ge 2 ]
1065
1066 local zone="${1}"
1067 local port="${2}"
1068 shift 2
1069
1070 local args
1071 if function_exists "hook_check_port_settings"; then
1072 list_append args "--check=\"hook_check_port_settings\""
1073 fi
1074 list_append args ${HOOK_PORT_SETTINGS}
1075
1076 local path="$(zone_dir "${zone}")/ports/${port}"
1077 settings_write "${path}" ${args}
1078 }
1079
1080 function zone_port_settings_remove() {
1081 assert [ $# -eq 2 ]
1082
1083 local zone="${1}"
1084 local port="${2}"
1085
1086 local path="$(zone_dir "${zone}")/ports/${port}"
1087 settings_remove "${path}"
1088 }