summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/iptables.eselect')
-rw-r--r--src/iptables.eselect281
1 files changed, 281 insertions, 0 deletions
diff --git a/src/iptables.eselect b/src/iptables.eselect
new file mode 100644
index 0000000..7a62722
--- /dev/null
+++ b/src/iptables.eselect
@@ -0,0 +1,281 @@
+# -*-eselect-*- vim: ft=eselect
+# Copyright 2005-2021 Gentoo Authors
+# Distributed under the terms of the GNU GPL version 2 or later
+
+inherit package-manager
+
+DESCRIPTION="Manage the iptables/arptables/ebtables symlinks"
+MAINTAINER="base-system@gentoo.org"
+VERSION="20200508"
+
+# a simple list of symlinks does for iptables
+IPTABLES_SYMLINKS=(
+ "iptables-xml"
+ "iptables" "iptables-restore" "iptables-save"
+)
+IP6TABLES_SYMLINKS=(
+ "ip6tables" "ip6tables-restore" "ip6tables-save"
+)
+
+# for arptables and ebtables we map names to legacy targets
+ARPTABLES_TARGETS=(
+ "arptables-legacy"
+ "xtables-nft-multi"
+)
+declare -A ARPTABLES_SYMLINKS=(
+ [arptables]="arptables-legacy"
+)
+
+EBTABLES_TARGETS=(
+ "ebtables-legacy"
+ "xtables-nft-multi"
+)
+declare -A EBTABLES_SYMLINKS=(
+ [ebtables]="ebtables-legacy"
+ [ebtables-restore]="ebtables-legacy-restore"
+ [ebtables-save]="ebtables-legacy-save"
+)
+
+# get which module is running
+get_module() {
+ local module
+ module="${BASH_SOURCE[0]##*/}"
+
+ printf -- '%s\n' "${module%.eselect}"
+}
+
+# find a list of symlink targets for the current module
+find_targets() {
+ local module target
+
+ module="$(get_module)"
+ case "${module}" in
+ iptables)
+ for target in "${EROOT}"/sbin/xtables-*-multi; do
+ [[ -x ${target} ]] && printf -- '%s\n' "${target##*/}"
+ done
+ ;;
+ arptables)
+ for target in "${ARPTABLES_TARGETS[@]}"; do
+ [[ -x ${EROOT}/sbin/${target} ]] && printf -- '%s\n' "${target}"
+ done
+ ;;
+ ebtables)
+ for target in "${EBTABLES_TARGETS[@]}"; do
+ [[ -x ${EROOT}/sbin/${target} ]] && printf -- '%s\n' "${target}"
+ done
+ ;;
+ *) die "Invalid module name ${module}"
+ esac
+}
+
+# get the list of symlinks for the current module
+get_symlinks_list() {
+ local module
+ module="$(get_module)"
+
+ case "${module}" in
+ iptables)
+ printf -- '%s\n' "${IPTABLES_SYMLINKS[@]}"
+
+ if [[ ${1} == -a ]] || has_version 'net-firewall/iptables[ipv6]'
+ then
+ printf -- '%s\n' "${IP6TABLES_SYMLINKS[@]}"
+ fi
+ ;;
+ arptables) printf -- '%s\n' "${!ARPTABLES_SYMLINKS[@]}";;
+ ebtables) printf -- '%s\n' "${!EBTABLES_SYMLINKS[@]}";;
+ *) die "Invalid module name ${module}"
+ esac
+}
+
+# get the symlink target given a symlink name and the target implementation
+get_symlink_target() {
+ local link="${1}" target="${2}" module
+ module="$(get_module)"
+
+ case "${module}" in
+ iptables) printf -- '%s\n' "${target}";;
+ arptables)
+ if [[ ${target} == *-legacy ]]; then
+ printf -- '%s\n' "${ARPTABLES_SYMLINKS[${link}]}"
+ else
+ printf -- '%s\n' "${target}"
+ fi
+ ;;
+ ebtables)
+ if [[ ${target} == *-legacy ]]; then
+ printf -- '%s\n' "${EBTABLES_SYMLINKS[${link}]}"
+ else
+ printf -- '%s\n' "${target}"
+ fi
+ ;;
+ *) die "Invalid module name ${module}"
+ esac
+}
+
+# set the symlinks for the current target
+set_symlinks() {
+ local target="${1}"
+ local retval=0
+
+ if is_number "${target}" && [[ ${target} -ge 1 ]]; then
+ local -a targets
+ readarray -t targets < <(find_targets)
+ target=${targets[$((target-1))]}
+ fi
+
+ if [[ -z ${target} || ! -f ${EROOT}/sbin/${target} ]]; then
+ die -q "Target \"${target}\" doesn't appear to be valid!"
+ fi
+
+ # create an array of symlinks to be created, then create them
+ # in a separate pass, it's done this way in an attempt to be atomic
+ # either all symlinks get updated, or none
+ local -a symlinks_list
+ readarray -t symlinks_list < <(get_symlinks_list)
+
+ local symlink
+ local -A do_symlinks
+ for symlink in "${symlinks_list[@]}"; do
+ local symlink_path="${EROOT}/sbin/${symlink}"
+
+ if [[ -L ${symlink_path} || ! -e ${symlink_path} ]]; then
+ do_symlinks["${symlink_path}"]="$(get_symlink_target "${symlink}" "${target}")"
+
+ else
+ die -q "Could not create symlink at ${symlink_path}:" \
+ "path exits and is not a symlink"
+ fi
+ done
+
+ for symlink in "${!do_symlinks[@]}"; do
+ if ! ln -sfn "${do_symlinks["${symlink}"]}" "${symlink}"; then
+ write_error_message "Failed to create symlink at ${symlink}"
+ retval=1
+ fi
+ done
+
+ return "${retval}"
+}
+
+### show action ###
+
+describe_show() {
+ printf -- 'Show the current %s symlink\n' "$(get_module)"
+}
+
+do_show() {
+ local -a symlinks_list
+ readarray -t symlinks_list < <(get_symlinks_list)
+
+ local all_unset=1 symlink
+ write_list_start "Current $(get_module) symlinks:"
+ for symlink in "${symlinks_list[@]}"; do
+ symlink_path="${EROOT}/sbin/${symlink}"
+
+ if [[ -L ${symlink_path} ]]; then
+ local symlink_target
+ symlink_target=$(canonicalise "${symlink_path}")
+ write_kv_list_entry "${symlink}" "${symlink_target%/}"
+ all_unset=0
+ elif [[ ! -f ${symlink_path} ]]; then
+ write_kv_list_entry "${symlink}" "(unset)"
+ fi
+ done
+
+ return "${all_unset}"
+}
+### list action ###
+
+describe_list() {
+ printf -- 'List available %s symlink targets\n' "$(get_module)"
+}
+
+do_list() {
+ local module
+ module="$(get_module)"
+
+ local -a targets_list symlinks_list
+ readarray -t targets_list < <(find_targets)
+ readarray -t symlinks_list < <(get_symlinks_list)
+
+ local -a targets_output
+
+ write_list_start "Available ${module} symlink targets:"
+ local symlink current_target
+ for symlink in "${symlinks_list[@]}"; do
+ local symlink_path="${EROOT}/sbin/${symlink}"
+ local target
+ for target in "${targets_list[@]}"; do
+ local symlink_target resolved_target
+ symlink_target="$(get_symlink_target "${symlink}" "${target}")"
+ resolved_target="$(basename "$(canonicalise "${symlink_path}")")"
+
+ if [[ ${resolved_target} == "${symlink_target}" ]]; then
+ if [[ -z ${current_target} ]]; then
+ current_target="${target}"
+ break
+ elif [[ ${current_target} != "${target}" ]]; then
+ write_warning_msg "Target mismatch"
+ unset current_target
+ break 2
+ fi
+ fi
+ done
+ done
+ for target in "${targets_list[@]}"; do
+ if [[ ${target} == "${current_target}" ]]; then
+ targets_output+=("$(highlight_marker "${target}")")
+ else
+ targets_output+=("${target}")
+ fi
+ done
+
+ write_numbered_list -m "(none found)" "${targets_output[@]}"
+}
+
+### set action ###
+
+describe_set() {
+ printf "Set a new $(get_module) symlink target\\n"
+}
+
+describe_set_options() {
+ printf -- "target : Target name or number (from 'list' action)\\n"
+}
+
+do_set() {
+ local target="${1}"
+
+ [[ -z ${target} ]] && die -q "You didn't tell me what to set the symlink to"
+ [[ ${#} -gt 1 ]] && die -q "Too many parameters"
+
+ set_symlinks "${target}" || die -q "Couldn't set symlinks"
+}
+
+### unset action ###
+
+describe_unset() {
+ printf -- 'Unset %s symlink targets\n' "$(get_module)"
+}
+
+do_unset() {
+ local retval=0
+
+ local -a symlinks_list
+ readarray -t symlinks_list < <(get_symlinks_list -a)
+
+ local symlink
+ for symlink in "${symlinks_list[@]}"; do
+ local symlink_path="${EROOT}/sbin/${symlink}"
+ if [[ -L ${symlink_path} ]]; then
+ unlink "${symlink_path}" || retval=${?}
+ elif [[ -e ${symlink_path} ]]; then
+ write_error_msg "Not removing non-symlink \"${symlink_path}\""
+ retval=1
+ fi
+ done
+
+ return ${retval}
+}