# #
###############################################################################
+HOOK_COMMANDS_CONFIG="hook_create hook_down hook_status hook_up"
+
+HOOK_COMMANDS_PORT="hook_create hook_down hook_hotplug hook_hotplug_rename \
+ hook_info hook_status hook_up"
+
+HOOK_COMMANDS_ZONE="hook_add hook_create hook_discover hook_down hook_edit hook_help \
+ hook_info hook_remove hook_status hook_up \
+ \
+ hook_config_create hook_config_edit hook_config_remove hook_config_show \
+ \
+ hook_port hook_port_add hook_port_edit hook_port_remove hook_port_show \
+ hook_port_status hook_port_up hook_port_down \
+ \
+ hook_ppp_ip_pre_up hook_ppp_ipv4_down hook_ppp_ipv4_up \
+ hook_ipv6_down hook_ipv6_up hook_ppp_write_config"
+
function hook_dir() {
local type=${1}
echo "${NETWORK_HOOKS_DIR}${type}"
}
+NETWORK_HOOKS_DIR_ZONES="$(hook_dir zone)"
function hook_exists() {
local type=${1}
assert isset type
assert isset hook
- local hook_dir=$(hook_dir ${type})
-
- [ -d "${hook_dir}/${hook}" ] && return ${EXIT_ERROR}
+ # Add the path prefix.
+ hook="$(hook_dir ${type})/${hook}"
- [ -x "${hook_dir}/${hook}" ]
+ [ ! -d "${hook}" ] && [ -x "${hook}" ]
}
function hook_exec() {
- local type=${1}
- local hook=${2}
- shift 2
-
+ local type="${1}"
assert isset type
+
+ local hook="${2}"
assert isset hook
- if ! hook_exists ${type} ${hook}; then
- error "Hook '${hook}' does not exist."
- return ${EXIT_ERROR}
- fi
+ local cmd="${3}"
+ assert isset cmd
+
+ assert hook_exists "${type}" "${hook}"
+ shift 3
+
+ # Complete the hook command by prepending "hook_"
+ local hook_cmd="hook_${cmd}"
+
+ # Check if the hook action is valid.
+ local valid_commands
+ case "${type}" in
+ "config")
+ valid_commands="${HOOK_COMMANDS_CONFIG}"
+ ;;
+ "port")
+ valid_commands="${HOOK_COMMANDS_PORT}"
+ ;;
+ "zone")
+ valid_commands="${HOOK_COMMANDS_ZONE}"
+ ;;
+ esac
+ isset valid_commands && assert list_match "${hook_cmd}" ${valid_commands}
+
+ local hook_path="$(hook_dir ${type})/${hook}"
+
+ # For performance reasons, all hooks are executed
+ # in a subshell and so will inherit the currently
+ # running environment.
+ (
+ # Set the name of the hook.
+ HOOK=$(basename ${hook})
+
+ # Source the code of the hook.
+ source "${hook_path}"
+
+ # Make sure HOOK is still properly set.
+ assert isset HOOK
+
+ # Execute the requested command.
+ cmd "${hook_cmd}" "$@"
+ )
+ local ret=$?
- exec_cmd $(hook_dir ${type})/${hook} $@
+ case "${ret}" in
+ ${EXIT_COMMAND_NOT_FOUND})
+ log ERROR "Hook command not implemented: ${hook_command} ($@)"
+ exit ${EXIT_COMMAND_NOT_FOUND}
+ ;;
+ ${EXIT_ERROR_ASSERT})
+ log ERROR "Hook exited with an assertion error."
+ exit ${EXIT_ERROR_ASSERT}
+ ;;
+ esac
+
+ return ${ret}
}
function config_get_hook() {
)
}
-## Wrappers around the hook functions for zones
-
function hook_zone_exists() {
hook_exists zone $@
}
local hook_zone=${1}
local hook_port=${2}
- hook_zone_exists ${hook_zone} || return ${EXIT_ERROR}
-
- [ -x "$(hook_dir zone)/${hook_zone}.ports/${hook_port}" ]
+ hook_exists zone "${hook_zone}.ports/${hook_port}"
}
function hook_zone_config_exists() {
local hook_zone=${1}
local hook_config=${2}
- hook_zone_exists ${hook_zone} || return ${EXIT_ERROR}
-
- [ -x "$(hook_dir zone)/${hook_zone}.configs/${hook_config}" ]
+ hook_exists zone "${hook_zone}.configs/${hook_config}"
}
function hook_zone_has_ports() {
local hook=${1}
- [ -d "$(hook_dir zone)/${hook}.ports" ]
-}
-
-function hook_zone_port_exists() {
- : # XXX WANTED
+ [ -d "${NETWORK_HOOKS_DIR_ZONES}/${hook}.ports" ]
}
function hook_zone_has_configs() {
local hook=${1}
- [ -d "$(hook_dir zone)/${hook}.configs" ]
+ [ -d "${NETWORK_HOOKS_DIR_ZONES}/${hook}.configs" ]
}
function hook_zone_exec() {
local hook_port=${2}
shift 2
- if ! hook_exists zone ${hook_zone}; then
- error "Hook '${hook_zone}' does not exist."
- return ${EXIT_ERROR}
- fi
-
- if ! hook_zone_port_exists ${hook_zone} ${hook_port}; then
- error "Port hook '${hook_port}' does not exist."
- return ${EXIT_ERROR}
- fi
-
- exec_cmd $(hook_dir zone)/${hook_zone}.ports/${hook_port} $@
+ hook_zone_exec "${hook_zone}.ports/${hook_port}" $@
}
function hook_zone_config_exec() {
local hook_zone=${1}
- local hook_config=${2}
+ local hook_port=${2}
shift 2
- assert isset hook_zone
- assert isset hook_config
-
- if ! hook_zone_exists ${hook_zone}; then
- error "Hook '${hook_zone}' does not exist."
- return ${EXIT_ERROR}
- fi
-
- if ! hook_zone_config_exists ${hook_zone} ${hook_config}; then
- error "Config hook '${hook_config}' does not exist."
- return ${EXIT_ERROR}
- fi
-
- exec_cmd $(hook_dir zone)/${hook_zone}.configs/${hook_config} $@
+ hook_zone_exec "${hook_zone}.configs/${hook_port}" $@
}
function hook_zone_get_all() {