aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick McLean <patrick.mclean@sony.com>2020-05-08 19:21:40 -0700
committerPatrick McLean <patrick.mclean@sony.com>2020-05-08 19:22:21 -0700
commit4fd0650ed9ef4cec5477038fcfb2e59db2cf2b93 (patch)
treee0fd3ad21aca19aa977835e2ff9f81966cd21f6e
parentiptables.eselect: new module (diff)
downloadeselect-extern.tar.gz
eselect-extern.tar.bz2
eselect-extern.zip
modules/iptables.eselect: Complete rewrite, solve issues in bug #721578extern
Signed-off-by: Patrick McLean <patrick.mclean@sony.com>
-rw-r--r--modules/iptables.eselect320
1 files changed, 214 insertions, 106 deletions
diff --git a/modules/iptables.eselect b/modules/iptables.eselect
index f94b25c..e3e5906 100644
--- a/modules/iptables.eselect
+++ b/modules/iptables.eselect
@@ -2,43 +2,128 @@
# Copyright 2005-2020 Gentoo Authors
# Distributed under the terms of the GNU GPL version 2 or later
-DESCRIPTION="Manage the iptables and ip6tables symlink"
-AUTHOR="chris@christopherpritchard.co.uk"
+inherit package-manager
+
+DESCRIPTION="Manage the iptables/arptables/ebtables symlinks"
MAINTAINER="base-system@gentoo.org"
-VERSION="20200319"
+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"
+ [arptables-restore]="arptables-legacy-restore"
+ [arptables-save]="arptables-legacy-save"
+)
+
+EBTABLES_TARGETS=(
+ "ebtables-legacy"
+ "xtables-nft-multi"
+)
+declare -A EBTABLES_SYMLINKS=(
+ [ebtables]="ebtables-legacy"
+ [ebtables-restore]="ebtables-legacy-restore"
+ [ebtables-save]="ebtables-legacy-save"
+)
-IPTABLES_TARGETS=("iptables" "iptables-restore" "iptables-save")
-IP6TABLES_TARGETS=("ip6tables" "ip6tables-restore" "ip6tables-save")
+# get which module is running
+get_module() {
+ local module
+ module="${BASH_SOURCE[0]##*/}"
-# find a list of xtables symlink targets
+ printf -- '%s\n' "${module%.eselect}"
+}
+
+# find a list of symlink targets for the current module
find_targets() {
- local f
- for f in "${EROOT}"/sbin/xtables-*-multi; do
- [[ -f ${f} ]] && basename "${f}"
- done
+ 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
}
-# remove the iptables symlink
-remove_symlinks() {
- local ipt
- for ipt in "${IPTABLES_TARGETS[@]}"; do
- rm -f "${EROOT}/sbin/${ipt}" &>/dev/null
- done
- if [[ -n ${ipv6} && -n ${ipv6_remove} ]]; then
- local ip6t
- for ip6t in "${IP6TABLES_TARGETS[@]}"; do
- rm -f "${EROOT}/sbin/${ip6t}" &>/dev/null
- done
- fi
+# 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 iptables symlink
+# 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)"
+ readarray -t targets < <(find_targets)
target=${targets[$((target-1))]}
fi
@@ -46,130 +131,153 @@ set_symlinks() {
die -q "Target \"${target}\" doesn't appear to be valid!"
fi
- local ipt
- for ipt in "${IPTABLES_TARGETS[@]}"; do
- ln -s "${target}" "${EROOT}/sbin/${ipt}"
- done
+ # 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}")"
- if [[ -n ${ipv6} ]]; then
- local ip6t
- for ip6t in "${IP6TABLES_TARGETS[@]}"; do
- ln -s "${target}" "${EROOT}/sbin/${ip6t}"
- done
- fi
+ 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() {
- echo "Show the current iptables symlink"
+ printf -- 'Show the current %s symlink\n' "$(get_module)"
}
do_show() {
- local ipv6
- if [[ -d ${EROOT}/var/lib/ip6tables ]]; then
- ipv6=1
- fi
- write_list_start "Current iptables symlinks:"
- local ipt all_unset=1
- for ipt in "${IPTABLES_TARGETS[@]}"; do
- if [[ -L ${EROOT}/sbin/${ipt} ]]; then
- local ipta
- ipta=$(canonicalise "${EROOT}/sbin/${ipt}")
- write_kv_list_entry "${ipt}" "${ipta%/}"
+ 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
- else
- write_kv_list_entry "${ipt}" "(unset)"
+ elif [[ ! -f ${symlink_path} ]]; then
+ write_kv_list_entry "${symlink}" "(unset)"
fi
done
- if [[ ${ipv6} -eq 1 ]]; then
- write_list_start "Current ip6tables symlinks:"
- local ip6t
- for ip6t in "${IP6TABLES_TARGETS[@]}"; do
- if [[ -L ${EROOT}/sbin/${ip6t} ]]; then
- local ipta
- ipta=$(canonicalise "${EROOT}/sbin/${ip6t}")
- write_kv_list_entry "${ip6t}" "${ipta%/}"
- all_unset=0
- else
- write_kv_list_entry "${ip6t}" "(unset)"
- fi
- done
- fi
+
return "${all_unset}"
}
### list action ###
describe_list() {
- echo "List available iptables symlink targets"
+ printf -- 'List available %s symlink targets\n' "$(get_module)"
}
do_list() {
- local ipv6
- local -a targets
- readarray -t targets <<< "$(find_targets)"
- if [[ -L ${EROOT}/var/lib/ip6tables ]]; then
- ipv6=1
- fi
- write_list_start "Available iptables symlink targets:"
- local i
- for (( i = 0; i < ${#targets[@]}; i++ )); do
- # highlight the target where the symlink is pointing to
- [[ ${targets[i]} = \
- $(basename "$(canonicalise "${EROOT}/sbin/iptables")") ]] \
- && targets[i]=$(highlight_marker "${targets[i]}")
+ 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[@]}"
+
+ write_numbered_list -m "(none found)" "${targets_output[@]}"
}
### set action ###
describe_set() {
- echo "Set a new iptables symlink target"
-}
-
-describe_set_parameters() {
- echo "[--ipv6] <target>"
+ printf "Set a new $(get_module) symlink target\\n"
}
describe_set_options() {
- echo "--ipv6: Forces creation of ip6tables symlinks"
- echo "target : Target name or number (from 'list' action)"
+ printf -- "target : Target name or number (from 'list' action)\\n"
}
do_set() {
- local ipv6 ipv6_remove
- if [[ ${1} == "--ipv6" ]]; then
- ipv6=1
- shift
- fi
local target="${1}"
[[ -z ${target} ]] && die -q "You didn't tell me what to set the symlink to"
- [[ ${#} -gt 2 ]] && die -q "Too many parameters"
+ [[ ${#} -gt 1 ]] && die -q "Too many parameters"
- if [[ -d ${EROOT}/var/lib/ip6tables ]]; then
- ipv6=1
- [[ -L ${EROOT}/sbin/ip6tables ]] && ipv6_remove=1
- fi
- if [[ -L ${EROOT}/sbin/iptables ]]; then
- # existing symlink
- remove_symlinks || die -q "Couldn't remove existing symlink"
- set_symlinks "${target}" || die -q "Couldn't set a new symlink"
- elif [[ -e ${EROOT}/sbin/iptables ]]; then
- # we have something strange
- die -q "${EROOT}/sbin/iptables exists but is not a symlink"
- else
- set_symlinks "${target}" || die -q "Couldn't set a new symlink"
- fi
+ set_symlinks "${target}" || die -q "Couldn't set symlinks"
}
### unset action ###
describe_unset() {
- echo "Unset iptables symlink targets"
+ printf -- 'Unset %s symlink targets\n' "$(get_module)"
}
do_unset() {
- remove_symlinks
+ 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}
}