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 ###############################################################################
26 [ -d "${NETWORK_ZONES_DIR}/${zone}" ]
33 for i
in ${VALID_ZONES}; do
34 match
="${match}|${i}[0-9]{1,5}"
37 echo "${match:1:${#match}}"
40 zone_name_is_valid
() {
43 # Don't accept empty strings.
44 [ -z "${zone}" ] && return ${EXIT_FALSE}
46 [[ ${zone} =~ $
(zone_match
) ]]
52 [[ "${zone:0:${#ZONE_LOCAL}}" = "${ZONE_LOCAL}" ]]
58 [[ "${zone:0:${#ZONE_NONLOCAL}}" = "${ZONE_NONLOCAL}" ]]
65 config_get_hook
"${NETWORK_ZONES_DIR}/${zone}/settings"
69 # This function will bring up the zone
70 # 'asynchronously' with help of systemd.
73 assert zone_exists
${zone}
75 service_start
"network@${zone}.service"
80 assert zone_exists
"${zone}"
82 # If the zone has already been started, we
83 # will reload it so the current configuration
85 if zone_is_active
"${zone}"; then
89 # If the zone is still down, but in auto-start mode,
91 elif zone_is_enabled
"${zone}"; then
96 # Otherwise, nothing will be done.
101 # This function will bring down the zone
102 # 'asynchronously' with help of systemd.
105 assert zone_exists
${zone}
107 service_stop
"network@${zone}.service"
112 assert zone_exists
"${zone}"
114 service_reload
"network@${zone}.service"
117 zone_hotplug_event
() {
121 hotplug_assert_in_hotplug_event
123 zone_cmd
"hotplug" "${zone}"
127 # This function will enable the zone
128 # with help of systemd.
131 assert zone_exists
"${zone}"
133 # Enable service for the zone
134 service_enable
"network@${zone}.service"
137 if [ ${ret} -eq ${EXIT_OK} ]; then
138 log INFO
"Auto-start enabled for zone ${zone}"
142 log ERROR
"Could not enable zone ${zone}: ${ret}"
147 # This function will disable the zone
148 # with help of systemd.
151 assert zone_exists
"${zone}"
153 # Disable service for the zone
154 service_disable
"network@${zone}.service"
157 if [ ${ret} -eq ${EXIT_OK} ]; then
158 log INFO
"Auto-start disabled for zone ${zone}"
162 log ERROR
"Could not disable zone ${zone}: ${ret}"
170 # Ask systemd if the zone is enabled.
171 if service_is_enabled
"network@${zone}.service"; then
182 if service_is_active
"network@${zone}.service"; then
189 zone_is_enabled_or_active
() {
193 zone_is_enabled
"${zone}" || zone_is_active
"${zone}"
204 local hook
="$(zone_get_hook ${zone})"
207 hook_exec zone
"${hook}" "${cmd}" "${zone}" "$@"
215 if ! zone_name_is_valid
${zone}; then
216 error
"Zone name '${zone}' is not valid."
220 if zone_exists
${zone}; then
221 error
"Zone '${zone}' does already exist."
225 if ! hook_zone_exists
${hook}; then
226 error
"Hook '${hook}' does not exist."
230 # Create directories for configs and ports
232 for what
in configs ports
; do
233 make_directory
"${NETWORK_ZONES_DIR}/${zone}/${what}"
236 hook_zone_exec
"${hook}" "new" "${zone}" "$@"
239 # Maybe the zone new hook did not exit correctly.
240 # If this is the case we remove the created zone immediately.
241 if [ "${ret}" != "${EXIT_OK}" ]; then
242 zone_destroy
"${zone}"
246 # Automatically enable zone.
247 zone_enable
"${zone}"
249 # Bring up the zone immediately after
257 if ! zone_exists
${zone}; then
258 error
"Zone '${zone}' does not exist."
262 local hook
="$(zone_get_hook "${zone}")"
263 if [ -z "${hook}" ]; then
264 error
"Config file did not provide any hook."
268 if ! hook_zone_exists
${hook}; then
269 error
"Hook '${hook}' does not exist."
273 hook_zone_exec
${hook} edit
${zone} "$@"
282 assert zone_exists
"${zone}"
283 assert not zone_exists
"${name}"
285 # The zone must be shut down before, is then renamed and
286 # potentially brought up again
288 # Save if the zone is running right now
289 zone_is_active
"${zone}"
290 local zone_was_active
="${?}"
292 # Save if the zone is enabled (i.e. auto-start)
293 zone_is_enabled
"${zone}"
294 local zone_was_enabled
="${?}"
300 zone_disable
"${zone}"
302 # Rename the configuration files
303 mv -f "${NETWORK_ZONES_DIR}/${zone}" "${NETWORK_ZONES_DIR}/${name}"
305 # Enable the zone if it was enabled before
306 [ ${zone_was_enabled} -eq ${EXIT_TRUE} ] && zone_enable "${name}"
308 # Start the zone if it was up before
309 [ ${zone_was_active} -eq ${EXIT_TRUE} ] && zone_start "${name}"
311 log INFO
"Zone ${zone} was renamed to ${name}"
319 # Cannot delete a zone that does not exist
320 if ! zone_exists
"${zone}"; then
321 log ERROR
"Zone ${zone} does not exist"
325 log INFO
"Destroying zone ${zone}"
327 # Force the zone down.
328 zone_is_active
"${zone}" && zone_stop
"${zone}"
330 # Disable zone auto-start
331 zone_disable
"${zone}"
333 rm -rf "${NETWORK_ZONES_DIR}/${zone}"
340 if ! zone_exists
${zone}; then
341 error
"Zone '${zone}' does not exist."
345 local hook
="$(zone_get_hook "${zone}")"
346 if [ -z "${hook}" ]; then
347 error
"Config file did not provide any hook."
351 if ! hook_zone_exists
${hook}; then
352 error
"Hook '${hook}' does not exist."
356 zone_db
${zone} starting
358 hook_zone_exec
${hook} up
${zone} "$@"
360 zone_db
${zone} started
362 # Execute all triggers after the zone got up
363 triggers_execute_all
"up" ZONE
="${zone}"
370 if ! zone_exists
${zone}; then
371 error
"Zone '${zone}' does not exist."
375 local hook
="$(zone_get_hook "${zone}")"
376 if [ -z "${hook}" ]; then
377 error
"Config file did not provide any hook."
381 if ! hook_zone_exists
${hook}; then
382 error
"Hook '${hook}' does not exist."
386 zone_db
${zone} stopping
388 hook_zone_exec
${hook} down
${zone} "$@"
390 zone_db
${zone} stopped
392 # Execute all triggers after the zone went down
393 triggers_execute_all
"down" ZONE
="${zone}"
401 if ! zone_exists
"${zone}"; then
402 error
"Zone '${zone}' does not exist."
406 local hook
="$(zone_get_hook "${zone}")"
407 if [ -z "${hook}" ]; then
408 error
"Config file did not provide any hook."
412 if ! hook_zone_exists
"${hook}"; then
413 error
"Hook '${hook}' does not exist."
417 hook_zone_exec
"${hook}" "status" "${zone}" "$@"
426 assert zone_exists
"${zone}"
428 log INFO
"Identifying zone ${zone}"
433 for port
in $
(zone_get_ports
"${zone}"); do
434 # Identify all the ports
435 port_identify
"${port}" --background "$@"
437 # Save the PIDs of the subprocesses
438 list_append pids
"$(cmd_background_get_pid)"
441 # Wait until all port_identfy processes have finished
442 for pid
in ${pids}; do
443 cmd_background_result
"${pid}"
455 for port
in $
(list_directory
"${NETWORK_ZONES_DIR}/${zone}/ports"); do
456 if port_exists
"${port}"; then
462 zone_get_ports_num
() {
468 for port
in $
(list_directory
"${NETWORK_ZONES_DIR}/${zone}/ports"); do
469 if port_exists
"${port}"; then
470 counter
=$
(( ${counter} + 1 ))
479 # Check, if the given port is configured
489 [ -e "${NETWORK_ZONES_DIR}/${zone}/ports/${port}" ]
499 assert zone_exists
"${zone}"
503 zone_config_new
"${zone}" "$@"
506 # usually ${1} is a valid hid
510 # We convert the hid into an id
511 local id
=$
(zone_config_convert_hid_to_id
${zone} ${hid})
513 # If id isset the hid is valid and we can go on with the id
515 zone_config_destroy
"${zone}" "${id}" "$@"
517 # If we can't get a valid hid we check if we got a valid id
519 if zone_config_id_is_valid
${zone} ${hid}; then
520 zone_config_destroy
"${zone}" ${hid} "$@"
522 log ERROR
"${id} is not a valid id or hid"
527 zone_config_list
"${zone}" "$@"
530 # usually ${1} is a valid hid
535 local id
=$
(zone_config_convert_hid_to_id
${zone} ${hid})
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}" "$@"
541 # If we didn't get a valid hid we check if we got a valid id
543 if zone_config_id_is_valid
${zone} ${id} && [[ ${cmd} == "edit" ]]; then
545 zone_config_edit
"${zone}" "${id}" "$@"
547 # in ${hid} is saved the command after network zone ${zone} config
548 error
"Unrecognized argument: ${hid}"
549 cli_usage root-zone-config-subcommands
564 local hook
="$(zone_get_hook "${zone}")"
567 hook_zone_exec
"${hook}" "config_${cmd}" "${zone}" "$@"
574 # Create a new configuration, but exit when that was
576 zone_config_cmd
"new" "${zone}" "$@" ||
return ${?}
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}"
585 zone_config_destroy
() {
586 zone_config_cmd
"destroy" "$@"
590 zone_config_cmd
"edit" "$@"
594 # This function list in an nice way all configs of a zone
598 # Print a nice header
599 local format
="%-3s %-20s %-20s"
600 print
"${format}" "ID" "HOOK" "HID"
607 # Print for all config:
609 for config
in $
(zone_configs_list
"${zone}"); do
611 hook
=$
(zone_config_get_hook
"${zone}" "${config}")
612 hid
=$
(zone_config_get_hid
"${zone}" "${config}")
614 print
"${format}" "${id}" "${hook}" "${hid}"
619 zone_config_cmd
"show" "$@"
622 # Returns a list of all used ids for a zone
623 zone_config_list_ids
() {
630 for config
in $
(zone_configs_list
${zone}); do
631 list_append ids
"$(config_get_id_from_config ${config})"
637 # List all hids of a zone
638 zone_config_list_hids
() {
644 for config
in $
(zone_configs_list
${zone}); do
645 zone_config_get_hid
"${zone}" "${config}"
649 # get the hid from a given config
650 zone_config_get_hid
() {
656 local hook
="$(zone_config_get_hook "${zone}" "${config}")"
658 hook_exec
"config" "${hook}" "hid" "${zone}" "${config}"
661 # Checks if a hid is valid for a given zone
662 zone_config_hid_is_valid
() {
669 for _hid
in $
(zone_config_list_hids
"${zone}"); do
670 if [[ ${_hid} = ${hid} ]]; then
678 # This function converts a hid to a id
679 zone_config_convert_hid_to_id
() {
686 for config
in $
(zone_configs_list
${zone}); do
687 # Get hook from config
688 local hook
="$(zone_config_get_hook "${zone}" "${config}")"
690 if [[ "$(hook_exec "config
" "${hook}" "hid" "${zone}" "${config}")" == "${hid}" ]]; then
691 config_get_id_from_config "${config}"
703 echo " Type
: $
(zone_get_hook
${zone})"
710 for zone in $(zones_get "$@
"); do
717 for zone in $(list_directory "${NETWORK_ZONES_DIR}"); do
718 if zone_exists ${zone}; then
724 zones_get_next_free() {
725 # This function return the next free zones.
726 # Example net0 upl0 upl1 are configured so the next free zones are:
730 for zone_name in ${VALID_ZONES}; do
734 local zone="${zone_name}${i}"
735 if ! zone_exists ${zone}; then
746 for zone in $(zones_get_all); do
747 zone_is_local ${zone} && echo "${zone}"
751 zones_get_nonlocal() {
753 for zone in $(zones_get_all); do
754 zone_is_nonlocal ${zone} && echo "${zone}"
764 while [ $# -gt 0 ]; do
779 if zone_name_is_valid ${1}; then
780 zones="${zones} ${1}"
782 warning "Unrecognized argument
'${1}'"
789 if [ -n "${zones}" ]; then
791 for zone in ${zones}; do
792 zone_exists ${zone} && echo "${zone}"
797 if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then
799 elif [ ${local} -eq 1 ]; then
801 elif [ ${remote} -eq 1 ]; then
809 list_directory "${NETWORK_ZONES_DIR}/${zone}/ports
"
821 # Check if the port actually exists.
822 if ! port_exists "${port}"; then
823 error "Cannot attach port
'${port}' which does not exist
"
827 # Check if the port is already connected to this or any other zone.
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}'"
836 local hook="$
(zone_get_hook
"${zone}")"
839 # Make the port briefly flash if supported
840 if device_exists ${port}; then
841 port_identify "${port}" --background
844 hook_zone_exec "${hook}" "port_attach" "${zone}" "${port}" "$@
"
849 log INFO "${port} has been attached to
${zone}"
851 # Automatically connect the port
852 zone_port_start "${zone}" "${port}"
855 log CRITICAL "${port} could not be attached to
${zone}"
871 # Check if the port actually exists.
872 if ! port_exists "${port}"; then
873 error "Port
'${port}' does not exist
"
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}'"
883 local hook=$(zone_get_hook "${zone}")
886 hook_zone_exec "${hook}" "port_edit" "${zone}" "${port}" "$@
"
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}'"
904 local hook=$(zone_get_hook "${zone}")
907 # Make the port briefly flash if supported
908 port_identify "${port}" --background
910 hook_zone_exec "${hook}" "port_detach" "${zone}" "${port}" "$@
"
915 log INFO "${port} has been detached from
${zone}"
917 # Bring down the port if needed
918 zone_port_stop "${zone}" "${port}"
921 log CRITICAL "${port} could not be detached from
${zone}"
940 local hook="$
(zone_get_hook
"${zone}")"
943 # Dispatch command to hook
944 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" "$@
"
948 zone_port_cmd "port_create
" "$@
"
952 zone_port_cmd "port_remove
" "$@
"
956 zone_port_cmd "port_up
" "$@
"
960 zone_port_cmd "port_down
" "$@
"
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.
974 if zone_is_active "${zone}"; then
975 if device_exists "${port}"; then
976 zone_port_up "${zone}" "${port}"
979 zone_port_create "${zone}" "${port}"
991 # Shut down the port if necessary
992 if zone_is_active "${zone}" && port_is_up "${port}"; then
993 zone_port_down "${zone}" "${port}"
997 zone_port_remove "${zone}" "${port}"
1000 zone_port_status() {
1001 zone_port_cmd "port_status
" "$@
"
1013 local hook="$
(zone_get_hook
"${zone}")"
1016 for port in $(zone_get_ports ${zone}); do
1017 hook_zone_exec "${hook}" "${cmd}" "${zone}" "${port}" "$@
"
1021 zone_ports_create() {
1022 zone_ports_cmd "port_create
" "$@
"
1025 zone_ports_remove() {
1026 zone_ports_cmd "port_remove
" "$@
"
1030 zone_ports_cmd "port_up
" "$@
"
1034 zone_ports_cmd "port_down
" "$@
"
1037 zone_ports_status() {
1038 zone_ports_cmd "port_status
" "$@
"
1041 zone_configs_cmd() {
1048 assert zone_exists "${zone}"
1051 for config in $(zone_configs_list "${zone}"); do
1052 local config_hook="$
(zone_config_get_hook
"${zone}" "${config}")"
1053 assert isset config_hook
1055 hook_config_exec "${config_hook}" "${cmd}" "${zone}" "${config}" "$@
"
1060 zone_configs_cmd "up
" "$@
"
1063 zone_configs_down() {
1064 zone_configs_cmd "down
" "$@
"
1067 zone_configs_status() {
1068 zone_configs_cmd "status
" "$@
"
1071 zone_configs_list() {
1074 list_directory "${NETWORK_ZONES_DIR}/${zone}/configs
"
1077 zone_config_get_new_id() {
1078 # This functions returns the next free id for a zone
1083 local zone_path="${NETWORK_ZONES_DIR}/${zone}"
1087 if [ ! -f ${zone_path}/configs/*.${i} ]; then
1095 zone_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.
1107 # The key should be local for this function
1111 for config in $(zone_configs_list ${zone}); do
1112 # Check if the config is from the given hook, when not continue
1113 if [[ $(zone_config_get_hook "${zone}" "${config}") != ${hook} ]]; then
1116 # Get the value of the key for a given function
1117 zone_config_settings_read
"${zone}" "${config}" \
1118 --ignore-superfluous-settings "${key}"
1119 # Check if the value of the config and the passed value are eqal
1120 if [[ "${value}" == "${!key}" ]]; then
1125 return ${EXIT_FALSE}
1128 zone_config_get_hook
() {
1138 zone_config_settings_read
"${zone}" "${config}" \
1139 --ignore-superfluous-settings HOOK
1144 zone_config_hook_is_configured
() {
1145 # Checks if a zone has already at least one config with the given hook.
1146 # Returns True when yes and False when no
1153 for config
in $
(zone_configs_list
"${zone}"); do
1154 local config_hook
="$(zone_config_get_hook "${zone}" "${config}")"
1155 assert isset config_hook
1156 if [[ ${hook} == ${config_hook} ]]; then
1162 # If we get here the zone has no config with the given hook
1163 return ${EXIT_FALSE}
1166 zone_config_id_is_valid
() {
1167 # This function checks if a given id is valid for a zone
1168 # Return True when yes and false when no
1174 local zone_path
="${NETWORK_ZONES_DIR}/${zone}"
1176 [ -f ${zone_path}/configs
/*.
${id} ];
1179 # This function checks if a given hid is valid for a zone
1180 # Return True when yes and false when no
1181 zone_config_hid_is_valid
() {
1187 for _hid
in $
(zone_config_list_hids
${zone}); do
1188 if [[ ${_hid} == ${hid} ]]; then
1193 return ${EXIT_FALSE}
1196 zone_config_get_hook_from_id
() {
1197 # Returns the hook for a given id
1203 for config
in $
(zone_configs_list
"${zone}"); do
1204 if [[ ${config} == *.
${id} ]]; then
1205 local config_hook
="$(zone_config_get_hook "${zone}" "${config}")"
1206 assert isset config_hook
1207 print
"${config_hook}"
1212 # If we get here the zone has no config with the given id
1213 return ${EXIT_ERROR}
1226 starting|started|stopping|stopped
)
1227 db_connection_update
${zone} ${action}
1235 device_is_up
${zone}
1242 zone_get_supported_port_hooks
() {
1245 local hook
=$
(zone_get_hook
${zone})
1247 hook_zone_ports_get_all
${hook}
1250 zone_get_supported_config_hooks
() {
1254 zone_settings_read
() {
1260 if [ $# -eq 0 ] && [ -n "${HOOK_SETTINGS}" ]; then
1261 list_append args
${HOOK_SETTINGS}
1263 list_append args
"$@"
1266 # Save the HOOK variable.
1267 local hook
="${HOOK}"
1269 settings_read
"${NETWORK_ZONES_DIR}/${zone}/settings" ${args}
1275 zone_settings_write() {
1280 if function_exists "hook_check_settings
"; then
1281 list_append args "--check=\"hook_check_settings
\""
1283 list_append args ${HOOK_SETTINGS}
1285 settings_write "${NETWORK_ZONES_DIR}/${zone}/settings" ${args}
1288 zone_settings_set
() {
1296 zone_settings_read
${zone}
1298 for arg
in ${args}; do
1302 zone_settings_write
${zone}
1306 zone_settings_get
() {
1314 zone_settings_read
"${zone}" "${key}" \
1315 --ignore-superfluous-settings
1321 zone_config_settings_read
() {
1329 if [ $# -eq 0 ] && [ -n "${HOOK_CONFIG_SETTINGS}" ]; then
1330 list_append args
${HOOK_CONFIG_SETTINGS}
1332 list_append args
"$@"
1335 local path
="${NETWORK_ZONES_DIR}/${zone}/configs/${config}"
1336 settings_read
"${path}" ${args}
1339 zone_config_settings_write
() {
1347 id
=$
(zone_config_get_new_id
${zone})
1348 log DEBUG
"ID for the config is: ${id}"
1352 if function_exists
"hook_check_config_settings"; then
1353 list_append args
"--check=\"hook_check_config_settings\""
1355 list_append args
${HOOK_CONFIG_SETTINGS}
1357 local path
="${NETWORK_ZONES_DIR}/${zone}/configs/${hook}.${id}"
1358 settings_write
"${path}" ${args}
1361 zone_config_settings_destroy
() {
1362 # This function deletes the config file for a given zone and config
1367 local path
="${NETWORK_ZONES_DIR}/${zone}/configs/${config}"
1369 # Check if path is valid
1370 if [ ! -f ${path} ]; then
1371 log ERROR
"Path: '${path}' is not valid"
1372 return ${EXIT_ERROR}
1375 log DEBUG
"Deleting config file ${path}"
1379 zone_port_settings_read
() {
1387 if [ $# -eq 0 ] && [ -n "${HOOK_PORT_SETTINGS}" ]; then
1388 list_append args
${HOOK_PORT_SETTINGS}
1390 list_append args
"$@"
1393 local path
="${NETWORK_ZONES_DIR}/${zone}/ports/${port}"
1394 settings_read
"${path}" ${args}
1397 zone_port_settings_write
() {
1405 if function_exists
"hook_check_port_settings"; then
1406 list_append args
"--check=\"hook_check_port_settings\""
1408 list_append args
${HOOK_PORT_SETTINGS}
1410 local path
="${NETWORK_ZONES_DIR}/${zone}/ports/${port}"
1411 settings_write
"${path}" ${args}
1414 zone_port_settings_remove
() {
1420 local path
="${NETWORK_ZONES_DIR}/${zone}/ports/${port}"
1421 settings_remove
"${path}"
1425 # This function return the color of a zone
1429 color_read
"zone" ${name}
1432 zone_get_description_title
() {
1436 description_title_read $
(description_format_filename
"zone" "${name}")