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_OK}" ]; then
247 zone_destroy
"${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 local hook
="$(zone_get_hook "${zone}")"
268 if [ -z "${hook}" ]; then
269 error
"Config file did not provide any hook."
273 if ! hook_zone_exists
${hook}; then
274 error
"Hook '${hook}' does not exist."
278 hook_zone_exec
${hook} edit
${zone} "$@"
287 assert zone_exists
"${zone}"
288 assert not zone_exists
"${name}"
290 # The zone must be shut down before, is then renamed and
291 # potentially brought up again
293 # Save if the zone is running right now
294 zone_is_active
"${zone}"
295 local zone_was_active
="${?}"
297 # Save if the zone is enabled (i.e. auto-start)
298 zone_is_enabled
"${zone}"
299 local zone_was_enabled
="${?}"
305 zone_disable
"${zone}"
307 # Rename the configuration files
308 mv -f "$(zone_dir "${zone}")" "$(zone_dir "${name}")"
310 # Enable the zone if it was enabled before
311 [ ${zone_was_enabled} -eq ${EXIT_TRUE} ] && zone_enable "${name}"
313 # Start the zone if it was up before
314 [ ${zone_was_active} -eq ${EXIT_TRUE} ] && zone_start "${name}"
316 log INFO
"Zone ${zone} was renamed to ${name}"
324 # Cannot delete a zone that does not exist
325 if ! zone_exists
"${zone}"; then
326 log ERROR
"Zone ${zone} does not exist"
330 log INFO
"Destroying zone ${zone}"
332 # Force the zone down.
333 zone_is_active
"${zone}" && zone_stop
"${zone}"
335 # Disable zone auto-start
336 zone_disable
"${zone}"
338 rm -rf "$(zone_dir "${zone}")"
345 if ! zone_exists
${zone}; then
346 error
"Zone '${zone}' does not exist."
350 local hook
="$(zone_get_hook "${zone}")"
351 if [ -z "${hook}" ]; then
352 error
"Config file did not provide any hook."
356 if ! hook_zone_exists
${hook}; then
357 error
"Hook '${hook}' does not exist."
361 zone_db
${zone} starting
363 hook_zone_exec
${hook} up
${zone} "$@"
365 zone_db
${zone} started
367 # Execute all triggers after the zone got up
368 triggers_execute_all
"up" ZONE
="${zone}"
375 if ! zone_exists
${zone}; then
376 error
"Zone '${zone}' does not exist."
380 local hook
="$(zone_get_hook "${zone}")"
381 if [ -z "${hook}" ]; then
382 error
"Config file did not provide any hook."
386 if ! hook_zone_exists
${hook}; then
387 error
"Hook '${hook}' does not exist."
391 zone_db
${zone} stopping
393 hook_zone_exec
${hook} down
${zone} "$@"
395 zone_db
${zone} stopped
397 # Execute all triggers after the zone went down
398 triggers_execute_all
"down" ZONE
="${zone}"
406 if ! zone_exists
"${zone}"; then
407 error
"Zone '${zone}' does not exist."
411 local hook
="$(zone_get_hook "${zone}")"
412 if [ -z "${hook}" ]; then
413 error
"Config file did not provide any hook."
417 if ! hook_zone_exists
"${hook}"; then
418 error
"Hook '${hook}' does not exist."
422 hook_zone_exec
"${hook}" "status" "${zone}" "$@"
431 assert zone_exists
"${zone}"
433 log INFO
"Identifying zone ${zone}"
438 for port
in $
(zone_get_ports
"${zone}"); do
439 # Identify all the ports
440 port_identify
"${port}" --background "$@"
442 # Save the PIDs of the subprocesses
443 list_append pids
"$(cmd_background_get_pid)"
446 # Wait until all port_identfy processes have finished
447 for pid
in ${pids}; do
448 cmd_background_result
"${pid}"
460 for port
in $
(zone_dir
${zone})/ports
/*; do
461 port
=$
(basename ${port})
463 if port_exists
${port}; then
469 zone_get_ports_num
() {
475 for port
in $
(zone_dir
"${zone}")/ports
/*; do
476 port
="$(basename "${port}")"
478 if port_exists
"${port}"; then
479 counter
=$
(( ${counter} + 1 ))
488 # Check, if the given port is configured
498 [ -e "$(zone_dir ${zone})/ports/${port}" ]
508 assert zone_exists
"${zone}"
512 zone_config_new
"${zone}" "$@"
515 # usually ${1} is a valid hid
519 # We convert the hid into an id
520 local id
=$
(zone_config_convert_hid_to_id
${zone} ${hid})
522 # If id isset the hid is valid and we can go on with the id
524 zone_config_destroy
"${zone}" "${id}" "$@"
526 # If we can't get a valid hid we check if we got a valid id
528 if zone_config_id_is_valid
${zone} ${hid}; then
529 zone_config_destroy
"${zone}" ${hid} "$@"
531 log ERROR
"${id} is not a valid id or hid"
536 zone_config_list
"${zone}" "$@"
539 # usually ${1} is a valid hid
544 local id
=$
(zone_config_convert_hid_to_id
${zone} ${hid})
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}" "$@"
550 # If we didn't get a valid hid we check if we got a valid id
552 if zone_config_id_is_valid
${zone} ${id} && [[ ${cmd} == "edit" ]]; then
554 zone_config_edit
"${zone}" "${id}" "$@"
556 # in ${hid} is saved the command after network zone ${zone} config
557 error
"Unrecognized argument: ${hid}"
558 cli_usage root-zone-config-subcommands
573 local hook
="$(zone_get_hook "${zone}")"
576 hook_zone_exec
"${hook}" "config_${cmd}" "${zone}" "$@"
583 # Create a new configuration, but exit when that was
585 zone_config_cmd
"new" "${zone}" "$@" ||
return ${?}
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}"
594 zone_config_destroy
() {
595 zone_config_cmd
"destroy" "$@"
599 zone_config_cmd
"edit" "$@"
603 # This function list in an nice way all configs of a zone
607 # Print a nice header
608 local format
="%-3s %-20s %-20s"
609 print
"${format}" "ID" "HOOK" "HID"
616 # Print for all config:
618 for config
in $
(zone_configs_list
"${zone}"); do
620 hook
=$
(zone_config_get_hook
"${zone}" "${config}")
621 hid
=$
(zone_config_get_hid
"${zone}" "${config}")
623 print
"${format}" "${id}" "${hook}" "${hid}"
628 zone_config_cmd
"show" "$@"
631 # Returns a list of all used ids for a zone
632 zone_config_list_ids
() {
639 for config
in $
(zone_configs_list
${zone}); do
640 list_append ids
"$(config_get_id_from_config ${config})"
646 # List all hids of a zone
647 zone_config_list_hids
() {
653 for config
in $
(zone_configs_list
${zone}); do
654 zone_config_get_hid
"${zone}" "${config}"
658 # get the hid from a given config
659 zone_config_get_hid
() {
665 local hook
="$(zone_config_get_hook "${zone}" "${config}")"
667 hook_exec
"config" "${hook}" "hid" "${zone}" "${config}"
670 # Checks if a hid is valid for a given zone
671 zone_config_hid_is_valid
() {
678 for _hid
in $
(zone_config_list_hids
"${zone}"); do
679 if [[ ${_hid} = ${hid} ]]; then
687 # This function converts a hid to a id
688 zone_config_convert_hid_to_id
() {
695 for config
in $
(zone_configs_list
${zone}); do
696 # Get hook from config
697 local hook
="$(zone_config_get_hook "${zone}" "${config}")"
699 if [[ "$(hook_exec "config
" "${hook}" "hid" "${zone}" "${config}")" == "${hid}" ]]; then
700 config_get_id_from_config "${config}"
712 echo " Type
: $
(zone_get_hook
${zone})"
719 for zone in $(zones_get "$@
"); do
726 for zone in $(zone_dir)/*; do
727 zone=$(basename ${zone})
728 zone_exists ${zone} || continue
734 zones_get_next_free() {
735 # This function return the next free zones.
736 # Example net0 upl0 upl1 are configured so the next free zones are:
740 for zone_name in ${VALID_ZONES}; do
744 local zone="${zone_name}${i}"
745 if ! zone_exists ${zone}; then
756 for zone in $(zones_get_all); do
757 zone_is_local ${zone} && echo "${zone}"
761 zones_get_nonlocal() {
763 for zone in $(zones_get_all); do
764 zone_is_nonlocal ${zone} && echo "${zone}"
774 while [ $# -gt 0 ]; do
789 if zone_name_is_valid ${1}; then
790 zones="${zones} ${1}"
792 warning "Unrecognized argument
'${1}'"
799 if [ -n "${zones}" ]; then
801 for zone in ${zones}; do
802 zone_exists ${zone} && echo "${zone}"
807 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
809 elif [ ${local} -eq 1 ]; then
811 elif [ ${remote} -eq 1 ]; then
820 for port in $(zone_dir ${zone})/ports/*; do
821 [ -e "${port}" ] || continue
823 echo $(basename ${port})
836 # Check if the port actually exists.
837 if ! port_exists "${port}"; then
838 error "Cannot attach port
'${port}' which does not exist
"
842 # Check if the port is already connected to this or any other zone.
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}'"
851 local hook="$
(zone_get_hook
"${zone}")"
854 # Make the port briefly flash if supported
855 if device_exists ${port}; then
856 port_identify "${port}" --background
859 hook_zone_exec "${hook}" "port_attach" "${zone}" "${port}" "$@
"
864 log INFO "${port} has been attached to
${zone}"
866 # Automatically connect the port
867 zone_port_start "${zone}" "${port}"
870 log CRITICAL "${port} could not be attached to
${zone}"
886 # Check if the port actually exists.
887 if ! port_exists "${port}"; then
888 error "Port
'${port}' does not exist
"
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}'"
898 local hook=$(zone_get_hook "${zone}")
901 hook_zone_exec "${hook}" "port_edit" "${zone}" "${port}" "$@
"
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}'"
919 local hook=$(zone_get_hook "${zone}")
922 # Make the port briefly flash if supported
923 port_identify "${port}" --background
925 hook_zone_exec "${hook}" "port_detach" "${zone}" "${port}" "$@
"
930 log INFO "${port} has been detached from
${zone}"
932 # Bring down the port if needed
933 zone_port_stop "${zone}" "${port}"
936 log CRITICAL "${port} could not be detached from
${zone}"
955 local hook="$
(zone_get_hook
"${zone}")"
958 # Dispatch command to hook
959 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" "$@
"
963 zone_port_cmd "port_create
" "$@
"
967 zone_port_cmd "port_remove
" "$@
"
971 zone_port_cmd "port_up
" "$@
"
975 zone_port_cmd "port_down
" "$@
"
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.
989 if zone_is_active "${zone}"; then
990 if device_exists "${port}"; then
991 zone_port_up "${zone}" "${port}"
994 zone_port_create "${zone}" "${port}"
1006 # Shut down the port if necessary
1007 if zone_is_active "${zone}" && port_is_up "${port}"; then
1008 zone_port_down "${zone}" "${port}"
1012 zone_port_remove "${zone}" "${port}"
1015 zone_port_status() {
1016 zone_port_cmd "port_status
" "$@
"
1028 local hook="$
(zone_get_hook
"${zone}")"
1031 for port in $(zone_get_ports ${zone}); do
1032 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" "$@
"
1036 zone_ports_create() {
1037 zone_ports_cmd "port_create
" "$@
"
1040 zone_ports_remove() {
1041 zone_ports_cmd "port_remove
" "$@
"
1045 zone_ports_cmd "port_up
" "$@
"
1049 zone_ports_cmd "port_down
" "$@
"
1052 zone_ports_status() {
1053 zone_ports_cmd "port_status
" "$@
"
1056 zone_configs_cmd() {
1063 assert zone_exists "${zone}"
1066 for config in $(zone_configs_list "${zone}"); do
1067 local config_hook="$
(zone_config_get_hook
"${zone}" "${config}")"
1068 assert isset config_hook
1070 hook_config_exec "${config_hook}" "${cmd}" "${zone}" "${config}" "$@
"
1075 zone_configs_cmd "up
" "$@
"
1078 zone_configs_down() {
1079 zone_configs_cmd "down
" "$@
"
1082 zone_configs_status() {
1083 zone_configs_cmd "status
" "$@
"
1086 zone_configs_list() {
1090 for config in $(zone_dir ${zone})/configs/*; do
1091 [ -e "${config}" ] || continue
1097 zone_config_get_new_id() {
1098 # This functions returns the next free id for a zone
1103 local zone_path=$(zone_dir ${zone})
1107 if [ ! -f ${zone_path}/configs/*.${i} ]; then
1115 zone_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.
1127 # The key should be local for this function
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
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
1145 return ${EXIT_FALSE}
1148 zone_config_get_hook
() {
1158 zone_config_settings_read
"${zone}" "${config}" \
1159 --ignore-superfluous-settings HOOK
1164 zone_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
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
1182 # If we get here the zone has no config with the given hook
1183 return ${EXIT_FALSE}
1186 zone_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
1194 local zone_path
=$
(zone_dir
${zone})
1196 [ -f ${zone_path}/configs
/*.
${id} ];
1199 # This function checks if a given hid is valid for a zone
1200 # Return True when yes and false when no
1201 zone_config_hid_is_valid
() {
1207 for _hid
in $
(zone_config_list_hids
${zone}); do
1208 if [[ ${_hid} == ${hid} ]]; then
1213 return ${EXIT_FALSE}
1216 zone_config_get_hook_from_id
() {
1217 # Returns the hook for a given id
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}"
1232 # If we get here the zone has no config with the given id
1233 return ${EXIT_ERROR}
1246 starting|started|stopping|stopped
)
1247 db_connection_update
${zone} ${action}
1255 device_is_up
${zone}
1262 zone_get_supported_port_hooks
() {
1265 local hook
=$
(zone_get_hook
${zone})
1267 hook_zone_ports_get_all
${hook}
1270 zone_get_supported_config_hooks
() {
1279 echo "$(zone_dir ${zone})/settings"
1282 zone_settings_read
() {
1288 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
1289 list_append args
${HOOK_SETTINGS}
1291 list_append args
"$@"
1294 # Save the HOOK variable.
1295 local hook
="${HOOK}"
1297 settings_read
"$(zone_file "${zone}")" ${args}
1303 zone_settings_write
() {
1308 if function_exists
"hook_check_settings"; then
1309 list_append args
"--check=\"hook_check_settings\""
1311 list_append args
${HOOK_SETTINGS}
1313 settings_write
"$(zone_file ${zone})" ${args}
1316 zone_settings_set
() {
1324 zone_settings_read
${zone}
1326 for arg
in ${args}; do
1330 zone_settings_write
${zone}
1334 zone_settings_get
() {
1342 zone_settings_read
"${zone}" "${key}" \
1343 --ignore-superfluous-settings
1349 zone_config_settings_read
() {
1357 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1358 list_append args
${HOOK_CONFIG_SETTINGS}
1360 list_append args
"$@"
1363 local path
="$(zone_dir "${zone}")/configs/${config}"
1364 settings_read
"${path}" ${args}
1367 zone_config_settings_write
() {
1375 id
=$
(zone_config_get_new_id
${zone})
1376 log DEBUG
"ID for the config is: ${id}"
1380 if function_exists
"hook_check_config_settings"; then
1381 list_append args
"--check=\"hook_check_config_settings\""
1383 list_append args
${HOOK_CONFIG_SETTINGS}
1385 local path
="$(zone_dir "${zone}")/configs/${hook}.${id}"
1386 settings_write "${path}" ${args}
1389 zone_config_settings_destroy() {
1390 # This function deletes the config file for a given zone and config
1395 local path="$
(zone_dir
"${zone}")/configs
/${config}"
1397 # Check if path is valid
1398 if [ ! -f ${path} ]; then
1399 log ERROR "Path
: '${path}' is not valid
"
1400 return ${EXIT_ERROR}
1403 log DEBUG "Deleting config
file ${path}"
1407 zone_port_settings_read() {
1415 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1416 list_append args ${HOOK_PORT_SETTINGS}
1418 list_append args "$@
"
1421 local path="$
(zone_dir
"${zone}")/ports
/${port}"
1422 settings_read "${path}" ${args}
1425 zone_port_settings_write() {
1433 if function_exists "hook_check_port_settings
"; then
1434 list_append args "--check=\"hook_check_port_settings
\""
1436 list_append args ${HOOK_PORT_SETTINGS}
1438 local path="$
(zone_dir
"${zone}")/ports
/${port}"
1439 settings_write "${path}" ${args}
1442 zone_port_settings_remove() {
1448 local path="$
(zone_dir
"${zone}")/ports
/${port}"
1449 settings_remove "${path}"
1453 # This function return the color of a zone
1457 color_read "zone
" ${name}
1460 zone_get_description_title() {
1464 description_title_read $(description_format_filename "zone
" "${name}")