2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2010 Michael Tremer & Christian Schmidt #
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. #
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. #
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/>. #
20 ###############################################################################
25 echo "${NETWORK_ZONE_DIR}/zones/${zone}"
32 [ -d "$(zone_dir ${zone})" ]
39 for i
in ${VALID_ZONES}; do
40 match
="${match}|${i}[0-9]{1,5}"
43 echo "${match:1:${#match}}"
46 zone_name_is_valid
() {
49 # Don't accept empty strings.
50 [ -z "${zone}" ] && return ${EXIT_FALSE}
52 [[ ${zone} =~ $
(zone_match
) ]]
58 [[ "${zone:0:${#ZONE_LOCAL}}" = "${ZONE_LOCAL}" ]]
64 [[ "${zone:0:${#ZONE_NONLOCAL}}" = "${ZONE_NONLOCAL}" ]]
71 config_get_hook $
(zone_dir
${zone})/settings
75 # This function will bring up the zone
76 # 'asynchronously' with help of systemd.
79 assert zone_exists
${zone}
81 service_start
"network@${zone}.service"
86 assert zone_exists
"${zone}"
88 # If the zone has already been started, we
89 # will reload it so the current configuration
91 if zone_is_active
"${zone}"; then
95 # If the zone is still down, but in auto-start mode,
97 elif zone_is_enabled
"${zone}"; then
102 # Otherwise, nothing will be done.
107 # This function will bring down the zone
108 # 'asynchronously' with help of systemd.
111 assert zone_exists
${zone}
113 service_stop
"network@${zone}.service"
118 assert zone_exists
"${zone}"
120 service_reload
"network@${zone}.service"
123 zone_hotplug_event
() {
127 hotplug_assert_in_hotplug_event
129 zone_cmd
"hotplug" "${zone}"
133 # This function will enable the zone
134 # with help of systemd.
137 assert zone_exists
"${zone}"
139 # Enable service for the zone
140 service_enable
"network@${zone}.service"
143 if [ ${ret} -eq ${EXIT_OK} ]; then
144 log INFO
"Auto-start enabled for zone ${zone}"
148 log ERROR
"Could not enable zone ${zone}: ${ret}"
153 # This function will disable the zone
154 # with help of systemd.
157 assert zone_exists
"${zone}"
159 # Disable service for the zone
160 service_disable
"network@${zone}.service"
163 if [ ${ret} -eq ${EXIT_OK} ]; then
164 log INFO
"Auto-start disabled for zone ${zone}"
168 log ERROR
"Could not disable zone ${zone}: ${ret}"
176 # Ask systemd if the zone is enabled.
177 if service_is_enabled
"network@${zone}.service"; then
188 if service_is_active
"network@${zone}.service"; then
195 zone_is_enabled_or_active
() {
199 zone_is_enabled
"${zone}" || zone_is_active
"${zone}"
210 local hook
="$(zone_get_hook ${zone})"
213 hook_exec zone
"${hook}" "${cmd}" "${zone}" $@
221 if ! zone_name_is_valid
${zone}; then
222 error
"Zone name '${zone}' is not valid."
226 if zone_exists
${zone}; then
227 error
"Zone '${zone}' does already exist."
231 if ! hook_zone_exists
${hook}; then
232 error
"Hook '${hook}' does not exist."
236 mkdir
-p $
(zone_dir
${zone})
238 # Create directories for configs and ports
239 mkdir
-p $
(zone_dir
${zone})/{configs
,ports
}
241 hook_zone_exec
"${hook}" "new" "${zone}" $@
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}"
251 # Automatically enable zone.
252 zone_enable
"${zone}"
254 # Bring up the zone immediately after
262 if ! zone_exists
${zone}; then
263 error
"Zone '${zone}' does not exist."
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."
273 local hook
="$(zone_get_hook "${zone}")"
274 if [ -z "${hook}" ]; then
275 error
"Config file did not provide any hook."
279 if ! hook_zone_exists
${hook}; then
280 error
"Hook '${hook}' does not exist."
284 hook_zone_exec
${hook} edit
${zone} $@
293 assert zone_exists
"${zone}"
294 assert not zone_has_destroy_tag
"${zone}"
295 assert not zone_exists
"${name}"
297 # The zone must be shut down before, is then renamed and
298 # potentially brought up again
300 # Save if the zone is running right now
301 zone_is_active
"${zone}"
302 local zone_was_active
="${?}"
304 # Save if the zone is enabled (i.e. auto-start)
305 zone_is_enabled
"${zone}"
306 local zone_was_enabled
="${?}"
312 zone_disable
"${zone}"
314 # Rename the configuration files
315 mv -f "$(zone_dir "${zone}")" "$(zone_dir "${name}")"
317 # Enable the zone if it was enabled before
318 [ ${zone_was_enabled} -eq ${EXIT_TRUE} ] && zone_enable "${name}"
320 # Start the zone if it was up before
321 [ ${zone_was_active} -eq ${EXIT_TRUE} ] && zone_start "${name}"
323 log INFO
"Zone ${zone} was renamed to ${name}"
330 assert zone_exists
"${zone}"
332 # Make the zone for removal.
333 touch "$(zone_dir "${zone}")/.destroy"
335 log INFO
"Zone '${zone}' has been tagged for removal."
338 zone_has_destroy_tag
() {
340 assert zone_exists
"${zone}"
342 [ -e "$(zone_dir "${zone}")/.destroy" ]
345 # This function will remove the given zone
346 # RIGHT NOW. Use zone_destroy to remove it
347 # at the next status change.
350 assert zone_exists
"${zone}"
352 log INFO
"Removing zone '${zone}' right now."
354 # Force the zone down.
355 zone_is_active
"${zone}" && zone_stop
"${zone}"
358 zone_disable
"${zone}"
360 rm -rf "$(zone_dir "${zone}")"
367 if ! zone_exists
${zone}; then
368 error
"Zone '${zone}' does not exist."
372 # Check if a zone has got the remove tag.
373 if zone_has_destroy_tag
${zone}; then
374 error
"Cannot bring up any zone which is to be removed."
378 local hook
="$(zone_get_hook "${zone}")"
379 if [ -z "${hook}" ]; then
380 error
"Config file did not provide any hook."
384 if ! hook_zone_exists
${hook}; then
385 error
"Hook '${hook}' does not exist."
389 zone_db
${zone} starting
391 hook_zone_exec
${hook} up
${zone} $@
393 zone_db
${zone} started
395 # Execute all triggers after the zone got up
396 triggers_execute_all
"up" ZONE
="${zone}"
403 if ! zone_exists
${zone}; then
404 error
"Zone '${zone}' does not exist."
408 local hook
="$(zone_get_hook "${zone}")"
409 if [ -z "${hook}" ]; then
410 error
"Config file did not provide any hook."
414 if ! hook_zone_exists
${hook}; then
415 error
"Hook '${hook}' does not exist."
419 zone_db
${zone} stopping
421 hook_zone_exec
${hook} down
${zone} $@
423 zone_db
${zone} stopped
425 # Execute all triggers after the zone went down
426 triggers_execute_all
"down" ZONE
="${zone}"
428 # Remove the zone, if it has got a remove tag.
429 if zone_has_destroy_tag
"${zone}"; then
430 zone_destroy_now
"${zone}"
439 if ! zone_exists
"${zone}"; then
440 error
"Zone '${zone}' does not exist."
444 local hook
="$(zone_get_hook "${zone}")"
445 if [ -z "${hook}" ]; then
446 error
"Config file did not provide any hook."
450 if ! hook_zone_exists
"${hook}"; then
451 error
"Hook '${hook}' does not exist."
455 hook_zone_exec
"${hook}" "status" "${zone}" "$@"
457 # Show that the zone it to be removed soon.
458 if zone_has_destroy_tag
${zone}; then
459 warning
"This zone is tagged for removal."
469 assert zone_exists
"${zone}"
471 log INFO
"Identifying zone ${zone}"
476 for port
in $
(zone_get_ports
"${zone}"); do
477 # Identify all the ports
478 port_identify
"${port}" --background $@
480 # Save the PIDs of the subprocesses
481 list_append pids
"$(cmd_background_get_pid)"
484 # Wait until all port_identfy processes have finished
485 for pid
in ${pids}; do
486 cmd_background_result
"${pid}"
498 for port
in $
(zone_dir
${zone})/ports
/*; do
499 port
=$
(basename ${port})
501 if port_exists
${port}; then
507 zone_get_ports_num
() {
513 for port
in $
(zone_dir
"${zone}")/ports
/*; do
514 port
="$(basename "${port}")"
516 if port_exists
"${port}"; then
517 counter
=$
(( ${counter} + 1 ))
526 # Check, if the given port is configured
536 [ -e "$(zone_dir ${zone})/ports/${port}" ]
546 assert zone_exists
"${zone}"
550 zone_config_new
"${zone}" "$@"
554 if zone_config_id_is_valid
${zone} ${id}; then
555 zone_config_destroy
"${zone}" "$@"
557 log ERROR
"${id} is not a valid id"
561 zone_config_list
"${zone}" "$@"
564 # Check is we get a valid id
565 # TODO This could be also a valid hid
568 if zone_config_id_is_valid
${zone} ${id} && [[ ${1} == "edit" ]]; then
570 zone_config_edit
"${zone}" "${id}" "$@"
572 error
"Unrecognized argument: ${cmd}"
573 cli_usage root-zone-config-subcommands
587 local hook
="$(zone_get_hook "${zone}")"
590 hook_zone_exec
"${hook}" "config_${cmd}" "${zone}" "$@"
597 # Create a new configuration, but exit when that was
599 zone_config_cmd
"new" "${zone}" "$@" ||
return ${?}
601 # If the config could be created, we will try to bring
602 # it up if the zone is up, too.
603 if zone_is_up
"${zone}"; then
604 zone_configs_up
"${zone}"
608 zone_config_destroy
() {
609 zone_config_cmd
"destroy" "$@"
613 zone_config_cmd
"edit" "$@"
617 # This function list in an nice way all configs of a zone
621 # Print a nice header
622 local format
="%-3s %-20s"
623 print
"${format}" "ID" "HOOK"
629 # Print for all config:
631 # TODO: Add hids here
632 for config
in $
(zone_configs_list
"${zone}"); do
634 hook
=$
(zone_config_get_hook
"${zone}" "${config}")
636 print
"${format}" "${id}" "${hook}"
641 zone_config_cmd
"show" "$@"
648 echo " Type: $(zone_get_hook ${zone})"
655 for zone
in $
(zones_get $@
); do
662 for zone
in $
(zone_dir
)/*; do
663 zone
=$
(basename ${zone})
664 zone_exists
${zone} ||
continue
670 zones_get_next_free
() {
671 # This function return the next free zones.
672 # Example net0 upl0 upl1 are configured so the next free zones are:
676 for zone_name
in ${VALID_ZONES}; do
680 local zone
="${zone_name}${i}"
681 if ! zone_exists
${zone}; then
692 for zone
in $
(zones_get_all
); do
693 zone_is_local
${zone} && echo "${zone}"
697 zones_get_nonlocal
() {
699 for zone
in $
(zones_get_all
); do
700 zone_is_nonlocal
${zone} && echo "${zone}"
710 while [ $# -gt 0 ]; do
725 if zone_name_is_valid
${1}; then
726 zones
="${zones} ${1}"
728 warning
"Unrecognized argument '${1}'"
735 if [ -n "${zones}" ]; then
737 for zone
in ${zones}; do
738 zone_exists
${zone} && echo "${zone}"
743 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
745 elif [ ${local} -eq 1 ]; then
747 elif [ ${remote} -eq 1 ]; then
756 for port
in $
(zone_dir
${zone})/ports
/*; do
757 [ -e "${port}" ] ||
continue
759 echo $
(basename ${port})
772 # Check if the port actually exists.
773 if ! port_exists
"${port}"; then
774 error
"Cannot attach port '${port}' which does not exist"
778 # Check if the port is already connected to this or any other zone.
780 for z
in $
(zones_get_all
); do
781 if zone_has_port
"${z}" "${port}"; then
782 error
"Port '${port}' is already attached to zone '${z}'"
787 local hook
="$(zone_get_hook "${zone}")"
790 # Make the port briefly flash if supported
791 if device_exists
${port}; then
792 port_identify
"${port}" --background
795 hook_zone_exec
"${hook}" "port_attach" "${zone}" "${port}" "$@"
800 log INFO
"${port} has been attached to ${zone}"
802 # Automatically connect the port
803 zone_port_start
"${zone}" "${port}"
806 log CRITICAL
"${port} could not be attached to ${zone}"
822 # Check if the port actually exists.
823 if ! port_exists
"${port}"; then
824 error
"Port '${port}' does not exist"
828 # Check if the zone actually has this port.
829 if ! zone_has_port
"${zone}" "${port}"; then
830 error
"Port '${port}' is not attached to zone '${zone}'"
834 local hook
=$
(zone_get_hook
"${zone}")
837 hook_zone_exec
"${hook}" "port_edit" "${zone}" "${port}" "$@"
849 # Check if the zone actually has this port.
850 if ! zone_has_port
"${zone}" "${port}"; then
851 error
"Port '${port}' is not attached to zone '${zone}'"
855 local hook
=$
(zone_get_hook
"${zone}")
858 # Make the port briefly flash if supported
859 port_identify
"${port}" --background
861 hook_zone_exec
"${hook}" "port_detach" "${zone}" "${port}" "$@"
866 log INFO
"${port} has been detached from ${zone}"
868 # Bring down the port if needed
869 zone_port_stop
"${zone}" "${port}"
872 log CRITICAL
"${port} could not be detached from ${zone}"
891 local hook
="$(zone_get_hook "${zone}")"
894 # Dispatch command to hook
895 hook_zone_exec
"${hook}" "${cmd}" "${zone}" "${port}" $@
899 zone_port_cmd
"port_create" $@
903 zone_port_cmd
"port_remove" $@
907 zone_port_cmd
"port_up" $@
911 zone_port_cmd
"port_down" $@
914 # The next two functions automagically bring up and down
915 # port that are attached to a bridge or similar.
916 # The problem that is tried to overcome here is that there
917 # are ports which exist all the time (like ethernet ports)
918 # and therefore do not dispatch a hotplug event when
919 # port_create is called.
925 if zone_is_active
"${zone}"; then
926 if device_exists
"${port}"; then
927 zone_port_up
"${zone}" "${port}"
930 zone_port_create
"${zone}" "${port}"
942 # Shut down the port if necessary
943 if zone_is_active
"${zone}" && port_is_up
"${port}"; then
944 zone_port_down
"${zone}" "${port}"
948 zone_port_remove
"${zone}" "${port}"
952 zone_port_cmd
"port_status" $@
964 local hook
="$(zone_get_hook "${zone}")"
967 for port
in $
(zone_get_ports
${zone}); do
968 hook_zone_exec
"${hook}" "${cmd}" "${zone}" "${port}" $@
972 zone_ports_create
() {
973 zone_ports_cmd
"port_create" $@
976 zone_ports_remove
() {
977 zone_ports_cmd
"port_remove" $@
981 zone_ports_cmd
"port_up" $@
985 zone_ports_cmd
"port_down" $@
988 zone_ports_status
() {
989 zone_ports_cmd
"port_status" $@
999 assert zone_exists
"${zone}"
1002 for config
in $
(zone_configs_list
"${zone}"); do
1003 local config_hook
="$(zone_config_get_hook "${zone}" "${config}")"
1004 assert isset config_hook
1006 hook_config_exec
"${config_hook}" "${cmd}" "${zone}" "${config}" $@
1011 zone_configs_cmd
"up" $@
1014 zone_configs_down
() {
1015 zone_configs_cmd
"down" $@
1018 zone_configs_status
() {
1019 zone_configs_cmd
"status" $@
1022 zone_configs_list
() {
1026 for config
in $
(zone_dir
${zone})/configs
/*; do
1027 [ -e "${config}" ] ||
continue
1033 zone_config_get_new_id
() {
1034 # This functions returns the next free id for a zone
1039 local zone_path
=$
(zone_dir
${zone})
1043 if [ ! -f ${zone_path}/configs
/*.
${i} ]; then
1051 zone_config_get_hook
() {
1061 zone_config_settings_read
"${zone}" "${config}" \
1062 --ignore-superfluous-settings HOOK
1067 zone_config_hook_is_configured
() {
1068 # Checks if a zone has already at least one config with the given hook.
1069 # Returns True when yes and False when no
1076 for config
in $
(zone_configs_list
"${zone}"); do
1077 local config_hook
="$(zone_config_get_hook "${zone}" "${config}")"
1078 assert isset config_hook
1079 if [[ ${hook} == ${config_hook} ]]; then
1085 # If we get here the zone has no config with the given hook
1086 return ${EXIT_FALSE}
1089 zone_config_id_is_valid
() {
1090 # This function checks if a given id is valid for a zone
1091 # Return True when yes and false when no
1097 local zone_path
=$
(zone_dir
${zone})
1099 [ -f ${zone_path}/configs
/*.
${id} ];
1102 zone_config_get_hook_from_id
() {
1103 # Returns the hook for a given id
1109 for config
in $
(zone_configs_list
"${zone}"); do
1110 if [[ ${config} == *.
${id} ]]; then
1111 local config_hook
="$(zone_config_get_hook "${zone}" "${config}")"
1112 assert isset config_hook
1113 print
"${config_hook}"
1118 # If we get here the zone has no config with the given id
1119 return ${EXIT_ERROR}
1132 starting|started|stopping|stopped
)
1133 db_connection_update
${zone} ${action}
1141 device_is_up
${zone}
1148 zone_get_supported_port_hooks
() {
1151 local hook
=$
(zone_get_hook
${zone})
1153 hook_zone_ports_get_all
${hook}
1156 zone_get_supported_config_hooks
() {
1165 echo "$(zone_dir ${zone})/settings"
1168 zone_settings_read
() {
1174 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
1175 list_append args
${HOOK_SETTINGS}
1180 # Save the HOOK variable.
1181 local hook
="${HOOK}"
1183 settings_read
"$(zone_file "${zone}")" ${args}
1189 zone_settings_write
() {
1194 if function_exists
"hook_check_settings"; then
1195 list_append args
"--check=\"hook_check_settings\""
1197 list_append args
${HOOK_SETTINGS}
1199 settings_write
"$(zone_file ${zone})" ${args}
1202 zone_settings_set
() {
1210 zone_settings_read
${zone}
1212 for arg
in ${args}; do
1216 zone_settings_write
${zone}
1220 zone_settings_get
() {
1228 zone_settings_read
"${zone}" "${key}" \
1229 --ignore-superfluous-settings
1235 zone_config_settings_read
() {
1243 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1244 list_append args
${HOOK_CONFIG_SETTINGS}
1249 local path
="$(zone_dir "${zone}")/configs/${config}"
1250 settings_read
"${path}" ${args}
1253 zone_config_settings_write
() {
1261 id
=$
(zone_config_get_new_id
${zone})
1262 log DEBUG
"ID for the config is: ${id}"
1266 if function_exists
"hook_check_config_settings"; then
1267 list_append args
"--check=\"hook_check_config_settings\""
1269 list_append args
${HOOK_CONFIG_SETTINGS}
1271 local path
="$(zone_dir "${zone}")/configs/${hook}.${id}"
1272 settings_write "${path}" ${args}
1275 zone_port_settings_read() {
1283 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1284 list_append args ${HOOK_PORT_SETTINGS}
1289 local path="$
(zone_dir
"${zone}")/ports
/${port}"
1290 settings_read "${path}" ${args}
1293 zone_port_settings_write() {
1301 if function_exists "hook_check_port_settings
"; then
1302 list_append args "--check=\"hook_check_port_settings
\""
1304 list_append args ${HOOK_PORT_SETTINGS}
1306 local path="$
(zone_dir
"${zone}")/ports
/${port}"
1307 settings_write "${path}" ${args}
1310 zone_port_settings_remove() {
1316 local path="$
(zone_dir
"${zone}")/ports
/${port}"
1317 settings_remove "${path}"
1321 # This function return the color of a zone
1325 color_read "zone
" ${name}
1328 zone_get_description_title() {
1332 description_title_read $(description_format_filename "zone
" "${name}")