summaryrefslogtreecommitdiffstats
path: root/utils/ipset_bash_completion
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ipset_bash_completion')
-rw-r--r--utils/ipset_bash_completion/README.md64
-rw-r--r--utils/ipset_bash_completion/ipset1507
2 files changed, 782 insertions, 789 deletions
diff --git a/utils/ipset_bash_completion/README.md b/utils/ipset_bash_completion/README.md
index ce5c47e..ecfd6b9 100644
--- a/utils/ipset_bash_completion/README.md
+++ b/utils/ipset_bash_completion/README.md
@@ -33,14 +33,57 @@ icmp[6] types and interface names when adding, deleting or testing elements.
- Complete on filenames if the current option requires it.
- Complete variable names and command substitution.
- Do not complete if an invalid combination of options is used.
-- Do not complete if an invalid value of an option argument is detected.
+- Optionally do not complete if an invalid value of an option argument is detected.
- Environment variables allow to modify completion behaviour.
Installation
============
-Put it into ~/.bash_completion or /etc/bash_completion.d/.
+Quote from bash-completion README:
+
+ Install it in one of the directories pointed to by
+ bash-completion's pkgconfig file variables. There are two
+ alternatives: the recommended one is 'completionsdir' (get it with
+ "pkg-config --variable=completionsdir bash-completion") from which
+ completions are loaded on demand based on invoked commands' names,
+ so be sure to name your completion file accordingly, and to include
+ for example symbolic links in case the file provides completions
+ for more than one command. The other one which is present for
+ backwards compatibility reasons is 'compatdir' (get it with
+ "pkg-config --variable=compatdir bash-completion") from which files
+ are loaded when bash_completion is loaded.
+
+ For packages using GNU autotools the installation can be handled
+ for example like this in configure.ac:
+
+ PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
+ bashcompdir="${sysconfdir}/bash_completion.d")
+ AC_SUBST(bashcompdir)
+
+ ...accompanied by this in Makefile.am:
+
+ bashcompdir = @bashcompdir@
+ dist_bashcomp_DATA = # completion files go here
+
+ For cmake we ship the bash-completion-config.cmake and
+ bash-completion-config-version.cmake files. Example usage:
+
+ find_package(bash-completion)
+ if(BASH_COMPLETION_FOUND)
+ message(STATUS
+ "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+ else()
+ set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d")
+ message (STATUS
+ "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+ endif()
+
+ install(FILES your-completion-file DESTINATION
+ ${BASH_COMPLETION_COMPLETIONSDIR})
+
+For backwards compatibility it is still possible
+to put it into ~/.bash_completion or /etc/bash_completion.d/.
Tip:
To make tab completion more handsome put the following into either
@@ -113,6 +156,7 @@ which will be used for hostname completion.
For all *net* type of sets and the hash:ip,mark set type, if hostname completion is attempted,
if the environment variable **_IPSET_COMP_NETWORKS** is set to a non-empty value,
networks are retrieved from /etc/networks.
+Means these two commands disable it: `_IPSET_COMP_NETWORKS=` or `_IPSET_COMP_NETWORKS=""`
Also a list of ip addresses can be supplied using the environment variable
**_IPSET_IPLIST_FILE**. Which should point to a file containing an ip address per line.
@@ -139,13 +183,15 @@ the list of possible completions (this is the default).
---
-When adding elements to a **bitmap:ip,mac** type of set,
-the environment variable **_IPSET_MACLIST_FILE** will be queried
+When completing on MAC addresses (bitmap:ip,mac, hash:mac type of set),
+the environment variable **_IPSET_MAC_COMPL_MODE** is queried to decide how to complete.
+If set to 'file' the variable **_IPSET_MACLIST_FILE** will be queried
for a file containing a list of mac addresses.
The file should contain one mac address per line.
Empty lines and comments (also after the address) are supported.
-If the variable is unset mac addresses are fetched from arp cache,
-/etc/ethers and the output of `ip link show`.
+If the variable **_IPSET_MAC_COMPL_MODE** is set to 'system' mac addresses are fetched
+from arp cache, /etc/ethers and the output of `ip link show`.
+If the variable is unset or set to 'both' (default) both methods are used).
---
@@ -168,8 +214,8 @@ In that case it is recommended to disable input validation (see below).
---
-If the environment variable **_IPSET_VALIDATE_INPUT** is set to a non empty value
-validation of users input is disabled.
+If the environment variable **_IPSET_VALIDATE_INPUT** is defined and set to a non empty value
+validation of users input is enabled.
---
@@ -183,7 +229,7 @@ Compatibility
Compatible with ipset versions 6+.
-Tested with ipset v6.20.1.
+Tested with ipset v6.24, v6.27.
bash v4+ is required.
diff --git a/utils/ipset_bash_completion/ipset b/utils/ipset_bash_completion/ipset
index b6d94c2..d258be2 100644
--- a/utils/ipset_bash_completion/ipset
+++ b/utils/ipset_bash_completion/ipset
@@ -7,7 +7,7 @@
# https://sourceforge.net/projects/ipset-bashcompl
# -----------------------------------------------------------------
-# Copyright (C) 2013-2014 AllKind (AllKind@fastest.cc)
+# Copyright (C) 2013-2016 Mart Frauenlob aka AllKind (AllKind@fastest.cc)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
# -----------------------------------------------------------------
# Compatible with ipset versions: 6+
# Tested with ipset versions:
-# 6.22
+# 6.24, 6.27
# -----------------------------------------------------------------
# Requirements:
#
@@ -33,6 +33,7 @@
#
# The bash completion package version 2.0 or greater is recommended.
# http://bash-completion.alioth.debian.org/
+# Older version are not supported.
#
# If the package is not available, things might not be so reliable.
# Also the colon (if there) is removed from COMP_WORDBREAKS.
@@ -40,13 +41,54 @@
# if they don't take care of it themselves.
#
# -----------------------------------------------------------------
-# Installation:
+# Installation (quote from bash-completion README):
#
-# Put it into ~/.bash_completion or /etc/bash_completion.d/
+# Install it in one of the directories pointed to by
+# bash-completion's pkgconfig file variables. There are two
+# alternatives: the recommended one is 'completionsdir' (get it with
+# "pkg-config --variable=completionsdir bash-completion") from which
+# completions are loaded on demand based on invoked commands' names,
+# so be sure to name your completion file accordingly, and to include
+# for example symbolic links in case the file provides completions
+# for more than one command. The other one which is present for
+# backwards compatibility reasons is 'compatdir' (get it with
+# "pkg-config --variable=compatdir bash-completion") from which files
+# are loaded when bash_completion is loaded.
+#
+# For packages using GNU autotools the installation can be handled
+# for example like this in configure.ac:
+#
+# PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
+# bashcompdir="${sysconfdir}/bash_completion.d")
+# AC_SUBST(bashcompdir)
+#
+# ...accompanied by this in Makefile.am:
+#
+# bashcompdir = @bashcompdir@
+# dist_bashcomp_DATA = # completion files go here
+#
+# For cmake we ship the bash-completion-config.cmake and
+# bash-completion-config-version.cmake files. Example usage:
+#
+# find_package(bash-completion)
+# if(BASH_COMPLETION_FOUND)
+# message(STATUS
+# "Using bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+# else()
+# set (BASH_COMPLETION_COMPLETIONSDIR "/etc/bash_completion.d")
+# message (STATUS
+# "Using fallback bash completion dir ${BASH_COMPLETION_COMPLETIONSDIR}")
+# endif()
+#
+# install(FILES your-completion-file DESTINATION
+# ${BASH_COMPLETION_COMPLETIONSDIR})
+#
+# For backwards compatibility it is still possible to put it into
+# ~/.bash_completion or /etc/bash_completion.d/.
#
# -----------------------------------------------------------------
#
-# Version 2.6
+# Version 2.9.2
#
# -----------------------------------------------------------------
@@ -56,14 +98,9 @@ shopt -s extglob
# Functions
# -----------------------------------------------------------------
-_ipset_colon_ltrim() {
-((got_bashcompl)) || return 0
-__ltrim_colon_completions "$1"
-}
-
_ipset_is_set() {
local -i idx
-((${#arr_sets[@]})) || arr_sets=( $(ipset list -n) )
+((${#arr_sets[@]})) || arr_sets=( $( ( "${words[0]}" list -n ) 2>/dev/null ) )
for idx in ${!arr_sets[@]}; do
if [[ ${arr_sets[idx]} = $1 ]]; then
return 0
@@ -76,34 +113,32 @@ _ipset_get_set_type() {
local n d
while read n d; do
[[ $n = Type: ]] && printf '%s\n' $d && break
-done < <(ipset -t list "$1" 2>/dev/null)
+done < <( ( "${words[0]}" -t list "$1" ) 2>/dev/null)
}
_ipset_set_has_option() {
while read -r; do
[[ $REPLY = Header:*$1* ]] && return 0
-done < <(ipset -t list "$2")
+done < <( ( "${words[0]}" -t list "$2" ) 2>/dev/null)
return 1
}
_ipset_get_supported_types() {
((${#arr_types[@]})) && return
-local -i i=0
+local -i i=0 x
while read -r; do
[[ $REPLY = "Supported set types:"* ]] && ((!i)) && i=1 && continue
((i)) || continue
if [[ $REPLY = *:* ]]; then
set -- $REPLY
- arr_types+=("$1")
+ for x in ${!arr_types[@]}; do # check if already registered
+ if [[ $1 = ${arr_types[x]} ]]; then
+ continue 2
+ fi
+ done
+ arr_types+=("$1") # register type
fi
-done < <(ipset help)
-for i in ${!arr_types[@]}; do # remove dupe entries
- for ((x=i+1; x < ${#arr_types[@]}; x++)); do
- if [[ ${arr_types[i]} = ${arr_types[x]} ]]; then
- unset arr_types[x]
- fi
- done
-done
+done < <( ( "${words[0]}" help ) 2>/dev/null )
}
_ipset_get_members() {
@@ -120,7 +155,7 @@ while read -r; do
else
arr_members+=("$REPLY")
fi
-done < <(ipset list "$1" 2>/dev/null)
+done < <( ( "${words[0]}" list "$1" ) 2>/dev/null)
}
_ipset_get_set_family() {
@@ -128,7 +163,7 @@ while read -r; do
[[ $REPLY = Header:*"family inet6"* ]] && printf "v6\n" && return
[[ $REPLY = Header:*"family inet "* ]] && printf "v4\n" && return
[[ $REPLY = Header:*"range "*.*.*.* ]] && printf "v4\n" && return
-done < <(ipset -t list "$1")
+done < <( ( "${words[0]}" -t list "$1" ) 2>/dev/null)
}
_ipset_dedupe_cmd_opts() {
@@ -152,35 +187,28 @@ _ipset_get_options() {
local str_list
local -i idx oidx ridx
if ((got_action)); then
- case "$str_action" in
- rename|e|swap|w|test|flush|destroy|x)
- str_list='-q -quiet'
- ;;
- save)
- str_list='-f -file -q -quiet'
- ;;
- create|n|add|del)
- str_list='-! -exist -q -quiet'
- ;;
- restore)
- str_list='-! -exist -f -file -q -quiet'
- ;;
- list)
- str_list='-f -file -q -quiet'
- if ((names_only || headers_only)); then
- str_list+=' -o -output'
- elif ((res_sort)); then
- str_list+=' -o -output -r -resolve -s -sorted'
- elif ((save_format == 1)); then
- str_list+=' -r -resolve -s -sorted -t -terse'
- elif ((save_format == 3)); then
- str_list+=' -r -resolve -s -sorted'
- else
- str_list+=' -n -name -o -output -r -resolve \
- -s -sorted -t -terse'
- fi
- ;;
- esac
+ if [[ $str_action = @(rename|e|swap|w|test|flush|destroy|x) ]]; then
+ str_list='-q -quiet'
+ elif [[ $str_action = save ]]; then
+ str_list='-f -file -q -quiet -o -output'
+ elif [[ $str_action = @(create|n|add|del) ]]; then
+ str_list='-! -exist -q -quiet'
+ elif [[ $str_action = restore ]]; then
+ str_list='-! -exist -f -file -q -quiet'
+ elif [[ $str_action = list ]]; then
+ str_list='-f -file -q -quiet'
+ if ((names_only || headers_only)); then
+ str_list+=' -o -output'
+ elif ((res_sort)); then
+ str_list+=' -o -output -r -resolve -s -sorted'
+ elif ((save_format == 1)); then
+ str_list+=' -r -resolve -s -sorted -t -terse'
+ elif ((save_format == 3)); then
+ str_list+=' -r -resolve -s -sorted'
+ else
+ str_list+=' -n -name -o -output -r -resolve -s -sorted -t -terse'
+ fi
+ fi
else
str_list='-f -file -q -quiet'
if ((names_only || headers_only)) && ((save_format == 1)); then
@@ -196,8 +224,8 @@ else
elif ((ignore_errors)); then
:
elif ((use_file)); then
- str_list='-! -exist -n -name -o -output -q -quiet -r \
- -resolve -s -sorted -t -terse'
+ str_list="-! -exist -n -name -o -output -q -quiet -r \
+ -resolve -s -sorted -t -terse"
else
str_list='- ${arr_opts[@]}'
fi
@@ -334,7 +362,7 @@ _ipset_get_ifnames() {
while read -r; do
REPLY="${REPLY#*: }"
printf "%s\n" ${REPLY%%:*}
-done < <(PATH=${PATH}:/sbin command ip -o link show)
+done < <(PATH=${PATH}:/sbin ( command ip -o link show ) 2>/dev/null)
}
_ipset_get_iplist() {
@@ -412,7 +440,7 @@ fi
if [[ $str_p ]]; then # we have a proto spec
COMPREPLY=( $(compgen -P "$str_p:$str_lprefix" \
-W '$(_ipset_get_services -o $str_var -p $str_p)' -- "$lcur" ) )
- _ipset_colon_ltrim "$str_p:$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_p:$str_lprefix$lcur"
else
if [[ $str_lprefix ]]; then
COMPREPLY=( $(compgen -P "$str_lprefix" \
@@ -447,7 +475,6 @@ for idx in ${!COMPREPLY[@]}; do
((got_bracket)) && unset COMPREPLY[idx]
fi
done
-#_ipset_colon_ltrim "$lcur"
}
_ipset_complete_iface_spec() {
@@ -486,7 +513,7 @@ if [[ $lcur != *,* ]]; then
COMPREPLY=( ${COMPREPLY[*]}, ${COMPREPLY[*]}- )
fi
fi
- _ipset_colon_ltrim "$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_lprefix$lcur"
elif [[ $lcur = *,* ]]; then
str_lprefix="${lcur}" lcur="${lcur#*,}" str_var=""
str_lprefix="${str_lprefix%"$lcur"}"
@@ -499,7 +526,7 @@ elif [[ $lcur = *,* ]]; then
COMPREPLY+=( $( compgen -P "$str_lprefix" -W \
'${str_var} $(_ipset_get_ifnames)' -- "$lcur" ) )
[[ ${COMPREPLY[0]} = *physdev: ]] && compopt -o nospace
- _ipset_colon_ltrim "$str_lprefix"
+ __ltrim_colon_completions "$str_lprefix"
fi
}
@@ -551,7 +578,7 @@ else
COMPREPLY+=( $( compgen -W \
'$(_ipset_get_iplist "$(_ipset_get_set_family "$str_setname")")' \
-- "$lcur" ) )
- _ipset_colon_ltrim "$lcur"
+ __ltrim_colon_completions "$lcur"
fi
_ipset_complete_hostnames "$lcur"
if [[ $str_lprefix ]]; then
@@ -613,7 +640,7 @@ if [[ $lcur != *,* ]]; then
-- "$lcur" ) )
if [[ $str_type = hash:net,port?(,net) ]]; then
COMPREPLY+=( $( compgen -W '$(_ipset_get_networks)' -- "$lcur" ) )
- _ipset_colon_ltrim "$lcur"
+ __ltrim_colon_completions "$lcur"
fi
_ipset_complete_hostnames "$lcur"
if [[ $str_lprefix ]]; then # range spec
@@ -626,7 +653,7 @@ if [[ $lcur != *,* ]]; then
COMPREPLY=( ${COMPREPLY[*]}, )
fi
fi
- _ipset_colon_ltrim "$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_lprefix$lcur"
elif [[ $lcur =~ $str_regex ]]; then
compopt -o nospace
str_glob='[^[]*-' # otherwise messes up my vim syntax highlightning
@@ -653,7 +680,7 @@ elif [[ $lcur =~ $str_regex ]]; then
if [[ $str_lprefix = *:* ]]; then
str_lprefix="${str_lprefix%:*}:"
fi
- _ipset_colon_ltrim "${str_lprefix}"
+ __ltrim_colon_completions "${str_lprefix}"
if ((${#COMPREPLY[@]} == 1)); then
if [[ $str_lprefix && $str_type != hash:@(ip|net),port,@(ip|net) ]]; then
compopt +o nospace
@@ -676,7 +703,7 @@ elif [[ $lcur =~ $str_regex ]]; then
COMPREPLY+=( $( compgen -P "$str_lprefix" -W \
'$(_ipset_get_services -p $str_var)' -- "$lcur" ) )
fi
- _ipset_colon_ltrim "$str_lprefix"
+ __ltrim_colon_completions "$str_lprefix"
elif [[ $lcur = *,* ]]; then # first attempt :/ long list
str_lprefix="${lcur%,*}," lcur="${lcur#*,}"
str_var="tcp: udp: sctp: udplite: icmp: icmp6:"
@@ -686,7 +713,7 @@ elif [[ $lcur =~ $str_regex ]]; then
# add the protocols
COMPREPLY+=( $( compgen -P "$str_lprefix" -S ":0$str_suffix" -W \
'$(_ipset_get_protocols)' -- "$lcur" ) )
- _ipset_colon_ltrim "$str_lprefix$lcur"
+ __ltrim_colon_completions "$str_lprefix$lcur"
compopt -o nospace
fi
elif [[ $lcur = *,*,* && $str_type = hash:@(ip,port,@(ip|net)|net,port,net) ]]; then
@@ -727,7 +754,7 @@ elif [[ $lcur = *,*,* && $str_type = hash:@(ip,port,@(ip|net)|net,port,net) ]];
COMPREPLY=( $( compgen -P "$str_lprefix2" \
-W '${COMPREPLY[@]}' -- "$lcur2" ) )
fi
- _ipset_colon_ltrim "$str_lprefix2$lcur2"
+ __ltrim_colon_completions "$str_lprefix2$lcur2"
if ((${#COMPREPLY[@]} == 1)); then
if [[ $str_type = hash:@(ip|net),port,net && \
${COMPREPLY[*]##*,} != */* ]]
@@ -802,7 +829,7 @@ if ((y)); then
[[ $addr =~ $str_regex ]] && printf "%s\n" "$addr"
done < /etc/ethers)"
fi
- printf "%s\n" "$str_tmp"
+ printf "%s\n" "$str_tmp"
fi
}
@@ -811,6 +838,8 @@ fi
# -----------------------------------------------------------------
_ipset_complete() {
+# at least bash 4 is required
+((${BASH_VERSINFO[0]} < 4)) && return 0
local cur prev cword words ips_version
local str_action str_setname str_type str_filename
local str_glob str_regex str_prefix str_suffix
@@ -822,7 +851,7 @@ local -i i=x=y=0
local -i got_bashcompl=got_action=action_index=order_index=set_has_timeout=0
local -i got_bp_proto=0
local -i ignore_errors=use_file=names_only=headers_only=save_format=res_sort=0
-local arr_sets=() arr_types=() arr_members=() arr_unknown_opts=()
+local arr_sets=() arr_types=() arr_members=()
local arr_dupe_cmd_opts=() arr_used_opts=() arr_tmp=()
local arr_opts=(
"-! -exist"
@@ -894,19 +923,45 @@ neigbour-advertisement
redirect
)
-# at least bash 4 is required
-((${BASH_VERSINFO[0]} < 4)) && return 0
-
COMPREPLY=()
+# expecting _get_comp_words_by_ref() to exist from bash_completion
+if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1
+ _get_comp_words_by_ref -n : cur prev cword words || return
+else got_bashcompl=0 # not so neat, but a workaround
+ COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}"
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ cword=$COMP_CWORD
+ for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done
+fi
+
# ipset version check 6.x upwards (to v?) is supported
-ips_version="$(ipset version)"
-ips_version="${ips_version#ipset v}"
-ips_version="${ips_version%,+([[:blank:]])protocol*}"
-read -a ips_version <<< ${ips_version//./ }
-[[ ${ips_version[0]} = +([[:digit:]]) ]] || return 1
+
+# All calls of ipset should be done in a subshell with stderr
+# pointing to /dev/null, to avoid printing of
+# `-bash command ipset not found' errors
+
+i=0 # for safety
+if ((UID != 0)); then # not root user
+ "${words[0]}" version &>/dev/null # can we retrieve the version?
+ i=$?
+fi
+if ((i == 0)); then
+ ips_version="$("${words[0]}" version)"
+ ips_version="${ips_version#ipset v}"
+ ips_version="${ips_version%,+([[:blank:]])protocol*}"
+ read -a ips_version <<< ${ips_version//./ }
+ [[ ${ips_version[0]} = +([[:digit:]]) ]] || return 1
+else
+ # assume we have no permissions to run ipset
+ # set version to 6.22 = show all features
+ # though many things won't work, as of missing permissions
+ ips_version=( 6 22 )
+fi
((ips_version[0] < 6)) && return 1
+
# ipset -ge v6.19 has counters flag
# ipset -ge v6.20 has comment flag
# ipset -ge v6.21 has hash:ip,mark markmask flag
@@ -938,45 +993,22 @@ elif ((ips_version[0] == 6)); then
str_bp_counters="bytes packets"
fi
else
+ # ipset versions -lt 6 are not supported
return 0
fi
-# expecting _get_comp_words_by_ref() to exist from bash_completion
-if declare -f _get_comp_words_by_ref &>/dev/null; then got_bashcompl=1
- _get_comp_words_by_ref -n : cur prev cword words || return
-else got_bashcompl=0 # not so neat, but a workaround
- COMP_WORDBREAKS="${COMP_WORDBREAKS//:/}"
- cur="${COMP_WORDS[COMP_CWORD]}"
- prev="${COMP_WORDS[COMP_CWORD-1]}"
- cword=$COMP_CWORD
- for i in ${!COMP_WORDS[@]}; do words[i]="${COMP_WORDS[i]}"; done
-fi
-
-if ((got_bashcompl)); then
-# current bash completion got a bug i reported:
-# https://alioth.debian.org/tracker/index.php?func=detail&aid=314056&group_id=100114&atid=413095
-# putting corrected function here, so things don't break
-__ltrim_colon_completions() {
- if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
- # Remove colon-word prefix from COMPREPLY items
- local colon_word="${1%"${1##*:}"}"
- local i=${#COMPREPLY[*]}
- while [[ $((--i)) -ge 0 ]]; do
- COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
- done
- fi
-}
-
# construct own known_hosts function from origin
# just remove the __ltrim_colon_completions call
# to avoid unwanted ltrim if we need to work with the list of hosts
# ugly hack - gimme better ;p
-if ! declare -F _ipset_known_hosts &>/dev/null; then
-eval '_ipset_known_hosts() { '$(declare -f _known_hosts_real | grep -v __ltrim_colon_completions | grep -Ev "^_known_hosts_real.*$" | grep -Ev "^(\{|\})")'; }'
-fi
+if ((got_bashcompl)); then
+ if ! declare -F _ipset_known_hosts &>/dev/null; then
+ eval '_ipset_known_hosts() { '$(declare -f _known_hosts_real | \
+ grep -v __ltrim_colon_completions | \
+ grep -Ev "^_known_hosts_real.*$" | grep -Ev "^(\{|\})")'; }'
+ fi
fi
-#_DEBUG_NF_COMPLETION=Y
if [[ $_DEBUG_NF_COMPLETION ]]; then
printf "\nCOMP_WORDBREAKS: <%s>\n" "$COMP_WORDBREAKS"
printf "COMP_LINE: <%s>\n" "$COMP_LINE"
@@ -991,78 +1023,66 @@ fi
# collect information about used options
for ((i=1; i < ${#words[@]}-1; i++)); do
-case "${words[i]}" in
- @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w|help|version))
- [[ ${words[i-1]} = @(-f|-file) ]] && continue # there could be a file named like a command
- if ! ((got_action)); then
- if [[ ${words[i]} != save ]]; then
- got_action=1 action_index=$i str_action=${words[i]}
- elif [[ ${words[i-1]} != @(-o|-output) ]]; then
- got_action=1 action_index=$i str_action=${words[i]}
- fi
- if [[ $str_action = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w) ]]
- then str_setname=${words[i+1]} # register the set name
- fi
+if [[ ${words[i]} = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w|help|version) ]]
+then
+ [[ ${words[i-1]} = @(-f|-file) ]] && continue # could be a file named like a command
+ if ! ((got_action)); then
+ if [[ ${words[i]} != save ]]; then
+ got_action=1 action_index=$i str_action=${words[i]}
+ elif [[ ${words[i-1]} != @(-o|-output) ]]; then
+ got_action=1 action_index=$i str_action=${words[i]}
fi
- ;;
- -\!|-exist)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- ignore_errors=1 arr_used_opts+=(${words[i]})
- ;;
- -f|-file)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- use_file=1 str_filename="${words[i+1]}" \
- arr_used_opts+=(${words[i]})
- ;;
- -n|-name)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- names_only=1 arr_used_opts+=(${words[i]})
- ;;
- -t|-terse)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- headers_only=1 arr_used_opts+=(${words[i]})
- ;;
- -o|-output)
- if [[ ${words[i-1]} != @(-f|-file) ]]; then
- arr_used_opts+=(${words[i]})
- if [[ $prev = @(-o|-output) ]]; then
- save_format=2 # expecting opt-arg
- elif [[ ${words[i+1]} = save ]]; then
- save_format=3 # no -n/-t with -o save
- else
- save_format=1
- fi
+ if [[ $str_action = @(create|n|add|del|test|destroy|x|list|save|restore|flush|rename|e|swap|w) ]]
+ then
+ str_setname=${words[i+1]} # register the set name
fi
- ;;
- -r|-resolve|-s|-sorted)
- [[ ${words[i-1]} != @(-f|-file) ]] &&\
- res_sort=1 arr_used_opts+=(${words[i]})
- ;;
- -q|-quiet)
+ fi
+elif [[ ${words[i]} = @(-\!|-exist) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ ignore_errors=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-f|-file) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ use_file=1 str_filename="${words[i+1]}" arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-n|-name) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ names_only=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-t|-terse) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ headers_only=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-o|-output) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
arr_used_opts+=(${words[i]})
- ;;
-# -?*)
-# if [[ ${words[i]#-} != @(q|quiet) ]]; then
-# # don't include filenames
-# if [[ ${words[i-1]} != @(-f|-file|\>) || ${words[i+1]} != \< ]]; then
-# arr_unknown_opts[${#arr_unknown_opts[@]}]="${words[i]}"
-# fi
-# fi
-# ;;
- before|after)
- if ((got_action && ! order_index && i == action_index+3)); then
- order_index=$i str_order=""
- fi
- ;;
- timeout|range|maxelem|family|hashsize|size|netmask|nomatch|counters|bytes|packets|comment|markmask|forceadd|skbinfo|skbmark|skbprio|skbqueue)
- if ((got_action && i > action_index+2)); then
- str_tmp="$COMP_LINE"
- [[ $str_setname = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
- [[ $str_filename = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
- [[ $str_tmp = *${words[i]}* ]] && arr_dupe_cmd_opts[${#arr_dupe_cmd_opts[@]}]="${words[i]}"
+ if [[ $prev = @(-o|-output) ]]; then
+ save_format=2 # expecting opt-arg
+ elif [[ ${words[i+1]} = save ]]; then
+ save_format=3 # no -n/-t with -o save
+ else
+ save_format=1
fi
- ;;
-esac
+ fi
+elif [[ ${words[i]} = @(-r|-resolve|-s|-sorted) ]]; then
+ if [[ ${words[i-1]} != @(-f|-file) ]]; then
+ res_sort=1 arr_used_opts+=(${words[i]})
+ fi
+elif [[ ${words[i]} = @(-q|-quiet) ]]; then
+ arr_used_opts+=(${words[i]})
+elif [[ ${words[i]} = @(before|after) ]]; then
+ if ((got_action && ! order_index && i == action_index+3)); then
+ order_index=$i str_order=""
+ fi
+elif [[ ${words[i]} = @(timeout|range|maxelem|family|hashsize|size|netmask|nomatch|counters|bytes|packets|comment|markmask|forceadd|skbinfo|skbmark|skbprio|skbqueue) ]]
+then
+ if ((got_action && i > action_index+2)); then
+ str_tmp="$COMP_LINE"
+ [[ $str_setname = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
+ [[ $str_filename = ${words[i]} ]] && str_tmp="${str_tmp/${words[i]}/}"
+ [[ $str_tmp = *${words[i]}* ]] && arr_dupe_cmd_opts[${#arr_dupe_cmd_opts[@]}]="${words[i]}"
+ fi
+fi
done
if [[ $_DEBUG_NF_COMPLETION ]]; then
@@ -1076,7 +1096,6 @@ if [[ $_DEBUG_NF_COMPLETION ]]; then
printf "ignore_errors: <%s>\n" "$ignore_errors"
printf "names_only: <%s>\n" "$names_only"
printf "headers_only: <%s>\n" "$headers_only"
-# printf "arr_unknown_opts: <%s>\n" "${arr_unknown_opts[@]}"
printf "arr_used_opts: <%s>\n" "${arr_used_opts[@]}"
printf "arr_dupe_cmd_opts: <%s>\n" "${arr_dupe_cmd_opts[@]}"
fi
@@ -1094,13 +1113,6 @@ elif ((ignore_errors)); then
fi
fi
-#case "$cur" in # depend on current
-# \<|\>) # redirection operator
-# compopt -o nospace
-# COMPREPLY=( $( compgen -f ) ) # no $cur, so completion starts without space after redirection
-# return 0
-# ;;
-#esac
# catch variables and command substitution
if [[ $cur == \$\(* ]]; then # command substitution
COMPREPLY=( $(compgen -c -P '$(' ${cur#??}) )
@@ -1113,28 +1125,26 @@ elif [[ $cur == \$* ]]; then # variables with a leading `$'
return 0
fi
-case "$prev" in # depend on previous option
- -o|-output)
- # make sure it's not a filename named -o or -output
- if [[ $str_filename != $prev ]]; then
- if ((names_only || headers_only)); then
- COMPREPLY=( $( compgen -W 'plain xml' -- "$cur" ) )
- else
- COMPREPLY=( $( compgen -W 'plain save xml' -- "$cur" ) )
- fi
- return 0
- fi
- ;;
- -f|-file|\<|\>)
- if ((got_bashcompl)); then
- _filedir
+# depend on previous option
+if [[ $prev = @(-o|-output) ]]; then
+ # make sure it's not a filename named -o or -output
+ if [[ $str_filename != $prev ]]; then
+ if ((names_only || headers_only)); then
+ COMPREPLY=( $( compgen -W 'plain xml' -- "$cur" ) )
else
- compopt -o nospace
- COMPREPLY=( $( compgen -f -- "$cur" ) )
+ COMPREPLY=( $( compgen -W 'plain save xml' -- "$cur" ) )
fi
return 0
- ;;
-esac
+ fi
+elif [[ $prev = @(-f|-file|\<|\>) ]]; then
+ if ((got_bashcompl)); then
+ _filedir
+ else
+ compopt -o nospace
+ COMPREPLY=( $( compgen -f -- "$cur" ) )
+ fi
+ return 0
+fi
if ((got_action)); then # we got the main action
# Disallow sets with names of options starting with a hyphen
@@ -1147,412 +1157,374 @@ then
fi
if ((cword == action_index+1)) && [[ $str_action = $prev ]]; then
# depend on previous option which should be the action
- case "$str_action" in
-# create|n|version) :
-# ;;
- help)
- _ipset_get_supported_types
- COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- add|del|rename|e|swap|w|test)
- COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- list|flush|save|destroy|x)
- # we don't know if its an option request, could also be a set
- # named `-*', if the latter is true, show sets and options
- if [[ $cur = -* ]]; then
- _ipset_get_options
- if _ipset_is_set "${cur}*"; then
- COMPREPLY=( $( compgen -W '${arr_sets[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- fi
- else
- COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- fi
- ;;
- restore)
- if [[ $cur = -* ]]; then
- _ipset_get_options
- elif ! [[ $str_filename ]]; then
- # don't show redirector if we have option -f
- COMPREPLY=( \< )
+ # create|n|version - take no aktion
+ if [[ $str_action = help ]]; then
+ _ipset_get_supported_types
+ COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = @(add|del|rename|e|swap|w|test) ]]; then
+ COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = @(list|flush|save|destroy|x) ]]; then
+ # we don't know if its an option request, could also be a set
+ # named `-*', if the latter is true, show sets and options
+ if [[ $cur = -* ]]; then
+ _ipset_get_options
+ if _ipset_is_set "${cur}*"; then
+ COMPREPLY=( $( compgen -W '${arr_sets[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
fi
- ;;
- esac
+ else
+ COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_action = restore ]]; then
+ if [[ $cur = -* ]]; then
+ _ipset_get_options
+ elif ! [[ $str_filename ]]; then
+ # don't show redirector if we have option -f
+ COMPREPLY=( \< )
+ fi
+ fi
elif ((cword == action_index+2)) && [[ $str_setname = $prev ]]; then
- case "$str_action" in
-# rename|e) :
-# ;;
- save|restore|list|flush|destroy|x)
- if [[ $cur = -* ]]; then
- _ipset_get_options
+ # rename|e - take no aktion
+ if [[ $str_action = @(save|restore|list|flush|destroy|x) ]]; then
+ if [[ $cur = -* ]]; then
+ _ipset_get_options
+ fi
+ elif [[ $str_action = @(create|n) ]]; then
+ _ipset_get_supported_types
+ COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = @(swap|w) ]]; then # list two sets
+ COMPREPLY=( $( compgen -W '$( ( "${words[0]}" list -n ) 2>/dev/null )' -- "$cur" ) )
+ for i in ${!COMPREPLY[@]}; do # remove the dupe setname from the list
+ [[ ${COMPREPLY[i]} = $str_setname ]] && unset COMPREPLY[i] && break
+ done
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_action = add ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = bitmap:ip ]]; then
+ _ipset_complete_host_spec "$cur" --v4
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = @(hash:ip|hash:net|hash:ip,mark) ]]; then
+ _ipset_complete_host_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = hash:net,iface ]]; then
+ _ipset_complete_iface_spec "$cur"
+ elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
+ then
+ _ipset_complete_hostport_spec "$cur"
+ elif [[ $str_type = hash:net,net ]]; then
+ _ipset_complete_netnet_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = hash:mac ]]; then
+ COMPREPLY=( $( compgen -W '$(_ipset_complete_mac_spec)' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ elif [[ $str_type = bitmap:ip,mac ]]; then
+ if [[ $cur = *,* ]]; then
+ str_prefix="$cur" cur="${cur#*,}"
+ str_prefix="${str_prefix%$cur}"
+ COMPREPLY+=( $( compgen -P "$str_prefix" -W '$(_ipset_complete_mac_spec)' \
+ -- "$cur" ) )
+ __ltrim_colon_completions "$str_prefix$cur"
+ else
+ compopt -o nospace
+ _ipset_complete_host_spec "$cur" --v4 --no-range
+ __ltrim_colon_completions "$cur"
+ if ((${#COMPREPLY[@]} == 1)); then
+ COMPREPLY=( ${COMPREPLY[*]}, )
+ fi
fi
- ;;
- @(create|n))
- _ipset_get_supported_types
- COMPREPLY=( $( compgen -W '${arr_types[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- @(swap|w)) # list two sets
- COMPREPLY=( $( compgen -W '$(ipset list -n)' -- "$cur" ) )
- for i in ${!COMPREPLY[@]}; do # remove the dupe setname from the list
- [[ ${COMPREPLY[i]} = $str_setname ]] && unset COMPREPLY[i] && break
+ elif [[ $str_type = bitmap:port ]]; then # complete port [range]
+ _ipset_complete_portrange "$cur"
+ elif [[ $str_type = list:* ]]; then
+ # show sets if the set to add is of type list:set
+ arr_tmp=() arr_sets=( $( ( "${words[0]}" list -n ) 2>/dev/null ) )
+ _ipset_get_members --names-only "$str_setname"
+ for x in ${!arr_sets[@]}; do
+ [[ ${arr_sets[x]} = $str_setname ]] && continue
+ for y in ${!arr_members[@]}; do
+ [[ ${arr_sets[x]} = ${arr_members[y]} ]] && continue 2
+ done
+ arr_tmp+=("${arr_sets[x]}")
done
- _ipset_colon_ltrim "$cur"
- ;;
- add)
- str_type=$(_ipset_get_set_type "$str_setname")
- case "$str_type" in
- bitmap:ip)
- _ipset_complete_host_spec "$cur" --v4
- _ipset_colon_ltrim "$cur"
- ;;
- hash:ip|hash:net|hash:ip,mark)
- _ipset_complete_host_spec "$cur"
- _ipset_colon_ltrim "$cur"
- ;;
- hash:net,iface)
- _ipset_complete_iface_spec "$cur"
- ;;
- hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net))
- _ipset_complete_hostport_spec "$cur"
- ;;
- hash:net,net)
- _ipset_complete_netnet_spec "$cur"
- _ipset_colon_ltrim "$cur"
- ;;
- hash:mac)
- COMPREPLY=( $( compgen -W '$(_ipset_complete_mac_spec)' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- bitmap:ip,mac)
- if [[ $cur = *,* ]]; then
- str_prefix="$cur" cur="${cur#*,}"
- str_prefix="${str_prefix%$cur}"
- COMPREPLY+=( $( compgen -P "$str_prefix" -W '$(_ipset_complete_mac_spec)' \
- -- "$cur" ) )
- _ipset_colon_ltrim "$str_prefix$cur"
- else
- compopt -o nospace
- _ipset_complete_host_spec "$cur" --v4 --no-range
- _ipset_colon_ltrim "$cur"
- if ((${#COMPREPLY[@]} == 1)); then
- COMPREPLY=( ${COMPREPLY[*]}, )
+ COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_action = del ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = bitmap:ip ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --v4
+ __ltrim_colon_completions "$cur"
+ else
+ _ipset_complete_host_spec "$cur" --v4
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = bitmap:port ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_portrange "$cur"
+ else
+ _ipset_complete_portrange "$cur"
+ _ipset_get_members --names-only "$str_setname"
+ str_glob='?(tcp:|udp:)@([![]*-*|\[?*\]-*)'
+ if [[ $cur = $str_glob ]]; then
+ str_var="${cur#?(tcp:|udp:)}" # offset
+ str_tmp="${cur%"$str_var"}" # proto
+ # identify service number by name, to find the offset
+ if [[ $str_var != +([[:digit:]]) ]]; then
+ if [[ $str_var = \[+([![])\]-* ]]; then
+ str_var="${str_var%%\]*}"
+ str_var="${str_var#\[}"
+ elif [[ $str_var = *-* ]]; then
+ str_var="${str_var%%-*}"
fi
+ str_var=$(_ipset_get_svnum -p "${str_tmp:-all}" -o "$str_var")
fi
- ;;
- bitmap:port)
- # complete port [range]
- _ipset_complete_portrange "$cur"
- ;;
- # show sets if the set to add is of type list:set
- list:*) arr_tmp=() arr_sets=( $(ipset list -n) )
- _ipset_get_members --names-only "$str_setname"
- for x in ${!arr_sets[@]}; do
- [[ ${arr_sets[x]} = $str_setname ]] && continue
- for y in ${!arr_members[@]}; do
- [[ ${arr_sets[x]} = ${arr_members[y]} ]] && continue 2
+ if [[ $str_var = +([[:digit:]]) ]]; then
+ for i in ${!arr_members[@]}; do
+ ((${arr_members[i]} <= $str_var)) && \
+ unset arr_members[i] || break
done
- arr_tmp+=("${arr_sets[x]}")
- done
- COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- ;;
- esac
- ;;
- del)
- str_type=$(_ipset_get_set_type "$str_setname")
- if [[ $str_type = bitmap:ip ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --v4
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_host_spec "$cur" --v4
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = bitmap:port ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_portrange "$cur"
- else
- _ipset_complete_portrange "$cur"
- _ipset_get_members --names-only "$str_setname"
- str_glob='?(tcp:|udp:)@([![]*-*|\[?*\]-*)'
- if [[ $cur = $str_glob ]]; then
- str_var="${cur#?(tcp:|udp:)}" # offset
- str_tmp="${cur%"$str_var"}" # proto
- # identify service number by name, to find the offset
- if [[ $str_var != +([[:digit:]]) ]]; then
- if [[ $str_var = \[+([![])\]-* ]]; then
- str_var="${str_var%%\]*}"
- str_var="${str_var#\[}"
- elif [[ $str_var = *-* ]]; then
- str_var="${str_var%%-*}"
- fi
- str_var=$(_ipset_get_svnum -p "${str_tmp:-all}" -o "$str_var")
- fi
- if [[ $str_var = +([[:digit:]]) ]]; then
- for i in ${!arr_members[@]}; do
- ((${arr_members[i]} <= $str_var)) && \
- unset arr_members[i] || break
- done
- fi
- str_prefix="${cur%-*}-" cur="${cur##*-}"
fi
- COMPREPLY+=( $( compgen -P "$str_prefix" -W '${arr_members[@]}' -- "$cur" ) )
- fi
- elif [[ $str_type = bitmap:ip,mac ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --v4 --no-range
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_host_spec "$cur" --v4 --no-range
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:@(ip?(,mark)|net) ]]; then
- str_prefix=""
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur"
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_host_spec "$cur"
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net,net ]]; then
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_netnet_spec "$cur"
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_netnet_spec "$cur"
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
- then
- if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
- _ipset_complete_hostport_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_hostport_spec "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net,iface ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_iface_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_iface_spec "$cur"
- _ipset_colon_ltrim "$cur"
+ str_prefix="${cur%-*}-" cur="${cur##*-}"
fi
+ COMPREPLY+=( $( compgen -P "$str_prefix" -W '${arr_members[@]}' -- "$cur" ) )
+ fi
+ elif [[ $str_type = bitmap:ip,mac ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --v4 --no-range
+ __ltrim_colon_completions "$cur"
else
+ _ipset_complete_host_spec "$cur" --v4 --no-range
_ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
+ __ltrim_colon_completions "$cur"
fi
- ;;
- test)
- str_type=$(_ipset_get_set_type "$str_setname")
- if [[ $str_type = bitmap:ip ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --no-range --v4
- else
- _ipset_complete_elements "$cur" --no-range
- if ! _ipset_complete_host_spec "$cur" --no-range --v4; then
- COMPREPLY=()
- fi
- fi
- elif [[ $str_type = hash:ip?(,mark) ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- if ! _ipset_complete_host_spec "$cur" --no-range; then
- COMPREPLY=()
- fi
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_host_spec "$cur"
- _ipset_colon_ltrim "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- if ! _ipset_complete_host_spec "$cur"; then
- COMPREPLY=()
- fi
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
- then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_hostport_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_hostport_spec "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = hash:net,iface ]]; then
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- _ipset_complete_iface_spec "$cur"
- else
- _ipset_complete_elements "$cur" --no-range
- _ipset_complete_iface_spec "$cur"
- _ipset_colon_ltrim "$cur"
- fi
- elif [[ $str_type = bitmap:port ]]; then
- str_prefix="" str_tmp="$cur"
- if [[ $cur = @(tcp|udp):* ]]; then
- ((got_bp_proto)) || return 0 # supported since ipset v6.20
- str_prefix="${cur%:*}"
- str_tmp="${str_tmp#${str_prefix}:}"
- fi
- if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
- elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
- if ((got_bp_proto)); then # supported since ipset v6.20
- COMPREPLY=( $(compgen -W \
- 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
- [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
- _ipset_colon_ltrim "$cur"
- else # only tcp services prior to ipset v6.20
- COMPREPLY=( $(compgen \
- -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
- fi
- else
- if ((got_bp_proto)); then # supported since ipset v6.20
- COMPREPLY=( $(compgen -W \
- 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
- [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
- _ipset_colon_ltrim "$cur"
- else # only tcp services prior to ipset v6.20
- COMPREPLY=( $(compgen \
- -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
- fi
- _ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
+ elif [[ $str_type = hash:@(ip?(,mark)|net) ]]; then
+ str_prefix=""
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ else
+ _ipset_complete_host_spec "$cur"
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = hash:net,net ]]; then
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_netnet_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ else
+ _ipset_complete_netnet_spec "$cur"
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
+ then
+ if [[ ${_IPSET_COMPL_DEL_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_DEL_MODE} = spec ]]; then
+ _ipset_complete_hostport_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_hostport_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_type = hash:net,iface ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_iface_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_iface_spec "$cur"
+ __ltrim_colon_completions "$cur"
+ fi
+ else
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ fi
+ elif [[ $str_action = test ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = bitmap:ip ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --no-range --v4
+ else
+ _ipset_complete_elements "$cur" --no-range
+ if ! _ipset_complete_host_spec "$cur" --no-range --v4; then
+ COMPREPLY=()
fi
+ fi
+ elif [[ $str_type = hash:ip?(,mark) ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur" --no-range
+ __ltrim_colon_completions "$cur"
else
_ipset_complete_elements "$cur" --no-range
- _ipset_colon_ltrim "$cur"
+ if ! _ipset_complete_host_spec "$cur" --no-range; then
+ COMPREPLY=()
+ fi
+ __ltrim_colon_completions "$cur"
fi
- ;;
- esac
-elif ((cword == action_index+3)) && [[ $cur != -* ]]; then
- case "$str_action" in
- add)
- str_type=$(_ipset_get_set_type "$str_setname")
- if _ipset_set_has_option timeout "$str_setname"; then
- str_timeout=timeout
+ elif [[ $str_type = hash:net ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_host_spec "$cur"
+ __ltrim_colon_completions "$cur"
else
- str_timeout=""
+ _ipset_complete_elements "$cur" --no-range
+ if ! _ipset_complete_host_spec "$cur"; then
+ COMPREPLY=()
+ fi
+ __ltrim_colon_completions "$cur"
fi
- if ! _ipset_set_has_option counters "$str_setname"; then
- str_bp_counters=""
+ elif [[ $str_type = hash:@(ip,port|ip,port,ip|ip,port,net|net,port|net,port,net) ]]
+ then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_hostport_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_hostport_spec "$cur"
+ __ltrim_colon_completions "$cur"
fi
- if ! _ipset_set_has_option comment "$str_setname"; then
- str_comment=""
+ elif [[ $str_type = hash:net,iface ]]; then
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ _ipset_complete_iface_spec "$cur"
+ else
+ _ipset_complete_elements "$cur" --no-range
+ _ipset_complete_iface_spec "$cur"
+ __ltrim_colon_completions "$cur"
fi
- if ! _ipset_set_has_option skbinfo "$str_setname"; then
- str_skbflags=""
+ elif [[ $str_type = bitmap:port ]]; then
+ str_prefix="" str_tmp="$cur"
+ if [[ $cur = @(tcp|udp):* ]]; then
+ ((got_bp_proto)) || return 0 # supported since ipset v6.20
+ str_prefix="${cur%:*}"
+ str_tmp="${str_tmp#${str_prefix}:}"
fi
- case "$str_type" in
- hash:*net*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
- -- "$cur" ) )
- ;;
- hash:*!(net)*|bitmap:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
- -- "$cur" ) )
- ;;
- list:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
- -- "$cur" ) )
- ;;
- esac
- ;;
- create|n)
- case "$prev" in
- hash:ip,mark)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_markmask $str_comment $str_forceadd)' \
- -- "$cur" ) )
- ;;
- hash:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_comment $str_forceadd)' \
- -- "$cur" ) )
- ;;
- bitmap:ip)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_skbinfo $str_comment)' \
- -- "$cur" ) )
- ;;
- bitmap:!(ip)?*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_skbinfo $str_comment)' \
- -- "$cur" ) )
- ;;
- list:*)
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_skbinfo $str_comment)' \
- -- "$cur" ) )
- ;;
- esac
- ;;
- del|test)
- str_type=$(_ipset_get_set_type "$str_setname")
- if [[ $str_type = list:* ]]; then
- COMPREPLY=( $( compgen -W '$str_order' -- "$cur" ) )
- elif [[ $str_action = test && $str_type = hash:*net* ]]; then
- COMPREPLY=( $( compgen -W 'nomatch' -- "$cur" ) )
+ if [[ ${_IPSET_COMPL_TEST_MODE:=both} = members ]]; then
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ elif [[ ${_IPSET_COMPL_TEST_MODE} = spec ]]; then
+ if ((got_bp_proto)); then # supported since ipset v6.20
+ COMPREPLY=( $(compgen -W \
+ 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
+ [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
+ __ltrim_colon_completions "$cur"
+ else # only tcp services prior to ipset v6.20
+ COMPREPLY=( $(compgen \
+ -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
+ fi
+ else
+ if ((got_bp_proto)); then # supported since ipset v6.20
+ COMPREPLY=( $(compgen -W \
+ 'tcp: udp: $(_ipset_get_services -p "$str_prefix")' -- "$str_tmp" ) )
+ [[ ${COMPREPLY[*]} = @(tcp|udp): ]] && compopt -o nospace
+ __ltrim_colon_completions "$cur"
+ else # only tcp services prior to ipset v6.20
+ COMPREPLY=( $(compgen -W '$(_ipset_get_services -p tcp)' -- "$cur" ) )
+ fi
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
fi
- ;;
- esac
+ else
+ _ipset_complete_elements "$cur" --no-range
+ __ltrim_colon_completions "$cur"
+ fi
+ fi
+elif ((cword == action_index+3)) && [[ $cur != -* ]]; then
+ if [[ $str_action = add ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if _ipset_set_has_option timeout "$str_setname"; then
+ str_timeout=timeout
+ else
+ str_timeout=""
+ fi
+ if ! _ipset_set_has_option counters "$str_setname"; then
+ str_bp_counters=""
+ fi
+ if ! _ipset_set_has_option comment "$str_setname"; then
+ str_comment=""
+ fi
+ if ! _ipset_set_has_option skbinfo "$str_setname"; then
+ str_skbflags=""
+ fi
+ if [[ $str_type = hash:*net* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
+ -- "$cur" ) )
+ elif [[ $str_type = @(hash:*!(net)*|bitmap:*) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
+ -- "$cur" ) )
+ elif [[ $str_type = list:* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_skbflags $str_comment)' \
+ -- "$cur" ) )
+ fi
+ elif [[ $str_action = @(create|n) ]]; then
+ if [[ $prev = hash:ip,mark ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_markmask $str_comment $str_forceadd)' \
+ -- "$cur" ) )
+ elif [[ $prev = hash:* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_skbinfo $str_comment $str_forceadd)' \
+ -- "$cur" ) )
+ elif [[ $prev = bitmap:ip ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_skbinfo $str_comment)' \
+ -- "$cur" ) )
+ elif [[ $prev = bitmap:!(ip)?* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_skbinfo $str_comment)' \
+ -- "$cur" ) )
+ elif [[ $prev = list:* ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_skbinfo $str_comment)' \
+ -- "$cur" ) )
+ fi
+ elif [[ $str_action = @(del|test) ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = list:* ]]; then
+ COMPREPLY=( $( compgen -W '$str_order' -- "$cur" ) )
+ elif [[ $str_action = test && $str_type = hash:*net* ]]; then
+ COMPREPLY=( $( compgen -W 'nomatch' -- "$cur" ) )
+ fi
+ fi
elif ((cword == action_index+3)) && [[ $cur = -* ]]; then
_ipset_get_options
elif ((cword >= action_index+4)) && [[ $cur = -* ]]; then # add all following hyphen options
@@ -1561,207 +1533,180 @@ elif ((cword >= action_index+4)) && [[ $cur = -* ]]; then # add all following hy
_ipset_get_options
fi
elif ((cword >= action_index+4)); then # add all following non-hyphen options
- case "$str_action" in
- add)
- str_type=$(_ipset_get_set_type "$str_setname")
- if _ipset_set_has_option timeout "$str_setname"; then
- str_timeout=timeout
- else
- str_timeout=""
- fi
- if ! _ipset_set_has_option counters "$str_setname"; then
- str_bp_counters=""
+ if [[ $str_action = add ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if _ipset_set_has_option timeout "$str_setname"; then
+ str_timeout=timeout
+ else
+ str_timeout=""
+ fi
+ if ! _ipset_set_has_option counters "$str_setname"; then
+ str_bp_counters=""
+ fi
+ if ! _ipset_set_has_option comment "$str_setname"; then
+ str_comment=""
+ fi
+ if ! _ipset_set_has_option skbinfo "$str_setname"; then
+ str_skbflags=""
+ fi
+ # validate option argument values
+ if [[ $_IPSET_VALIDATE_INPUT ]]; then
+ for ((x=$action_index+3; x < ${#words[@]}; x++)); do
+ if [[ ${words[x]} = @(timeout|bytes|packets) ]]; then
+ [[ ${words[x+1]} = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] || return 0
+ elif [[ ${words[x]} = skbmark ]]; then
+ if [[ ${words[x+1]} = 0[xX]+([[:xdigit:]])?(/0[xX]+([[:xdigit:]])) ]]; then
+ (( ${words[x+1]%/*} >= 0 && ${words[x+1]%/*} <= 0xFFFFFFFF )) || return 0
+ (( ${words[x+1]#*/} >= 0 && ${words[x+1]#*/} <= 0xFFFFFFFF )) || return 0
+ else
+ return 0
+ fi
+ elif [[ ${words[x]} = skbprio ]]; then
+ [[ ${words[x+1]} = +([[:xdigit:]]):?(+([[:xdigit:]])) ]] || return 0
+ elif [[ ${words[x]} = skbqueue ]]; then
+ [[ ${words[x+1]} = +([[:digit:]]) ]] || return 0
+ fi
+ done
+ fi
+ if [[ $str_type = hash:*net* ]]; then
+ if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
+ -- "$cur" ) )
fi
- if ! _ipset_set_has_option comment "$str_setname"; then
- str_comment=""
+ elif [[ $str_type = @(hash:*!(net)*|bitmap:*) ]]; then
+ if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
+ -- "$cur" ) )
fi
- if ! _ipset_set_has_option skbinfo "$str_setname"; then
- str_skbflags=""
+ elif [[ $str_type = list:* ]]; then
+ if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)); then
+ _ipset_complete_elements "$cur"
+ __ltrim_colon_completions "$cur"
+ elif [[ $prev != @(timeout|bytes|packets|skbmark|skbprio|skbqueue) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
+ -- "$cur" ) )
fi
- # validate option argument values
- if [[ ${_IPSET_VALIDATE_INPUT-1} ]]; then
- for ((x=$action_index+3; x < ${#words[@]}; x++)); do
- if [[ ${words[x]} = @(timeout|bytes|packets) ]]; then
- [[ ${words[x+1]} = @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] || return 0
- elif [[ ${words[x]} = skbmark ]]; then
- if [[ ${words[x+1]} = 0[xX]+([[:xdigit:]])?(/0[xX]+([[:xdigit:]])) ]]; then
- (( ${words[x+1]%/*} >= 0 && ${words[x+1]%/*} <= 0xFFFFFFFF )) || return 0
- (( ${words[x+1]#*/} >= 0 && ${words[x+1]#*/} <= 0xFFFFFFFF )) || return 0
+ fi
+ elif [[ $str_action = @(create|n) ]]; then
+ # validate option argument values
+ if [[ $_IPSET_VALIDATE_INPUT ]]; then
+ for ((x=$action_index+3; x < ${#words[@]}; x++)); do
+ if [[ ${words[x+1]} && ${words[x+1]} != $cur ]]; then
+ if [[ ${words[x]} = @(hashsize|timeout|size|maxelem|markmask) ]]; then
+ [[ ${words[x+1]} != @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] && return 0
+ elif [[ ${words[x]} = family ]]; then
+ [[ ${words[x+1]} != inet?(6) ]] && return 0
+ elif [[ ${words[x]} = range ]]; then
+ if [[ $str_type = bitmap:port ]]; then
+ [[ ${words[x+1]} != *-* ]] && return 0
else
- return 0
+ [[ ${words[x+1]} != @(*-*|*/+([[:digit:]])) ]] && return 0
fi
- elif [[ ${words[x]} = skbprio ]]; then
- [[ ${words[x+1]} = +([[:xdigit:]]):?(+([[:xdigit:]])) ]] || return 0
- elif [[ ${words[x]} = skbqueue ]]; then
- [[ ${words[x+1]} = +([[:digit:]]) ]] || return 0
fi
- done
+ fi
+ done
+ fi
+ if [[ ${words[action_index+2]} = hash:ip,mark ]]; then # must be the set type
+ if [[ $prev = family ]]; then
+ COMPREPLY=( $( compgen -W '$(_ipset_dedupe_cmd_opts inet inet6)' \
+ -- "$cur" ) )
+ elif [[ $prev != @(hashsize|timeout|maxelem|markmask) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_markmask $str_comment $str_forceadd $str_skbinfo)' \
+ -- "$cur" ) )
fi
- case "$str_type" in
- hash:*net*)
- if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags nomatch)' \
- -- "$cur" ) )
- fi
- ;;
- hash:*!(net)*|bitmap:*)
- if [[ $prev != @(timeout|bytes|packets|comment|skbmark|skbprio|skbqueue) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
- -- "$cur" ) )
- fi
- ;;
- list:*)
- if [[ $prev = @(before|after) ]] && ((cword-1 == order_index)); then
- _ipset_complete_elements "$cur"
- _ipset_colon_ltrim "$cur"
- elif [[ $prev != @(timeout|bytes|packets|skbmark|skbprio|skbqueue) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts $str_order $str_timeout $str_bp_counters $str_comment $str_skbflags)' \
- -- "$cur" ) )
- fi
- ;;
- esac
- ;;
- create|n)
- # validate option argument values
- if [[ ${_IPSET_VALIDATE_INPUT-1} ]]; then
- for ((x=$action_index+3; x < ${#words[@]}; x++)); do
- if [[ ${words[x+1]} && ${words[x+1]} != $cur ]]; then
- case "${words[x]}" in
- @(hashsize|timeout|size|maxelem|markmask))
- [[ ${words[x+1]} != @(+([[:digit:]])|0[xX]+([[:xdigit:]])) ]] && return 0
- ;;
- family)
- [[ ${words[x+1]} != inet?(6) ]] && return 0
- ;;
- range)
- case "$str_type" in
- bitmap:port)
- [[ ${words[x+1]} != *-* ]] && return 0
- ;;
- *)
- [[ ${words[x+1]} != @(*-*|*/+([[:digit:]])) ]] && return 0
- ;;
- esac
- ;;
- esac
- fi
- done
+ elif [[ ${words[action_index+2]} = hash:* ]]; then
+ if [[ $prev = family ]]; then
+ COMPREPLY=( $( compgen -W '$(_ipset_dedupe_cmd_opts inet inet6)' \
+ -- "$cur" ) )
+ elif [[ $prev != @(hashsize|timeout|maxelem) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_comment $str_forceadd $str_skbinfo)' \
+ -- "$cur" ) )
fi
- case "${words[action_index+2]}" in # must be the set type
- hash:ip,mark)
- if [[ $prev = family ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts inet inet6)' \
- -- "$cur" ) )
- elif [[ $prev != @(hashsize|timeout|maxelem|markmask) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_markmask $str_comment $str_forceadd $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- hash:*)
- if [[ $prev = family ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts inet inet6)' \
- -- "$cur" ) )
- elif [[ $prev != @(hashsize|timeout|maxelem) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts family hashsize timeout maxelem $str_counters $str_comment $str_forceadd $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- bitmap:ip)
- if [[ $prev != @(range|netmask|timeout) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_comment $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- bitmap:!(ip)?*)
- if [[ $prev != @(range|timeout) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_comment $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- list:*)
- if [[ $prev != @(size|timeout) ]]; then
- COMPREPLY=( $( compgen -W \
- '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_comment $str_skbinfo)' \
- -- "$cur" ) )
- fi
- ;;
- esac
- if [[ ${words[action_index+2]} = bitmap:port && $prev = range ]]; then
- # complete port ranges
- _ipset_complete_portrange "$cur"
- elif [[ ${words[action_index+2]} = bitmap:* && $prev = range ]]; then
- str_prefix=""
- if [[ $cur = @(""|+([[:word:]])) ]]; then # empty or [:word:]
- :
- elif [[ $cur = [\[]*-*[\]] ]]; then # host with hyphen
- :
- elif [[ $cur = [[]*([!]]) ]]; then # incomplete host with dash
- :
- elif [[ $cur = *-[[]+([!]]) ]]; then # incomplete range - host with dash
- str_prefix="${cur%\-[*}-"
- elif [[ $cur = \[*\]-* ]]; then # first part of hostname range
- str_prefix="${cur%\]-*}]-"
- elif [[ $cur != *-* ]]; then # no hypen
- :
- else # ip-range
- str_prefix="${cur%-*}-"
+ elif [[ ${words[action_index+2]} = bitmap:ip ]]; then
+ if [[ $prev != @(range|netmask|timeout) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range netmask timeout $str_counters $str_comment $str_skbinfo)' \
+ -- "$cur" ) )
+ fi
+ elif [[ ${words[action_index+2]} = bitmap:!(ip)?* ]]; then
+ if [[ $prev != @(range|timeout) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts range timeout $str_counters $str_comment $str_skbinfo)' \
+ -- "$cur" ) )
+ fi
+ elif [[ ${words[action_index+2]} = list:* ]]; then
+ if [[ $prev != @(size|timeout) ]]; then
+ COMPREPLY=( $( compgen -W \
+ '$(_ipset_dedupe_cmd_opts size timeout $str_counters $str_comment $str_skbinfo)' \
+ -- "$cur" ) )
+ fi
+ fi
+ if [[ ${words[action_index+2]} = bitmap:port && $prev = range ]]; then
+ # complete port ranges
+ _ipset_complete_portrange "$cur"
+ elif [[ ${words[action_index+2]} = bitmap:* && $prev = range ]]; then
+ str_prefix=""
+ if [[ $cur = @(""|+([[:word:]])) ]]; then # empty or [:word:]
+ :
+ elif [[ $cur = [\[]*-*[\]] ]]; then # host with hyphen
+ :
+ elif [[ $cur = [[]*([!]]) ]]; then # incomplete host with dash
+ :
+ elif [[ $cur = *-[[]+([!]]) ]]; then # incomplete range - host with dash
+ str_prefix="${cur%\-[*}-"
+ elif [[ $cur = \[*\]-* ]]; then # first part of hostname range
+ str_prefix="${cur%\]-*}]-"
+ elif [[ $cur != *-* ]]; then # no hypen
+ :
+ else # ip-range
+ str_prefix="${cur%-*}-"
+ fi
+ _ipset_complete_host_spec "$cur" --v4
+ if ((${#COMPREPLY[@]} == 1)); then
+ if [[ -z $str_prefix && ${COMPREPLY[*]} != */* ]]; then
+ compopt -o nospace
+ COMPREPLY=( $( compgen -W '${COMPREPLY[*]}/ ${COMPREPLY[*]}-' -- "$cur" ) )
fi
- _ipset_complete_host_spec "$cur" --v4
- if ((${#COMPREPLY[@]} == 1)); then
- if [[ -z $str_prefix && ${COMPREPLY[*]} != */* ]]; then
- compopt -o nospace
- COMPREPLY=( $( compgen -W '${COMPREPLY[*]}/ ${COMPREPLY[*]}-' -- "$cur" ) )
- fi
+ fi
+ fi
+ elif [[ $str_action = @(del|test) ]]; then
+ str_type=$(_ipset_get_set_type "$str_setname")
+ if [[ $str_type = list:* ]]; then
+ arr_tmp=()
+ _ipset_get_members --names-only "$str_setname"
+ if [[ $prev = @(before|after) ]] && ((cword-1 == order_index))
+ then
+ if [[ $prev = before ]]; then
+ for x in ${!arr_members[@]}; do
+ if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
+ then
+ if [[ ${arr_members[x+1]} ]]; then
+ arr_tmp+=(${arr_members[x+1]})
+ break
+ fi
+ fi
+ done
+ elif [[ $prev = after ]]; then
+ for x in ${!arr_members[@]}; do
+ if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
+ then
+ if ((x>0)) && [[ ${arr_members[x-1]} ]]; then
+ arr_tmp+=(${arr_members[x-1]})
+ break
+ fi
+ fi
+ done
fi
+ COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
+ __ltrim_colon_completions "$cur"
fi
- ;;
- del|test)
- str_type=$(_ipset_get_set_type "$str_setname")
- case "$str_type" in
- list:*) arr_tmp=()
- _ipset_get_members --names-only "$str_setname"
- if [[ $prev = @(before|after) ]] && ((cword-1 == order_index))
- then
- case "$prev" in
- before)
- for x in ${!arr_members[@]}; do
- if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
- then
- if [[ ${arr_members[x+1]} ]]; then
- arr_tmp+=(${arr_members[x+1]})
- break
- fi
- fi
- done
- ;;
- after)
- for x in ${!arr_members[@]}; do
- if [[ ${arr_members[x]} = ${words[action_index+2]} ]]
- then
- if ((x>0)) && [[ ${arr_members[x-1]} ]]; then
- arr_tmp+=(${arr_members[x-1]})
- break
- fi
- fi
- done
- ;;
- esac
- COMPREPLY=( $( compgen -W '${arr_tmp[@]}' -- "$cur" ) )
- _ipset_colon_ltrim "$cur"
- fi
- ;;
- esac
- ;;
- esac
+ fi
+ fi
fi
else # we don't have the main action yet
if [[ $prev = - ]] && ((cword == 2)); then
@@ -1771,7 +1716,9 @@ if [[ $cur = -* ]]; then # any option is requested
_ipset_get_options
else
# we don't have the action yet, check options to display appropiate actions
- if ((save_format || names_only || headers_only)); then
+ if ((save_format && !headers_only && !names_only)); then
+ COMPREPLY=( $( compgen -W 'list save' -- "$cur" ) )
+ elif ((save_format || names_only || headers_only)); then
COMPREPLY=( $( compgen -W 'list' -- "$cur" ) )
elif ((res_sort)); then
COMPREPLY=( $( compgen -W 'list save' -- "$cur" ) )
@@ -1782,8 +1729,8 @@ else
elif ((use_file)); then
COMPREPLY=( $( compgen -W 'list save restore' -- "$cur" ) )
else
- COMPREPLY=( $( compgen -W 'create n add del test destroy x list save \
- restore flush rename e swap w help version' -- "$cur" ) )
+ COMPREPLY=( $( compgen -W 'create n add del test destroy x list save \
+ restore flush rename e swap w help version' -- "$cur" ) )
fi
fi
fi