diff --git a/.gitignore b/.gitignore index 79a1288..2eea6d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,12 @@ -ipset-*.tar.bz2 +/ipset-6.9.1.tar.bz2 +/ipset-6.11.tar.bz2 +/ipset-6.13.tar.bz2 +/ipset-6.14.tar.bz2 +/ipset-6.16.1.tar.bz2 +/ipset-6.19.tar.bz2 +/ipset-6.20.1.tar.bz2 +/ipset-6.21.1.tar.bz2 +/ipset-6.22.tar.bz2 +/ipset-6.26.tar.bz2 +/ipset-6.27.tar.bz2 +/ipset-6.29.tar.bz2 diff --git a/ipset-config b/ipset-config deleted file mode 100644 index 758f40b..0000000 --- a/ipset-config +++ /dev/null @@ -1,5 +0,0 @@ -# Save current ipsets on stop. -# Value: yes|no, default: no -# Saves all ipsets to /etc/sysconfig/ipset.d/ if service gets stopped -# (e.g. on system shutdown). -IPSET_SAVE_ON_STOP="no" diff --git a/ipset.service b/ipset.service index 65c3121..f86c16b 100644 --- a/ipset.service +++ b/ipset.service @@ -9,11 +9,10 @@ RemainAfterExit=yes ExecStart=/usr/libexec/ipset/ipset.start-stop start ExecStop=/usr/libexec/ipset/ipset.start-stop stop ExecReload=/usr/libexec/ipset/ipset.start-stop reload -# Save current ipset entries on stop. +# Save current ipset entries on stop/restart. # Value: yes|no, default: no # Saves all ipsets to /etc/sysconfig/ipset if ipset gets stopped -Environment=IPSET_SAVE_ON_STOP=no -EnvironmentFile=-/etc/sysconfig/ipset-config +Environment=IPSET_SAVE_ON_STOP=no IPSET_SAVE_ON_RESTART=no [Install] WantedBy=basic.target diff --git a/ipset.spec b/ipset.spec index 8fa6607..1d91179 100644 --- a/ipset.spec +++ b/ipset.spec @@ -1,21 +1,15 @@ Name: ipset -Version: 7.24 -Release: 2%{?dist} +Version: 6.29 +Release: 1%{?dist} Summary: Manage Linux IP sets -License: GPL-2.0-only +License: GPLv2 URL: http://ipset.netfilter.org/ -Source0: %{url}/%{name}-%{version}.tar.bz2 +Source0: http://ipset.netfilter.org/%{name}-%{version}.tar.bz2 Source1: %{name}.service Source2: %{name}.start-stop -Source3: %{name}-config BuildRequires: libmnl-devel -BuildRequires: automake -BuildRequires: autoconf -BuildRequires: make -BuildRequires: libtool -BuildRequires: libtool-ltdl-devel # An explicit requirement is needed here, to avoid cases where a user would # explicitly update only one of the two (e.g 'yum update ipset') @@ -48,7 +42,7 @@ This package contains the libraries which provide the IP sets funcionality. %package devel Summary: Development files for %{name} Requires: %{name}-libs%{?_isa} == %{version}-%{release} -Requires: kernel-headers +Requires: kernel-devel %description devel This package contains the files required to develop software using the %{name} @@ -71,11 +65,10 @@ out of the base package since it is not active by default. %prep -%autosetup -p1 +%setup -q %build -./autogen.sh %configure --enable-static=no --with-kmod=no # Just to make absolutely sure we are not building the bundled kernel module @@ -86,11 +79,11 @@ rm -fr kernel sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool -%make_build +make %{?_smp_mflags} %install -%make_install +make install DESTDIR=%{buildroot} find %{buildroot} -name '*.la' -exec rm -f '{}' \; # install systemd unit file @@ -101,16 +94,9 @@ install -c -m 644 %{SOURCE1} %{buildroot}/%{_unitdir} install -d -m 755 %{buildroot}%{_libexecdir}/%{name} install -c -m 755 %{SOURCE2} %{buildroot}%{_libexecdir}/%{name} -# install ipset-config -install -d -m 755 %{buildroot}%{_sysconfdir}/sysconfig -install -c -m 600 %{SOURCE3} %{buildroot}%{_sysconfdir}/sysconfig/%{name}-config - # Create directory for configuration mkdir -p %{buildroot}%{_sysconfdir}/%{name} -# Turn absolute symlink into a relative one -ln -sf %{name} %{buildroot}/%{_sbindir}/%{name}-translate - %preun if [[ $1 -eq 0 && -n $(lsmod | grep "^xt_set ") ]]; then @@ -119,23 +105,13 @@ if [[ $1 -eq 0 && -n $(lsmod | grep "^xt_set ") ]]; then fi -%ldconfig_scriptlets libs +%post libs -p /sbin/ldconfig + +%postun libs -p /sbin/ldconfig %post service %systemd_post %{name}.service -if [[ -f /etc/ipset/ipset ]] && [[ ! -f /etc/sysconfig/ipset ]]; then - mv /etc/ipset/ipset /etc/sysconfig/ipset - ln -s /etc/sysconfig/ipset /etc/ipset/ipset - echo "Warning: ipset save location has moved to /etc/sysconfig" -fi -[[ -f /etc/sysconfig/iptables-config ]] && . /etc/sysconfig/iptables-config -[[ -f /etc/sysconfig/ip6tables-config ]] && . /etc/sysconfig/ip6tables-config -if [[ ${IPTABLES_SAVE_ON_STOP} == yes ]] || \ - [[ ${IP6TABLES_SAVE_ON_STOP} == yes ]]; then - echo "Warning: ipset no longer saves automatically when iptables does" - echo " must enable explicitly in /etc/sysconfig/ipset-config" -fi %preun service if [[ $1 -eq 0 && -n $(lsmod | grep "^xt_set ") ]]; then @@ -149,182 +125,27 @@ fi %files -%doc ChangeLog -%license COPYING -%{_mandir}/man8/%{name}*.8.* +%doc COPYING ChangeLog +%doc %{_mandir}/man8/%{name}.8.gz %{_sbindir}/%{name} -%{_sbindir}/%{name}-translate %files libs -%license COPYING -%{_libdir}/lib%{name}.so.13* +%doc COPYING +%{_libdir}/lib%{name}.so.3* %files devel %{_includedir}/lib%{name} %{_libdir}/lib%{name}.so %{_libdir}/pkgconfig/lib%{name}.pc -%{_mandir}/man3/libipset.3.* %files service %{_unitdir}/%{name}.service %dir %{_libexecdir}/%{name} -%config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/ipset-config -%ghost %config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/ipset %attr(0755,root,root) %{_libexecdir}/%{name}/%{name}.start-stop +%dir %{_sysconfdir}/%{name} %changelog -* Thu Jul 24 2025 Fedora Release Engineering - 7.24-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Tue May 20 2025 Phil Sutter - 7.24-1 -- new version - -* Wed May 07 2025 Phil Sutter - 7.23-1 -- new version - -* Fri Jan 17 2025 Fedora Release Engineering - 7.22-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Thu Aug 01 2024 Phil Sutter - 7.22-1 -- Turn absolute ipset-translate symlink into a relative one -- Rebase onto v7.22 plus fixes - -* Thu Jul 18 2024 Fedora Release Engineering - 7.21-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Mon Feb 12 2024 Nicolas Chauvet - 7.21-1 -- Update to 7.21 - -* Thu Feb 01 2024 Nicolas Chauvet - 7.20-1 -- Update to 7.20 - -* Wed Jan 24 2024 Fedora Release Engineering - 7.19-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Sat Jan 20 2024 Fedora Release Engineering - 7.19-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Mon Oct 23 2023 Nicolas Chauvet - 7.19-1 -- Update to 7.19 - -* Fri Aug 11 2023 Phil Sutter - 7.17-7 -- Convert license to SPDX format - -* Fri Aug 11 2023 Phil Sutter - 7.17-6 -- Convert license to SPDX format - -* Fri Aug 11 2023 Phil Sutter - 7.17-5 -- Convert license to SPDX format - -* Fri Aug 11 2023 Phil Sutter - 7.17-4 -- Convert license to SPDX format - -* Thu Jul 20 2023 Fedora Release Engineering - 7.17-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Thu Jan 19 2023 Fedora Release Engineering - 7.17-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Mon Jan 02 2023 Nicolas Chauvet - 7.17-1 -- Update to 7.17 - -* Fri Dec 02 2022 Nicolas Chauvet - 7.16-1 -- Update to 7.16 - -* Tue Aug 23 2022 Nicolas Chauvet - 7.15-5 -- Backport upstream patches - rhbz#2117654 - ipset-translate does not work with IPv6 sets - -* Thu Jul 21 2022 Fedora Release Engineering - 7.15-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Tue Mar 15 2022 Phil Sutter - 7.15-3 -- Use the advanced init script from Centos9Stream - -* Thu Jan 20 2022 Fedora Release Engineering - 7.15-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Mon Aug 16 2021 Nicolas Chauvet - 7.15-1 -- Update to 7.15 - -* Wed Jul 28 2021 Nicolas Chauvet - 7.14-1 -- Update to 7.14 - -* Thu Jul 22 2021 Fedora Release Engineering - 7.11-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 7.11-2 -- Rebuilt for updated systemd-rpm-macros - See https://pagure.io/fesco/issue/2583. - -* Mon Mar 01 2021 Nicolas Chauvet - 7.11-1 -- Update to 7.11 - -* Tue Jan 26 2021 Fedora Release Engineering - 7.10-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Mon Dec 21 2020 Nicolas Chauvet - 7.10-1 -- Update to 7.10 - -* Wed Dec 16 2020 Nicolas Chauvet - 7.9-1 -- Update to 7.9 - -* Tue Jul 28 2020 Fedora Release Engineering - 7.6-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Mon Feb 24 2020 Nicolas Chauvet - 7.6-1 -- Update to 7.6 - -* Wed Jan 29 2020 Fedora Release Engineering - 7.5-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Fri Jan 10 2020 Nicolas Chauvet - 7.5-1 -- Update to 7.5 - -* Mon Nov 04 2019 Eric Garver - 7.4-1 -- Update to 7.4 - -* Mon Aug 19 2019 Nicolas Chauvet - 7.3-1 -- Update to 7.3 - -* Thu Jul 25 2019 Fedora Release Engineering - 7.2-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Thu Jul 11 2019 Nicolas Chauvet - 7.2-1 -- Update to 7.2 - -* Fri Feb 01 2019 Fedora Release Engineering - 6.38-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Mon Aug 13 2018 Nicolas Chauvet - 6.38-1 -- Update to 6.38 -- Clean-up spec - -* Fri Jul 13 2018 Fedora Release Engineering - 6.35-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Mon Feb 12 2018 Eric Garver - 6.35-3 -- Patch for missing header file (RHBZ#1543596) - -* Wed Feb 07 2018 Fedora Release Engineering - 6.35-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Mon Jan 08 2018 Nicolas Chauvet - 6.35-1 -- Update to 6.35 - -* Mon Jul 31 2017 Nicolas Chauvet - 6.32-1 -- Update to 6.32 - -* Wed Jul 26 2017 Fedora Release Engineering - 6.29-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Fri Apr 07 2017 Nicolas Chauvet - 6.29-3 -- Userspace needs kernel-headers - rhbz#1420864 - -* Fri Feb 10 2017 Fedora Release Engineering - 6.29-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - * Mon Apr 18 2016 Thomas Woerner - 6.29-1 - New upstream version 6.29 (RHBZ#1317208) - Suppress unnecessary stderr in command loop for resize and list diff --git a/ipset.start-stop b/ipset.start-stop index 377beed..da21890 100644 --- a/ipset.start-stop +++ b/ipset.start-stop @@ -1,359 +1,209 @@ -#!/bin/sh +#!/bin/bash # # ipset Start and stop ipset firewall sets # -# config: /etc/sysconfig/ipset-config +# config: /etc/ipset/ipset +# -IPSET_BIN=/usr/sbin/ipset -IPSET_CONFIG=/etc/sysconfig/ipset-config -IPSET_DATA_COMPAT=/etc/sysconfig/ipset -IPSET_DATA_COMPAT_BACKUP=${IPSET_DATA_COMPAT}.save -IPSET_DATA_DIR=/etc/sysconfig/ipset.d -IPSET_DATA_DIR_BACKUP=${IPSET_DATA_DIR}.save -IPSET_DATA_SAVED_FLAG=${IPSET_DATA_DIR}/.saved -IPSET_LOCK=/run/ipset.lock -IPSET_RUN=/run/ipset.run -CLEAN_FILES="" +IPSET=ipset +IPSET_BIN=/usr/sbin/${IPSET} +IPSET_DATA=/etc/${IPSET}/${IPSET} -trap "rm -rf \${CLEAN_FILES}" EXIT +IPTABLES_CONFIG=/etc/sysconfig/iptables-config +IP6TABLES_CONFIG=${IPTABLES_CONFIG/iptables/ip6tables} -info() { - echo "ipset: ${*}" >&2 +TMP_FIFO=/tmp/${IPSET}.$$ + +if [[ ! -x ${IPSET_BIN} ]]; then + echo "${IPSET_BIN} does not exist." + exit 5 +fi + +CLEAN_FILES=TMP_FIFO +trap "rm -f \$CLEAN_FILES" EXIT + +# Default ipset configuration: +[[ -z $IPSET_SAVE_ON_STOP ]] && IPSET_SAVE_ON_STOP=no # Overridden by ip(6)tables IP(6)TABLES_SAVE_ON_STOP +[[ -z $IPSET_SAVE_ON_RESTART ]] && IPSET_SAVE_ON_RESTART=no # Overridden by ip(6)tables IP(6)TABLES_SAVE_ON_RESTART + +# Load iptables configuration(s) +[[ -f "$IPTABLES_CONFIG" ]] && . "$IPTABLES_CONFIG" +[[ -f "$IP6TABLES_CONFIG" ]] && . "$IP6TABLES_CONFIG" + +# It doesn't make sense to save iptables config and not our config +[[ ${IPTABLES_SAVE_ON_STOP} = yes || ${IP6TABLES_SAVE_ON_STOP} = yes ]] && IPSET_SAVE_ON_STOP=yes +[[ ${IPTABLES_SAVE_ON_RESTART} = yes || ${IP6TABLES_SAVE_ON_RESTART} = yes ]] && IPSET_SAVE_ON_RESTART=yes + +check_can_unload() { + # If the xt_set module is loaded and can't be unloaded, then iptables is + # using ipsets, so refuse to stop the service. + if [[ -n $(lsmod | grep "^xt_set ") ]]; then + rmmod xt_set 2>/dev/null + [[ $? -ne 0 ]] && echo Current iptables configuration requires ipsets && return 1 + fi + + return 0 } -warn() { - echo "<4>ipset: ${*}" >&2 +flush_n_delete() { + local ret=0 set + + # Flush sets + ${IPSET_BIN} flush + let ret+=$? + + # Delete ipset sets. If we don't do them individually, then none + # will be deleted unless they all can be. + for set in $(${IPSET_BIN} list -name); do + ${IPSET_BIN} destroy 2>/dev/null + [[ $? -ne 0 ]] && ret=1 + done + + return $ret } -err() { - echo "<3>ipset: ${*}" >&2 +start_clean() +{ + mkfifo -m go= "${TMP_FIFO}" + [[ $? -ne 0 ]] && return 1 + + # Get the lists of sets in current(old) config and new config + old_sets="$(${IPSET_BIN} list -name | sort -u)" + new_sets="$(grep ^create "${IPSET_DATA}" | cut -d " " -f 2 | sort -u)" + + # List of sets no longer wanted + drop_sets="$( printf "%s\n" "${old_sets}" > "${TMP_FIFO}" & + printf "%s\n" "${new_sets}" | comm -23 "${TMP_FIFO}" - + )" + + # Get rid of sets no longer needed + # Unfortunately -! doesn't work for destroy, so we have to do it a command at a time + for dset in $drop_sets; do + ipset destroy $dset 2>/dev/null + # If it won't go - ? in use by iptables, just clear it + [[ $? -ne 0 ]] && ipset flush $dset + done + + # Now delete the set members no longer required + ${IPSET_BIN} save | grep "^add " | sort >${TMP_FIFO} & + grep "^add " ${IPSET_DATA} | sort | comm -23 ${TMP_FIFO} - | sed -e "s/^add /del /" \ + | ${IPSET_BIN} restore -! + + # At last we can add the set members we haven't got + ipset restore -! <${IPSET_DATA} + + rm ${TMP_FIFO} + + return 0 } -[ -x ${IPSET_BIN} ] || { err "Cannot execute ${IPSET_BIN}"; exit 1; } +start() { + # Do not start if there is no config file. + [[ ! -f "$IPSET_DATA" ]] && echo "Loaded with no configuration" && return 0 -# Source ipset configuration -# shellcheck source=ipset-config -[ -f ${IPSET_CONFIG} ] && . ${IPSET_CONFIG} + # We can skip the first bit and do a simple load if + # there is no current ipset configuration + res=1 + if [[ -n $(${IPSET_BIN} list -name) ]]; then + # The following may fail for some bizarre reason + start_clean + res=$? -set -f + [[ $res -ne 0 ]] && echo "Some old configuration may remain" + fi -lock() { - CLEAN_FILES="${CLEAN_FILES} ${IPSET_LOCK}" - until mkdir ${IPSET_LOCK} 2>/dev/null; do :; done -} + # res -ne 0 => either start_clean failed, or we didn't need to run it + if [[ $res -ne 0 ]]; then + # This is the easy way to start but would leave any old + # entries still configured. Still, better than nothing - + # but fine if we had no config + ${IPSET_BIN} restore -! <${IPSET_DATA} + res=$? + fi -save() { - fail=0 + if [[ $res -ne 0 ]]; then + return 1 + fi - # Make backups of existing configuration first, if any - [ -d ${IPSET_DATA_DIR} ] && mv -Tf ${IPSET_DATA_DIR} ${IPSET_DATA_DIR_BACKUP} - [ -f ${IPSET_DATA_COMPAT} ] && mv -Tf ${IPSET_DATA_COMPAT} ${IPSET_DATA_COMPAT_BACKUP} - - rm -f ${IPSET_DATA_SAVED_FLAG} - - # Save each set in a separate file - mkdir -p ${IPSET_DATA_DIR} - chmod 0700 ${IPSET_DATA_DIR} - IFS=" -" - for set in $(${IPSET_BIN} list -n -t); do - # Empty name allowed, use ".set" as suffix. 'ipset save' doesn't - # quote set names with spaces: if we have a space in the name, - # work around this by quoting it ourselves in the output. - # shellcheck disable=SC2003 # No POSIX equivalent to expr index - if expr index "${set}" " " >/dev/null; then - :> "${IPSET_DATA_DIR}/${set}.set" - for line in $(${IPSET_BIN} save "${set}"); do - create=0 - echo "${line}" | grep -q "^create " && create=1 - if [ $create -eq 1 ]; then - line=${line#create *} - else - line=${line#add *} - fi - line=${line#${set} *} - set="$(echo "${set}" | sed 's/"/\\"/g')" - if [ $create -eq 1 ]; then - echo "create \"${set}\" ${line}" >> "${IPSET_DATA_DIR}/${set}.set" - else - echo "add \"${set}\" ${line}" >> "${IPSET_DATA_DIR}/${set}.set" - fi - done - else - ${IPSET_BIN} save "${set}" > "${IPSET_DATA_DIR}/${set}.set" || fail=1 - fi - [ -f "${IPSET_DATA_DIR}/${set}.set" ] && chmod 600 "${IPSET_DATA_DIR}/${set}.set" - [ $fail -eq 1 ] && err "Cannot save set ${set}" && unset IFS && return 1 - done - touch ${IPSET_DATA_SAVED_FLAG} || { unset IFS; return 1; } - unset IFS - - # Done: remove backups - rm -rf ${IPSET_DATA_DIR_BACKUP} - rm -rf ${IPSET_DATA_COMPAT_BACKUP} - - return 0 -} - -# Generate a grep regexp matching abbreviated command forms. E.g., for create: -# \(c\|cr\|cre\|crea\|creat\|create\) -cmd_short_expr() { - out= - cmd_len=1 - while [ "${cmd_len}" -le "${#1}" ]; do - [ -z "${out}" ] && out='\(' || out="${out}"'\|' - # shellcheck disable=SC2003 # No POSIX equivalent to expr substr - out="${out}$(expr substr "${1}" 1 "${cmd_len}")" - cmd_len=$((cmd_len + 1)) - done - echo "${out}"'\)' -} - -ipset_restore() { - file="${1}" - - retfile="$(mktemp -q /tmp/ipset.XXXXXX)" - CLEAN_FILES="${CLEAN_FILES} ${retfile}" - - # If restore fails due to invalid lines, remove them and retry - while ! restore_err="$( (${IPSET_BIN} -f "${file}" -! restore 2>&1; echo $? >"${retfile}") | head -n1; exit "$(cat "${retfile}")" )"; do - warn "${restore_err}" - case ${restore_err#*: } in - "No command specified"*) - line="$(grep -m1 -n "^${restore_err##* }" "${file}")" - line="${line%:*}" - ;; - "Missing second mandatory argument to command "*) - cmd="${restore_err##* }" - cmd_expr="$(cmd_short_expr "${cmd}")" - line="$(grep -n '^'"${cmd_expr}" "${file}" | grep -m1 -v '^[0-9]\+\:'"${cmd_expr}"'[[:blank:]]\+[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+')" - line="${line%:*}" - ;; - "Missing mandatory argument to command "*) - cmd="${restore_err##* }" - cmd_expr="$(cmd_short_expr "${cmd}")" - line="$(grep -n '^'"${cmd_expr}" "${file}" | grep -m1 -v '^[0-9]\+\:'"${cmd_expr}"'[[:blank:]]\+[^[:blank:]]\+')" - line="${line%:*}" - ;; - "Command "*"is invalid in restore mode"*) - restore_err_cmd="${restore_err#*: }" - restore_err_cmd="${restore_err_cmd#*\`}" - restore_err_cmd="${restore_err_cmd%%\'*}" - cmd="${restore_err_cmd##* }" - cmd_expr="$(cmd_short_expr "${cmd}")" - line="$(grep -m1 -ne '^'"${cmd_expr}"'[[:blank:]]\+' -e '^'"${restore_err_cmd}"'$' "${file}")" - line="${line%:*}" - ;; - "Error in line "*) - line="${restore_err%: *}" - line="${line##* }" - ;; - *) - rm "${retfile}" - CLEAN_FILES="${CLEAN_FILES%* ${retfile}}" - return 1 - ;; - esac - - [ -z "${line}" ] && return 1 - - warn "Skipped invalid entry: $(sed "${line}q;d" "${file}")" - sed -i -e "${line}d" "${file}" - - [ -s "${file}" ] || return 1 - done - - rm "${retfile}" - CLEAN_FILES="${CLEAN_FILES%* ${retfile}}" -} - -load() { - if [ -f ${IPSET_DATA_SAVED_FLAG} ]; then - # If we have a cleanly saved directory with all sets, we can - # delete any left-overs and use it - rm -rf ${IPSET_DATA_DIR_BACKUP} - rm -f ${IPSET_DATA_COMPAT_BACKUP} - else - # If sets weren't cleanly saved, restore from backups - [ -d ${IPSET_DATA_DIR_BACKUP} ] && rm -rf ${IPSET_DATA_DIR} && mv -Tf ${IPSET_DATA_DIR_BACKUP} ${IPSET_DATA_DIR} - [ -f ${IPSET_DATA_COMPAT_BACKUP} ] && rm -f ${IPSET_DATA_COMPAT} && mv -Tf ${IPSET_DATA_COMPAT_BACKUP} ${IPSET_DATA_COMPAT} - fi - - if [ ! -d ${IPSET_DATA_DIR} ] && [ ! -f ${IPSET_DATA_COMPAT} ]; then - info "No existing configuration available, none loaded" - touch ${IPSET_RUN} - return - fi - - # Merge all sets into temporary file - merged="$(mktemp -q /tmp/ipset.XXXXXX)" - CLEAN_FILES="${CLEAN_FILES} ${merged}" - chmod 600 "${merged}" - set +f - if [ -d ${IPSET_DATA_DIR} ]; then - # Copy create commands from each saved set first, then the rest: - # list:set entries depend on other sets, so make sure they all - # get created first - for f in "${IPSET_DATA_DIR}"/*; do - [ "${f}" = "${IPSET_DATA_DIR}/*" ] && break - [ -f "${f}" ] || continue - grep '^c' "${f}" >> "${merged}" - done - for f in "${IPSET_DATA_DIR}"/*; do - [ "${f}" = "${IPSET_DATA_DIR}/*" ] && break - [ -f "${f}" ] || continue - grep -v '^c' "${f}" >> "${merged}" - done - fi - set -f - [ -f ${IPSET_DATA_COMPAT} ] && cat ${IPSET_DATA_COMPAT} >> "${merged}" - - # Drop sets that aren't in saved data, mark conflicts with existing sets - conflicts="" - IFS=" -" - for set in $(${IPSET_BIN} list -n -t); do - grep -q "^create ${set} " "${merged}" && conflicts="${conflicts}|${set}" && continue - - # We can't destroy the set if it's in use, flush it instead - if ! ${IPSET_BIN} destroy "${set}" 2>/dev/null; then - ${IPSET_BIN} flush "${set}" - fi - done - unset IFS - conflicts="${conflicts#|*}" - - # Common case: if we have no conflicts, just restore in one shot - if [ -z "${conflicts}" ]; then - if ! ipset_restore "${merged}"; then - err "Failed to restore configured sets" - exit 1 - fi - rm "${merged}" - CLEAN_FILES="${CLEAN_FILES%* ${merged}}" - touch ${IPSET_RUN} - return - fi - - # Find a salt for md5sum that makes names of saved sets unique - salt=0 - while true; do - unique=1 - IFS=" -" - for set in $(${IPSET_BIN} list -n -t); do - if grep -q "^create $(echo "${salt}${set}" | md5sum | head -c31) " "${merged}"; then - unique=0 - break - fi - done - unset IFS - [ ${unique} -eq 1 ] && break - salt=$((salt + 1)) - done - - # Add sets, mangling names for conflicting sets - mangled="$(mktemp -q /tmp/ipset.XXXXXX)" - CLEAN_FILES="${CLEAN_FILES} ${mangled}" - chmod 600 "${mangled}" - - cat "${merged}" > "${mangled}" - IFS='|' - for set in ${conflicts}; do - new_name=$(echo "${salt}${set}" | md5sum | head -c31) - echo "s/^(add|create) $set /\1 $new_name /" - done | sed -i -r -f - "${mangled}" - unset IFS - if ! ipset_restore "${mangled}"; then - err "Failed to restore configured sets" - exit 1 - fi - - rm "${mangled}" - CLEAN_FILES="${CLEAN_FILES%* ${mangled}}" - - # Swap and delete old sets - IFS='|' - for set in ${conflicts}; do - mangled="$(echo "${salt}${set}" | md5sum | head -c31)" - if ! ${IPSET_BIN} swap "${set}" "${mangled}" 2>/dev/null; then - # This fails if set types are different: try to destroy - # existing set - if ! ${IPSET_BIN} destroy "${set}" 2>/dev/null; then - # Conflicting set is in use, we can only warn - # and flush the existing set - err "Cannot load set \"${set}\", set with same name and conflicting type in use" - ${IPSET_BIN} flush "${set}" - ${IPSET_BIN} destroy "${mangled}" - else - ${IPSET_BIN} rename "${mangled}" "${set}" - fi - else - ${IPSET_BIN} destroy "${mangled}" - fi - done - unset IFS - - rm "${merged}" - CLEAN_FILES="${CLEAN_FILES%* ${merged}}" - touch ${IPSET_RUN} -} - -cleanup() { - ${IPSET_BIN} flush || err "Failed to flush sets" - - # Try to destroy all sets at once. This will fail if some are in use, - # destroy all the other ones in that case - ${IPSET_BIN} destroy 2>/dev/null && return - IFS=" -" - for set in $(${IPSET_BIN} list -n -t); do - if ! ${IPSET_BIN} destroy "${set}"; then - err "Failed to destroy set ${set}" - fi - done - unset IFS + return 0 } stop() { - [ -f ${IPSET_RUN} ] || { info "Not running"; return 0; } - [ "${IPSET_SAVE_ON_STOP}" = "yes" ] && { save || err "Failed to save sets"; } + # Nothing to stop if ip_set module is not loaded. + lsmod | grep -q "^ip_set " + [[ $? -ne 0 ]] && return 6 - # Nothing to stop if the ip_set module is not loaded - lsmod | grep -q "^ip_set " || { info "Not running"; rm ${IPSET_RUN}; return 0; } + flush_n_delete + [[ $? -ne 0 ]] && echo Warning: Not all sets were flushed/deleted - # If the xt_set module is in use, then iptables is using ipset, so - # refuse to stop the service - if mod="$(lsmod | grep ^xt_set)"; then - if [ "$(echo "${mod}" | tr -s ' ' | cut -d' ' -f3)" != "0" ]; then - err "Current iptables configuration requires ipset" && return 1 - fi - fi - - cleanup - - rm ${IPSET_RUN} - return 0 + return 0 } -lock +save() { + # Do not save if ip_set module is not loaded. + lsmod | grep -q "^ip_set " + [[ $? -ne 0 ]] && return 6 + + [[ -z $(${IPSET_BIN} list -name) ]] && return 0 + + ret=0 + TMP_FILE=$(/bin/mktemp -q /tmp/$IPSET.XXXXXX) \ + && CLEAN_FILES+=" $TMP_FILE" \ + && chmod 600 "$TMP_FILE" \ + && ${IPSET_BIN} save > $TMP_FILE 2>/dev/null \ + && [[ -s $TMP_FILE ]] \ + || ret=1 + + if [[ $ret -eq 0 ]]; then + # No need to do anything if the files are the same + if [[ ! -f $IPSET_DATA ]]; then + mv $TMP_FILE $IPSET_DATA && chmod 600 $IPSET_DATA || ret=1 + else + diff -q $TMP_FILE $IPSET_DATA >/dev/null + + if [[ $? -ne 0 ]]; then + if [[ -f $IPSET_DATA ]]; then + cp -f --preserve=timestamps $IPSET_DATA $IPSET_DATA.save \ + && chmod 600 $IPSET_DATA.save \ + || ret=1 + fi + if [[ $ret -eq 0 ]]; then + cp -f --preserve=timestamps $TMP_FILE $IPSET_DATA \ + && chmod 600 $IPSET_DATA \ + || ret=1 + fi + fi + fi + fi + + rm -f $TMP_FILE + return $ret +} + + case "$1" in -start) - load + start) + start + RETVAL=$? ;; -stop) + stop) + check_can_unload || exit 1 + [[ $IPSET_SAVE_ON_STOP = yes ]] && save stop + RETVAL=$? + [[ $RETVAL -eq 6 ]] && echo "${IPSET}: not running" && exit 0 ;; -reload) - cleanup - load + reload) + [[ $IPSET_SAVE_ON_RESTART = yes ]] && save + stop + RETVAL=$? + [[ $RETVAL -eq 6 ]] && echo "${IPSET}: not running" && exit 0 + start + RETVAL=$? ;; -save) - save - ;; -*) - info "Usage: $0 {start|stop|reload|save}" + *) + echo "Usage: $IPSET {start|stop|reload}" >&2 exit 1 esac -exit $? +exit $RETVAL diff --git a/sources b/sources index 66b03f3..5f9c0bc 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (ipset-7.24.tar.bz2) = 18ccb49bd38083f0556b11e1d17f43791c52a2b094c9a500b6f770796b17e8e70c3860a628eac2252eb672b1fc9de734d3a0e0823d61dd9be7b4188adc6dd214 +fd8ea35997115c5c630eee22f0beecec ipset-6.29.tar.bz2 diff --git a/tests/sanity-tests/Makefile b/tests/sanity-tests/Makefile deleted file mode 100644 index b11121b..0000000 --- a/tests/sanity-tests/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Makefile of /CoreOS/ipset -# Description: Test if ipset working ok -# Author: Susant Sahani -# -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -export TEST=/CoreOS/ipset -export TESTVERSION=1.0 -BUILT_FILES= -FILES=$(METADATA) runtest.sh Makefile -.PHONY: all install download clean -run: $(FILES) build - ./runtest.sh -build: $(BUILT_FILES) - test -x runtest.sh || chmod a+x runtest.sh -clean: - rm -f *~ $(BUILT_FILES) -include /usr/share/rhts/lib/rhts-make.include -$(METADATA): Makefile - @echo "Owner: Susant Sahani" > $(METADATA) - @echo "Name: $(TEST)" >> $(METADATA) - @echo "TestVersion: $(TESTVERSION)" >> $(METADATA) - @echo "Path: $(TEST_DIR)" >> $(METADATA) - @echo "Description: Test ipset sanity" >> $(METADATA) - @echo "Type: Sanity" >> $(METADATA) - @echo "TestTime: 5m" >> $(METADATA) - @echo "RunFor: ipset " >> $(METADATA) - @echo "Requires: ipset iperf3 python3 systemd python3-pyroute2 iptables" >> $(METADATA) - @echo "Priority: Normal" >> $(METADATA) - @echo "License: GPLv2" >> $(METADATA) - @echo "Confidential: no" >> $(METADATA) - @echo "Destructive: no" >> $(METADATA) - @echo "Releases: -Fedora 29" >> $(METADATA) - rhts-lint $(METADATA) diff --git a/tests/sanity-tests/iperf3d.service b/tests/sanity-tests/iperf3d.service deleted file mode 100644 index 179f317..0000000 --- a/tests/sanity-tests/iperf3d.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=iperf3d tests for ipset -After=multi-user.target network.target - -[Service] -Type=simple -ExecStart=/usr/bin/iperf3 -s -d --bind 192.168.225.32 --port 55555 -V - -[Install] -WantedBy=multi-user.target diff --git a/tests/sanity-tests/ipset-tests.py b/tests/sanity-tests/ipset-tests.py deleted file mode 100755 index 9eccd06..0000000 --- a/tests/sanity-tests/ipset-tests.py +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: LGPL-2.1+ -# ~~~ -# Description: Tests for ipset -# -# Author: Susant Sahani -# Copyright (c) 2018 Red Hat, Inc. -# ~~~ - -import errno -import os -import sys -import time -import unittest -import subprocess -import signal -import shutil -import socket -from pyroute2 import IPRoute - -def setUpModule(): - - if shutil.which('ipset') is None: - raise OSError(errno.ENOENT, 'ipset not found') - - if shutil.which('iperf3') is None: - raise OSError(errno.ENOENT, 'iperf3 not found') - -def tearDownModule(): - pass - -class GenericUtilities(): - - def SetupVethInterface(self): - - ip = IPRoute() - - ip.link('add', ifname='veth-test', peer='veth-peer', kind='veth') - idx_veth_test = ip.link_lookup(ifname='veth-test')[0] - idx_veth_peer = ip.link_lookup(ifname='veth-peer')[0] - - ip.link('set', index=idx_veth_test, address='02:01:02:03:04:08') - ip.link('set', index=idx_veth_peer, address='02:01:02:03:04:09') - - ip.addr('add', index=idx_veth_test, address='192.168.225.32', mask=24) - ip.addr('add', index=idx_veth_peer, address='192.168.225.33', mask=24) - - ip.link('set', index=idx_veth_test, state='up') - ip.link('set', index=idx_veth_peer, state='up') - - ip.close() - - def TearDownVethInterface(self): - - ip = IPRoute() - ip.link('del', index=ip.link_lookup(ifname='veth-test')[0]) - ip.close() - - def AddAddress(self, interface, address): - ip = IPRoute() - - idx_veth_peer = ip.link_lookup(ifname=interface)[0] - ip.close() - - def IPSetAdd(self, hashset, address): - subprocess.check_output(['ipset', 'add', hashset, address]) - - def IPSetRemove(self, hashset, address): - subprocess.check_output(['ipset', 'del', hashset, address]) - - def IPSetCreateHashSet(self, hashset, hashtype): - subprocess.check_output(['ipset', 'create', hashset, hashtype]) - - def IPSetDestroyHashSet(self, hashset): - subprocess.check_output(['ipset', 'destroy', hashset]) - -class IpsetTests(unittest.TestCase, GenericUtilities): - - def setUp(self): - self.SetupVethInterface() - - def tearDown(self): - self.TearDownVethInterface() - - def test_ipset_bitmap_ip_netfilter(self): - - self.IPSetCreateHashSet('testnetiperf', 'hash:ip') - - self.IPSetAdd('testnetiperf', '192.168.225.32') - self.IPSetAdd('testnetiperf', '192.168.225.33') - - subprocess.check_output(['ipset', 'test','testnetiperf','192.168.225.32']) - subprocess.check_output(['ipset', 'test','testnetiperf','192.168.225.33']) - - subprocess.check_output(['systemctl', 'start', 'iperf3d.service']) - time.sleep(5) - - r = subprocess.call("iperf3" + " -c 192.168.225.32 -p 55555 --connect-timeout 5", shell=True) - self.assertEqual(r, 0) - - r = subprocess.call("iptables" + " -I INPUT -m set --match-set testnetiperf src -j DROP", shell=True) - self.assertEqual(r, 0) - - r = subprocess.call("iperf3" + " -c 192.168.225.32 -p 55555 --connect-timeout 5", shell=True) - self.assertNotEqual(r, 0) - - subprocess.check_output(['systemctl', 'stop', 'iperf3d.service']) - - subprocess.call("iptables" + " --delete INPUT -m set --match-set testnetiperf src -j DROP" , shell=True) - - self.IPSetDestroyHashSet('testnetiperf') - - def test_ipset_add_bitmap_ip(self): - - self.IPSetCreateHashSet('testnet', 'hash:ip') - - self.IPSetAdd('testnet', '192.168.11.12') - self.IPSetAdd('testnet', '192.168.11.13') - self.IPSetAdd('testnet', '192.168.11.14') - self.IPSetAdd('testnet', '192.168.11.15') - - subprocess.check_output(['ipset', 'test','testnet','192.168.11.12']) - subprocess.check_output(['ipset', 'test','testnet','192.168.11.13']) - subprocess.check_output(['ipset', 'test','testnet','192.168.11.14']) - subprocess.check_output(['ipset', 'test','testnet','192.168.11.15']) - - self.IPSetDestroyHashSet('testnet') - - def test_ipset_delete_bitmap_ip(self): - - self.IPSetCreateHashSet('testnet', 'hash:ip') - - self.IPSetAdd('testnet', '192.168.11.12') - self.IPSetAdd('testnet', '192.168.11.13') - - subprocess.check_output(['ipset', 'test','testnet','192.168.11.12']) - subprocess.check_output(['ipset', 'test','testnet','192.168.11.13']) - - self.IPSetRemove('testnet', '192.168.11.12') - - r = subprocess.call("ipset" + " test testnet 192.168.11.12", shell=True) - self.assertEqual(r, 1) - - self.IPSetDestroyHashSet('testnet') - - def test_ipset_hash_bitmap_mac(self): - - self.IPSetCreateHashSet('testmac', 'hash:mac') - - self.IPSetAdd('testmac', '02:01:02:03:04:09') - - subprocess.check_output(['ipset', 'test','testmac','02:01:02:03:04:09']) - - self.IPSetRemove('testmac', '02:01:02:03:04:09') - - r = subprocess.call("ipset" + " test testmac 02:01:02:03:04:09", shell=True) - self.assertEqual(r, 1) - - self.IPSetDestroyHashSet('testmac') - - def test_ipset_hash_bitmap_ipport(self): - - self.IPSetCreateHashSet('testipport', 'hash:ip,mac') - - self.IPSetAdd('testipport', '1.1.1.1,02:01:02:03:04:09') - - subprocess.check_output(['ipset', 'test','testipport','1.1.1.1,02:01:02:03:04:09']) - - self.IPSetRemove('testipport', '1.1.1.1,02:01:02:03:04:09') - - r = subprocess.call("ipset" + " test testipport 1.1.1.1,02:01:02:03:04:09", shell=True) - self.assertEqual(r, 1) - - self.IPSetDestroyHashSet('testipport') - - def test_ipset_hash_bitmap_ipport(self): - - self.IPSetCreateHashSet('testipport', 'hash:ip,port') - - self.IPSetAdd('testipport', '192.168.1.1,udp:53') - self.IPSetAdd('testipport', '192.168.1.1,5555') - - subprocess.check_output(['ipset', 'test','testipport','192.168.1.1,udp:53']) - subprocess.check_output(['ipset', 'test','testipport','192.168.1.1,5555']) - - self.IPSetRemove('testipport', '192.168.1.1,5555') - - r = subprocess.call("ipset" + " test testipport 192.168.1.1,5555", shell=True) - self.assertEqual(r, 1) - - self.IPSetDestroyHashSet('testipport') - - def test_ipset_hash_bitmap_ipportip(self): - - self.IPSetCreateHashSet('testipportip', 'hash:ip,port,ip') - - self.IPSetAdd('testipportip', '192.168.1.1,80,10.0.0.1') - self.IPSetAdd('testipportip', '192.168.1.2,80,10.0.0.2') - - subprocess.check_output(['ipset', 'test','testipportip','192.168.1.1,80,10.0.0.1']) - subprocess.check_output(['ipset', 'test','testipportip','192.168.1.1,80,10.0.0.1']) - - self.IPSetRemove('testipportip', '192.168.1.1,80,10.0.0.1') - - r = subprocess.call("ipset" + " test testipportip 192.168.1.1,80,10.0.0.1", shell=True) - self.assertEqual(r, 1) - - self.IPSetDestroyHashSet('testipportip') - - def test_ipset_hash_bitmap_netiface(self): - - self.IPSetCreateHashSet('testnetiface', 'hash:net,iface') - - self.IPSetAdd('testnetiface', '192.168.0/24,veth-test') - self.IPSetAdd('testnetiface', '192.167.0/24,veth-peer') - - subprocess.check_output(['ipset', 'test','testnetiface','192.168.0/24,veth-test']) - subprocess.check_output(['ipset', 'test','testnetiface','192.167.0/24,veth-peer']) - - self.IPSetRemove('testnetiface', '192.168.0/24,veth-test') - - r = subprocess.call("ipset" + " test testnetiface 192.168.0/24,veth-test", shell=True) - self.assertEqual(r, 1) - - self.IPSetDestroyHashSet('testnetiface') - -if __name__ == '__main__': - unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=3)) diff --git a/tests/sanity-tests/runtest.sh b/tests/sanity-tests/runtest.sh deleted file mode 100755 index 78f525d..0000000 --- a/tests/sanity-tests/runtest.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: LGPL-2.1+ -# ~~~ -# runtest.sh of ipset -# Description: ipset tests. -# -# Author: Susant Sahani -# Copyright (c) 2018 Red Hat, Inc. -# ~~~ - -# Include Beaker environment -. /usr/share/beakerlib/beakerlib.sh || exit 1 - -PACKAGE="ipset" - -SERVICE_UNITDIR="/var/run/systemd/system" - -rlJournalStart - rlPhaseStartSetup - rlAssertRpm $PACKAGE - rlRun "systemctl stop firewalld" 0,5 - rlRun "setenforce 0" 0,1 - - rlRun "[ -e /sys/class/net/veth-test ] && ip link del veth-test" 0,1 - - rlRun "cp iperf3d.service $SERVICE_UNITDIR" - rlRun "cp ipset-tests.py /usr/bin/" - - rlRun "systemctl daemon-reload" - rlPhaseEnd - - rlPhaseStartTest - rlLog "Starting ipset tests ..." - rlRun "/usr/bin/python3 /usr/bin/ipset-tests.py" - rlPhaseEnd - - rlPhaseStartCleanup - rlRun "rm /usr/bin/ipset-tests.py" - rlRun "[ -e /sys/class/net/veth-test ] && ip link del veth-test" 0,1 - - rlRun "rm $SERVICE_UNITDIR/iperf3d.service" - rlRun "systemctl daemon-reload" - - rlRun "setenforce 1" 0,1 - rlLog "ipset tests done" - rlPhaseEnd -rlJournalPrintText -rlJournalEnd - -rlGetTestState diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 17d20d6..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,15 +0,0 @@ -- hosts: localhost - roles: - - role: standard-test-beakerlib - tags: - - classic - tests: - - sanity-tests - required_packages: - - ipset - - iptables - - python3 - - systemd - - iproute - - iperf3 - - python3-pyroute2