banIP: update 1.5.6-3
authorDirk Brenken <[email protected]>
Sat, 31 May 2025 20:09:28 +0000 (22:09 +0200)
committerDirk Brenken <[email protected]>
Sat, 31 May 2025 20:09:49 +0000 (22:09 +0200)
* add json reporting cache
* fixed the fetchcmd autodetection
* sanitize json reporting output
* small fixes and improvements

Signed-off-by: Dirk Brenken <[email protected]>
net/banip/Makefile
net/banip/files/banip-functions.sh

index 8f9c6bc5785d22429cd20c0bda29a716e87cd7f8..4ba4d6775d6b110c9e57827c5c77fbae284325bf 100644 (file)
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=banip
 PKG_VERSION:=1.5.6
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 PKG_LICENSE:=GPL-3.0-or-later
 PKG_MAINTAINER:=Dirk Brenken <[email protected]>
 
index 24394623af248468adac330254f5fa953cd1d67f..65bb249fe206e0ae7381e229675be915f69de9b8 100644 (file)
@@ -324,25 +324,25 @@ f_actual() {
 # get fetch utility
 #
 f_getfetch() {
-       local util utils insecure update="0"
+       local fetch fetch_list insecure update="0"
 
        ban_fetchcmd="$(command -v "${ban_fetchcmd}")"
        if { [ "${ban_autodetect}" = "1" ] && [ -z "${ban_fetchcmd}" ]; } || [ ! -x "${ban_fetchcmd}" ]; then
-               utils="curl wget-ssl libustream-openssl libustream-wolfssl libustream-mbedtls"
-               for util in ${utils}; do
-                       if printf "%s" "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e "@.packages[\"${util}\"]" >/dev/null 2>&1; then
-                               case "${util}" in
+               fetch_list="curl wget-ssl libustream-openssl libustream-wolfssl libustream-mbedtls"
+               for fetch in ${fetch_list}; do
+                       if printf "%s" "${ban_packages}" | "${ban_grepcmd}" -q "\"${fetch}"; then
+                               case "${fetch}" in
                                        "wget-ssl")
-                                               util="wget"
+                                               fetch="wget"
                                                ;;
                                        "libustream-openssl" | "libustream-wolfssl" | "libustream-mbedtls")
-                                               util="uclient-fetch"
+                                               fetch="uclient-fetch"
                                                ;;
                                esac
-                               if [ -x "$(command -v "${util}")" ]; then
+                               if [ -x "$(command -v "${fetch}")" ]; then
                                        update="1"
-                                       ban_fetchcmd="$(command -v "${util}")"
-                                       uci_set banip global ban_fetchcmd "${util}"
+                                       ban_fetchcmd="$(command -v "${fetch}")"
+                                       uci_set banip global ban_fetchcmd "${fetch}"
                                        uci_commit "banip"
                                        break
                                fi
@@ -1441,297 +1441,299 @@ f_report() {
        report_txt="${ban_reportdir}/ban_report.txt"
        map_jsn="${ban_reportdir}/ban_map.jsn"
 
-       # json output preparation
-       #
-       : >"${report_jsn}"
-       : >"${map_jsn}"
-       table_json="$("${ban_nftcmd}" -tj list table inet banIP 2>/dev/null)"
-       table_sets="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')"
-       sum_sets="0"
-       sum_cntelements="0"
-       sum_setinbound="0"
-       sum_setoutbound="0"
-       sum_cntinbound="0"
-       sum_cntoutbound="0"
-       sum_setports="0"
-       sum_setelements="0"
-       sum_synflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_synflood"].*.packets')"
-       sum_udpflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_udpflood"].*.packets')"
-       sum_icmpflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_icmpflood"].*.packets')"
-       sum_ctinvalid="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_ctinvalid"].*.packets')"
-       sum_tcpinvalid="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_tcpinvalid"].*.packets')"
-       timestamp="$(date "+%Y-%m-%d %H:%M:%S")"
+       if [ "${output}" != "json" ]; then
+               # json output preparation
+               #
+               : >"${report_jsn}"
+               : >"${map_jsn}"
+               table_json="$("${ban_nftcmd}" -tj list table inet banIP 2>/dev/null)"
+               table_sets="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')"
+               sum_sets="0"
+               sum_cntelements="0"
+               sum_setinbound="0"
+               sum_setoutbound="0"
+               sum_cntinbound="0"
+               sum_cntoutbound="0"
+               sum_setports="0"
+               sum_setelements="0"
+               sum_synflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_synflood"].*.packets')"
+               sum_udpflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_udpflood"].*.packets')"
+               sum_icmpflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_icmpflood"].*.packets')"
+               sum_ctinvalid="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_ctinvalid"].*.packets')"
+               sum_tcpinvalid="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_tcpinvalid"].*.packets')"
+               timestamp="$(date "+%Y-%m-%d %H:%M:%S")"
 
-       cnt="1"
-       for item in ${table_sets}; do
-               (
-                       set_json="$("${ban_nftcmd}" -j list set inet banIP "${item}" 2>/dev/null)"
-                       set_cnt="$(printf "%s" "${set_json}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | "${ban_wccmd}" -l 2>/dev/null)"
-                       set_cntinbound=""
-                       set_cntoutbound=""
-                       set_inbound=""
-                       set_outbound=""
-                       set_proto=""
-                       set_dport=""
-                       set_elements=""
-                       for chain in _inbound _outbound; do
-                               for expr in 0 1 2; do
-                                       if [ "${chain}" = "_inbound" ] && [ -z "${set_cntinbound}" ]; then
-                                               set_cntinbound="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")"
-                                       elif [ "${chain}" = "_outbound" ] && [ -z "${set_cntoutbound}" ]; then
-                                               set_cntoutbound="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")"
-                                       fi
-                                       [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[0].match.right.set")"
-                                       [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.left.payload.protocol")"
-                                       [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right.set")"
-                                       [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right")"
-                                       [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right.set")"
-                                       [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right")"
-                               done
-                       done
-                       if [ -n "${set_proto}" ] && [ -n "${set_dport}" ]; then
-                               set_proto="${set_proto//[\{\}\":]/}"
-                               set_proto="${set_proto#\[ *}"
-                               set_proto="${set_proto%* \]}"
-                               set_dport="${set_dport//[\{\}\":]/}"
-                               set_dport="${set_dport#\[ *}"
-                               set_dport="${set_dport%* \]}"
-                               set_dport="${set_proto}: $(f_trim "${set_dport}")"
-                       fi
-                       if [ "${ban_nftcount}" = "1" ]; then
-                               set_elements="$(printf "%s" "${set_json}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*][@.counter.packets>0].val' |
-                                       "${ban_awkcmd}" -F '[ ,]' '{ORS=" ";if($2=="\"range\":")printf"%s, ",$4;else if($2=="\"prefix\":")printf"%s, ",$5;else printf"\"%s\", ",$1}')"
-                       fi
-                       if [ -n "${set_cntinbound}" ]; then
-                               set_inbound="ON"
-                       else
-                               set_inbound="-"
+               cnt="1"
+               for item in ${table_sets}; do
+                       (
+                               set_json="$("${ban_nftcmd}" -j list set inet banIP "${item}" 2>/dev/null)"
+                               set_cnt="$(printf "%s" "${set_json}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | "${ban_wccmd}" -l 2>/dev/null)"
                                set_cntinbound=""
-                       fi
-                       if [ -n "${set_cntoutbound}" ]; then
-                               set_outbound="ON"
-                       else
-                               set_outbound="-"
                                set_cntoutbound=""
-                       fi
-                       if [ "${cnt}" = "1" ]; then
-                               printf "%s\n" "{ \"sets\":{ \"${item}\":{ \"cnt_elements\": \"${set_cnt}\", \"cnt_inbound\": \"${set_cntinbound}\", \"inbound\": \"${set_inbound}\", \"cnt_outbound\": \"${set_cntoutbound}\", \"outbound\": \"${set_outbound}\", \"port\": \"${set_dport:-"-"}\", \"set_elements\": [ ${set_elements%%??} ] }" >>"${report_jsn}"
-                       else
-                               printf "%s\n" ", \"${item}\":{ \"cnt_elements\": \"${set_cnt}\", \"cnt_inbound\": \"${set_cntinbound}\", \"inbound\": \"${set_inbound}\", \"cnt_outbound\": \"${set_cntoutbound}\", \"outbound\": \"${set_outbound}\", \"port\": \"${set_dport:-"-"}\", \"set_elements\": [ ${set_elements%%??} ] }" >>"${report_jsn}"
-                       fi
-               ) &
-               [ "${cnt}" -eq "1" ] || [ "${cnt}" -gt "${ban_cores}" ] && wait -n
-               cnt="$((cnt + 1))"
-       done
-       wait
-       printf "\n%s\n" "} }" >>"${report_jsn}"
-
-       # add sum statistics
-       #
-       json_init
-       if json_load_file "${report_jsn}" >/dev/null 2>&1; then
-               json_select "sets" >/dev/null 2>&1
-               json_get_keys table_sets >/dev/null 2>&1
-               if [ -n "${table_sets}" ]; then
-                       for item in ${table_sets}; do
-                               sum_sets="$((sum_sets + 1))"
-                               json_select "${item}"
-                               json_get_keys set_details
-                               for detail in ${set_details}; do
-                                       case "${detail}" in
-                                               "cnt_elements")
-                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                       sum_cntelements="$((sum_cntelements + jsnval))"
-                                                       ;;
-                                               "set_elements")
-                                                       json_get_values jsnval "${detail}" >/dev/null 2>&1
-                                                       if [ -n "${jsnval}" ]; then
-                                                               jsnval="$(printf "%s" "${jsnval}" | "${ban_wccmd}" -w)"
-                                                               sum_setelements="$((sum_setelements + jsnval))"
-                                                       fi
-                                                       ;;
-                                               "inbound")
-                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                       if [ "${jsnval}" = "ON" ]; then
-                                                               sum_setinbound="$((sum_setinbound + 1))"
-                                                       fi
-                                                       ;;
-                                               "outbound")
-                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                       if [ "${jsnval}" = "ON" ]; then
-                                                               sum_setoutbound="$((sum_setoutbound + 1))"
-                                                       fi
-                                                       ;;
-                                               "cnt_inbound")
-                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                       if [ -n "${jsnval}" ]; then
-                                                               sum_cntinbound="$((sum_cntinbound + jsnval))"
-                                                       fi
-                                                       ;;
-                                               "cnt_outbound")
-                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                       if [ -n "${jsnval}" ]; then
-                                                               sum_cntoutbound="$((sum_cntoutbound + jsnval))"
-                                                       fi
-                                                       ;;
-                                               "port")
-                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                       if [ "${jsnval}" != "-" ]; then
-                                                               jsnval="${jsnval//[^0-9 ]/}"
-                                                               jsnval="$(printf "%s" "${jsnval}" | "${ban_wccmd}" -w)"
-                                                               sum_setports="$((sum_setports + jsnval))"
-                                                       fi
-                                                       ;;
-                                       esac
+                               set_inbound=""
+                               set_outbound=""
+                               set_proto=""
+                               set_dport=""
+                               set_elements=""
+                               for chain in _inbound _outbound; do
+                                       for expr in 0 1 2; do
+                                               if [ "${chain}" = "_inbound" ] && [ -z "${set_cntinbound}" ]; then
+                                                       set_cntinbound="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")"
+                                               elif [ "${chain}" = "_outbound" ] && [ -z "${set_cntoutbound}" ]; then
+                                                       set_cntoutbound="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")"
+                                               fi
+                                               [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[0].match.right.set")"
+                                               [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.left.payload.protocol")"
+                                               [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right.set")"
+                                               [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right")"
+                                               [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right.set")"
+                                               [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right")"
+                                       done
                                done
-                               json_select ".."
-                       done
-                       "${ban_sedcmd}" -i ':a;$!N;1,1ba;P;$d;D' "${report_jsn}"
-                       printf "%s\n" "}, \"timestamp\": \"${timestamp}\", \"autoadd_allow\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_allowlist}")\", \"autoadd_block\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_blocklist}")\", \"sum_synflood\": \"${sum_synflood}\", \"sum_udpflood\": \"${sum_udpflood}\", \"sum_icmpflood\": \"${sum_icmpflood}\", \"sum_ctinvalid\": \"${sum_ctinvalid}\", \"sum_tcpinvalid\": \"${sum_tcpinvalid}\", \"sum_sets\": \"${sum_sets}\", \"sum_setinbound\": \"${sum_setinbound}\", \"sum_setoutbound\": \"${sum_setoutbound}\", \"sum_cntelements\": \"${sum_cntelements}\", \"sum_cntinbound\": \"${sum_cntinbound}\", \"sum_cntoutbound\": \"${sum_cntoutbound}\", \"sum_setports\": \"${sum_setports}\", \"sum_setelements\": \"${sum_setelements}\" }" >>"${report_jsn}"
-               fi
-       fi
+                               if [ -n "${set_proto}" ] && [ -n "${set_dport}" ]; then
+                                       set_proto="${set_proto//[\{\}\":]/}"
+                                       set_proto="${set_proto#\[ *}"
+                                       set_proto="${set_proto%* \]}"
+                                       set_dport="${set_dport//[\{\}\":]/}"
+                                       set_dport="${set_dport#\[ *}"
+                                       set_dport="${set_dport%* \]}"
+                                       set_dport="${set_proto}: $(f_trim "${set_dport}")"
+                               fi
+                               if [ "${ban_nftcount}" = "1" ]; then
+                                       set_elements="$(printf "%s" "${set_json}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*][@.counter.packets>0].val' |
+                                               "${ban_awkcmd}" -F '[ ,]' '{ORS=" ";if($2=="\"range\":")printf"%s, ",$4;else if($2=="\"prefix\":")printf"%s, ",$5;else printf"\"%s\", ",$1}')"
+                               fi
+                               if [ -n "${set_cntinbound}" ]; then
+                                       set_inbound="ON"
+                               else
+                                       set_inbound="-"
+                                       set_cntinbound=""
+                               fi
+                               if [ -n "${set_cntoutbound}" ]; then
+                                       set_outbound="ON"
+                               else
+                                       set_outbound="-"
+                                       set_cntoutbound=""
+                               fi
+                               if [ "${cnt}" = "1" ]; then
+                                       printf "%s\n" "{ \"sets\":{ \"${item}\":{ \"cnt_elements\": \"${set_cnt}\", \"cnt_inbound\": \"${set_cntinbound}\", \"inbound\": \"${set_inbound}\", \"cnt_outbound\": \"${set_cntoutbound}\", \"outbound\": \"${set_outbound}\", \"port\": \"${set_dport:-"-"}\", \"set_elements\": [ ${set_elements%%??} ] }" >>"${report_jsn}"
+                               else
+                                       printf "%s\n" ", \"${item}\":{ \"cnt_elements\": \"${set_cnt}\", \"cnt_inbound\": \"${set_cntinbound}\", \"inbound\": \"${set_inbound}\", \"cnt_outbound\": \"${set_cntoutbound}\", \"outbound\": \"${set_outbound}\", \"port\": \"${set_dport:-"-"}\", \"set_elements\": [ ${set_elements%%??} ] }" >>"${report_jsn}"
+                               fi
+                       ) &
+                       [ "${cnt}" -eq "1" ] || [ "${cnt}" -gt "${ban_cores}" ] && wait -n
+                       cnt="$((cnt + 1))"
+               done
+               wait
+               printf "\n%s\n" "} }" >>"${report_jsn}"
 
-       # retrieve/prepare map data
-       #
-       if [ "${ban_nftcount}" = "1" ] && [ "${ban_map}" = "1" ] && [ "${output}" = "json" ] && [ -s "${report_jsn}" ]; then
-               cnt="1"
-               f_getfetch
+               # add sum statistics
+               #
                json_init
-               if json_load_file "${ban_rtfile}" >/dev/null 2>&1; then
-                       json_get_values jsnval "active_uplink" >/dev/null 2>&1
-                       jsnval="${jsnval//\/[0-9][0-9]/}"
-                       jsnval="${jsnval//\/[0-9]/}"
-                       jsnval="\"${jsnval// /\", \"}\""
-                       if [ "${jsnval}" != '""' ]; then
-                               {
-                                       printf "%s" ",[{}"
-                                       "${ban_fetchcmd}" ${ban_geoparm} "[ ${jsnval} ]" "${ban_geourl}" 2>/dev/null |
-                                               "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="homeIP" '{printf ",{\"%s\": %s}\n",feed,$0}'
-                               } >>"${map_jsn}"
+               if json_load_file "${report_jsn}" >/dev/null 2>&1; then
+                       json_select "sets" >/dev/null 2>&1
+                       json_get_keys table_sets >/dev/null 2>&1
+                       if [ -n "${table_sets}" ]; then
+                               for item in ${table_sets}; do
+                                       sum_sets="$((sum_sets + 1))"
+                                       json_select "${item}"
+                                       json_get_keys set_details
+                                       for detail in ${set_details}; do
+                                               case "${detail}" in
+                                                       "cnt_elements")
+                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                               sum_cntelements="$((sum_cntelements + jsnval))"
+                                                               ;;
+                                                       "set_elements")
+                                                               json_get_values jsnval "${detail}" >/dev/null 2>&1
+                                                               if [ -n "${jsnval}" ]; then
+                                                                       jsnval="$(printf "%s" "${jsnval}" | "${ban_wccmd}" -w)"
+                                                                       sum_setelements="$((sum_setelements + jsnval))"
+                                                               fi
+                                                               ;;
+                                                       "inbound")
+                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                               if [ "${jsnval}" = "ON" ]; then
+                                                                       sum_setinbound="$((sum_setinbound + 1))"
+                                                               fi
+                                                               ;;
+                                                       "outbound")
+                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                               if [ "${jsnval}" = "ON" ]; then
+                                                                       sum_setoutbound="$((sum_setoutbound + 1))"
+                                                               fi
+                                                               ;;
+                                                       "cnt_inbound")
+                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                               if [ -n "${jsnval}" ]; then
+                                                                       sum_cntinbound="$((sum_cntinbound + jsnval))"
+                                                               fi
+                                                               ;;
+                                                       "cnt_outbound")
+                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                               if [ -n "${jsnval}" ]; then
+                                                                       sum_cntoutbound="$((sum_cntoutbound + jsnval))"
+                                                               fi
+                                                               ;;
+                                                       "port")
+                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                               if [ "${jsnval}" != "-" ]; then
+                                                                       jsnval="${jsnval//[^0-9 ]/}"
+                                                                       jsnval="$(printf "%s" "${jsnval}" | "${ban_wccmd}" -w)"
+                                                                       sum_setports="$((sum_setports + jsnval))"
+                                                               fi
+                                                               ;;
+                                               esac
+                                       done
+                                       json_select ".."
+                               done
+                               "${ban_sedcmd}" -i ':a;$!N;1,1ba;P;$d;D' "${report_jsn}"
+                               printf "%s\n" "}, \"timestamp\": \"${timestamp}\", \"autoadd_allow\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_allowlist}")\", \"autoadd_block\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_blocklist}")\", \"sum_synflood\": \"${sum_synflood}\", \"sum_udpflood\": \"${sum_udpflood}\", \"sum_icmpflood\": \"${sum_icmpflood}\", \"sum_ctinvalid\": \"${sum_ctinvalid}\", \"sum_tcpinvalid\": \"${sum_tcpinvalid}\", \"sum_sets\": \"${sum_sets}\", \"sum_setinbound\": \"${sum_setinbound}\", \"sum_setoutbound\": \"${sum_setoutbound}\", \"sum_cntelements\": \"${sum_cntelements}\", \"sum_cntinbound\": \"${sum_cntinbound}\", \"sum_cntoutbound\": \"${sum_cntoutbound}\", \"sum_setports\": \"${sum_setports}\", \"sum_setelements\": \"${sum_setelements}\" }" >>"${report_jsn}"
                        fi
                fi
-               if [ -s "${map_jsn}" ] && [ "$("${ban_catcmd}" "${map_jsn}")" != ",[{}" ]; then
+
+               # retrieve/prepare map data
+               #
+               if [ "${ban_nftcount}" = "1" ] && [ "${ban_map}" = "1" ] && [ -s "${report_jsn}" ]; then
+                       cnt="1"
+                       f_getfetch
                        json_init
-                       if json_load_file "${report_jsn}" >/dev/null 2>&1; then
-                               json_select "sets" >/dev/null 2>&1
-                               json_get_keys table_sets >/dev/null 2>&1
-                               if [ -n "${table_sets}" ]; then
-                                       for item in ${table_sets}; do
-                                               json_select "${item}"
-                                               json_get_keys set_details
-                                               for detail in ${set_details}; do
-                                                       if [ "${detail}" = "set_elements" ]; then
-                                                               json_get_values jsnval "${detail}" >/dev/null 2>&1
-                                                               jsnval="\"${jsnval// /\", \"}\""
-                                                       fi
-                                               done
-                                               if [ "${jsnval}" != '""' ]; then
-                                                       quantity="0"
-                                                       chunk=""
-                                                       (
-                                                               for ip in ${jsnval}; do
-                                                                       chunk="${chunk} ${ip}"
-                                                                       quantity="$((quantity + 1))"
-                                                                       if [ "${quantity}" -eq "100" ]; then
-                                                                               "${ban_fetchcmd}" ${ban_geoparm} "[ ${chunk%%?} ]" "${ban_geourl}" 2>/dev/null |
+                       if json_load_file "${ban_rtfile}" >/dev/null 2>&1; then
+                               json_get_values jsnval "active_uplink" >/dev/null 2>&1
+                               jsnval="${jsnval//\/[0-9][0-9]/}"
+                               jsnval="${jsnval//\/[0-9]/}"
+                               jsnval="\"${jsnval// /\", \"}\""
+                               if [ "${jsnval}" != '""' ]; then
+                                       {
+                                               printf "%s" ",[{}"
+                                               "${ban_fetchcmd}" ${ban_geoparm} "[ ${jsnval} ]" "${ban_geourl}" 2>/dev/null |
+                                                       "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="homeIP" '{printf ",{\"%s\": %s}\n",feed,$0}'
+                                       } >>"${map_jsn}"
+                               fi
+                       fi
+                       if [ -s "${map_jsn}" ] && [ "$("${ban_catcmd}" "${map_jsn}")" != ",[{}" ]; then
+                               json_init
+                               if json_load_file "${report_jsn}" >/dev/null 2>&1; then
+                                       json_select "sets" >/dev/null 2>&1
+                                       json_get_keys table_sets >/dev/null 2>&1
+                                       if [ -n "${table_sets}" ]; then
+                                               for item in ${table_sets}; do
+                                                       json_select "${item}"
+                                                       json_get_keys set_details
+                                                       for detail in ${set_details}; do
+                                                               if [ "${detail}" = "set_elements" ]; then
+                                                                       json_get_values jsnval "${detail}" >/dev/null 2>&1
+                                                                       jsnval="\"${jsnval// /\", \"}\""
+                                                               fi
+                                                       done
+                                                       if [ "${jsnval}" != '""' ]; then
+                                                               quantity="0"
+                                                               chunk=""
+                                                               (
+                                                                       for ip in ${jsnval}; do
+                                                                               chunk="${chunk} ${ip}"
+                                                                               quantity="$((quantity + 1))"
+                                                                               if [ "${quantity}" -eq "100" ]; then
+                                                                                       "${ban_fetchcmd}" ${ban_geoparm} "[ ${chunk%%?} ]" "${ban_geourl}" 2>/dev/null |
+                                                                                               "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="${item}" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}"
+                                                                                       chunk=""
+                                                                                       quantity="0"
+                                                                               fi
+                                                                       done
+                                                                       if [ "${quantity}" -gt "0" ]; then
+                                                                               "${ban_fetchcmd}" ${ban_geoparm} "[ ${chunk} ]" "${ban_geourl}" 2>/dev/null |
                                                                                        "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="${item}" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}"
-                                                                               chunk=""
-                                                                               quantity="0"
                                                                        fi
-                                                               done
-                                                               if [ "${quantity}" -gt "0" ]; then
-                                                                       "${ban_fetchcmd}" ${ban_geoparm} "[ ${chunk} ]" "${ban_geourl}" 2>/dev/null |
-                                                                               "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="${item}" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}"
-                                                               fi
-                                                       ) &
-                                                       [ "${cnt}" -gt "${ban_cores}" ] && wait -n
-                                                       cnt="$((cnt + 1))"
-                                               fi
-                                               json_select ".."
-                                       done
-                                       wait
+                                                               ) &
+                                                               [ "${cnt}" -gt "${ban_cores}" ] && wait -n
+                                                               cnt="$((cnt + 1))"
+                                                       fi
+                                                       json_select ".."
+                                               done
+                                               wait
+                                       fi
                                fi
                        fi
                fi
-       fi
 
-       # text output preparation
-       #
-       if [ "${output}" != "json" ] && [ -s "${report_jsn}" ]; then
-               json_init
-               if json_load_file "${report_jsn}" >/dev/null 2>&1; then
-                       json_get_var timestamp "timestamp" >/dev/null 2>&1
-                       json_get_var autoadd_allow "autoadd_allow" >/dev/null 2>&1
-                       json_get_var autoadd_block "autoadd_block" >/dev/null 2>&1
-                       json_get_var sum_synflood "sum_synflood" >/dev/null 2>&1
-                       json_get_var sum_udpflood "sum_udpflood" >/dev/null 2>&1
-                       json_get_var sum_icmpflood "sum_icmpflood" >/dev/null 2>&1
-                       json_get_var sum_ctinvalid "sum_ctinvalid" >/dev/null 2>&1
-                       json_get_var sum_tcpinvalid "sum_tcpinvalid" >/dev/null 2>&1
-                       json_get_var sum_sets "sum_sets" >/dev/null 2>&1
-                       json_get_var sum_setinbound "sum_setinbound" >/dev/null 2>&1
-                       json_get_var sum_setoutbound "sum_setoutbound" >/dev/null 2>&1
-                       json_get_var sum_cntelements "sum_cntelements" >/dev/null 2>&1
-                       json_get_var sum_cntinbound "sum_cntinbound" >/dev/null 2>&1
-                       json_get_var sum_cntoutbound "sum_cntoutbound" >/dev/null 2>&1
-                       json_get_var sum_setports "sum_setports" >/dev/null 2>&1
-                       json_get_var sum_setelements "sum_setelements" >/dev/null 2>&1
-                       {
-                               printf "%s\n%s\n%s\n" ":::" "::: banIP Set Statistics" ":::"
-                               printf "%s\n" "    Timestamp: ${timestamp}"
-                               printf "%s\n" "    ------------------------------"
-                               printf "%s\n" "    blocked syn-flood packets  : ${sum_synflood}"
-                               printf "%s\n" "    blocked udp-flood packets  : ${sum_udpflood}"
-                               printf "%s\n" "    blocked icmp-flood packets : ${sum_icmpflood}"
-                               printf "%s\n" "    blocked invalid ct packets : ${sum_ctinvalid}"
-                               printf "%s\n" "    blocked invalid tcp packets: ${sum_tcpinvalid}"
-                               printf "%s\n" "    ---"
-                               printf "%s\n" "    auto-added IPs to allowlist: ${autoadd_allow}"
-                               printf "%s\n\n" "    auto-added IPs to blocklist: ${autoadd_block}"
-                               json_select "sets" >/dev/null 2>&1
-                               json_get_keys table_sets >/dev/null 2>&1
-                               table_sets="$(printf "%s\n" ${table_sets} | "${ban_sortcmd}")"
-                               if [ -n "${table_sets}" ]; then
-                                       printf "%-25s%-15s%-24s%-24s%-24s%-24s\n" "    Set" "| Count   " "| Inbound (packets)" "| Outbound (packets)" "| Port/Protocol      " "| Elements           "
-                                       printf "%s\n" "    ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------"
-                                       for item in ${table_sets}; do
-                                               printf "    %-21s" "${item}"
-                                               json_select "${item}"
-                                               json_get_keys set_details
-                                               for detail in ${set_details}; do
-                                                       case "${detail}" in
-                                                               "cnt_elements")
-                                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                                       printf "%-15s" "| ${jsnval}"
-                                                                       ;;
-                                                               "cnt_inbound" | "cnt_outbound")
-                                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                                       [ -n "${jsnval}" ] && tmp_val=": ${jsnval}"
-                                                                       ;;
-                                                               "set_elements")
-                                                                       json_get_values jsnval "${detail}" >/dev/null 2>&1
-                                                                       jsnval="${jsnval// /, }"
-                                                                       printf "%-24s" "| ${jsnval:0:24}"
-                                                                       jsnval="${jsnval:24}"
-                                                                       while [ -n "${jsnval}" ]; do
-                                                                               printf "\n%-25s%-15s%-24s%-24s%-24s%-24s" "" "|" "|" "|" "|" "| ${jsnval:0:24}"
+               # text output preparation
+               #
+               if [ "${output}" != "json" ] && [ -s "${report_jsn}" ]; then
+                       json_init
+                       if json_load_file "${report_jsn}" >/dev/null 2>&1; then
+                               json_get_var timestamp "timestamp" >/dev/null 2>&1
+                               json_get_var autoadd_allow "autoadd_allow" >/dev/null 2>&1
+                               json_get_var autoadd_block "autoadd_block" >/dev/null 2>&1
+                               json_get_var sum_synflood "sum_synflood" >/dev/null 2>&1
+                               json_get_var sum_udpflood "sum_udpflood" >/dev/null 2>&1
+                               json_get_var sum_icmpflood "sum_icmpflood" >/dev/null 2>&1
+                               json_get_var sum_ctinvalid "sum_ctinvalid" >/dev/null 2>&1
+                               json_get_var sum_tcpinvalid "sum_tcpinvalid" >/dev/null 2>&1
+                               json_get_var sum_sets "sum_sets" >/dev/null 2>&1
+                               json_get_var sum_setinbound "sum_setinbound" >/dev/null 2>&1
+                               json_get_var sum_setoutbound "sum_setoutbound" >/dev/null 2>&1
+                               json_get_var sum_cntelements "sum_cntelements" >/dev/null 2>&1
+                               json_get_var sum_cntinbound "sum_cntinbound" >/dev/null 2>&1
+                               json_get_var sum_cntoutbound "sum_cntoutbound" >/dev/null 2>&1
+                               json_get_var sum_setports "sum_setports" >/dev/null 2>&1
+                               json_get_var sum_setelements "sum_setelements" >/dev/null 2>&1
+                               {
+                                       printf "%s\n%s\n%s\n" ":::" "::: banIP Set Statistics" ":::"
+                                       printf "%s\n" "    Timestamp: ${timestamp}"
+                                       printf "%s\n" "    ------------------------------"
+                                       printf "%s\n" "    blocked syn-flood packets  : ${sum_synflood}"
+                                       printf "%s\n" "    blocked udp-flood packets  : ${sum_udpflood}"
+                                       printf "%s\n" "    blocked icmp-flood packets : ${sum_icmpflood}"
+                                       printf "%s\n" "    blocked invalid ct packets : ${sum_ctinvalid}"
+                                       printf "%s\n" "    blocked invalid tcp packets: ${sum_tcpinvalid}"
+                                       printf "%s\n" "    ---"
+                                       printf "%s\n" "    auto-added IPs to allowlist: ${autoadd_allow}"
+                                       printf "%s\n\n" "    auto-added IPs to blocklist: ${autoadd_block}"
+                                       json_select "sets" >/dev/null 2>&1
+                                       json_get_keys table_sets >/dev/null 2>&1
+                                       table_sets="$(printf "%s\n" ${table_sets} | "${ban_sortcmd}")"
+                                       if [ -n "${table_sets}" ]; then
+                                               printf "%-25s%-15s%-24s%-24s%-24s%-24s\n" "    Set" "| Count   " "| Inbound (packets)" "| Outbound (packets)" "| Port/Protocol      " "| Elements           "
+                                               printf "%s\n" "    ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------"
+                                               for item in ${table_sets}; do
+                                                       printf "    %-21s" "${item}"
+                                                       json_select "${item}"
+                                                       json_get_keys set_details
+                                                       for detail in ${set_details}; do
+                                                               case "${detail}" in
+                                                                       "cnt_elements")
+                                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                                               printf "%-15s" "| ${jsnval}"
+                                                                               ;;
+                                                                       "cnt_inbound" | "cnt_outbound")
+                                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                                               [ -n "${jsnval}" ] && tmp_val=": ${jsnval}"
+                                                                               ;;
+                                                                       "set_elements")
+                                                                               json_get_values jsnval "${detail}" >/dev/null 2>&1
+                                                                               jsnval="${jsnval// /, }"
+                                                                               printf "%-24s" "| ${jsnval:0:24}"
                                                                                jsnval="${jsnval:24}"
-                                                                       done
-                                                                       ;;
-                                                               *)
-                                                                       json_get_var jsnval "${detail}" >/dev/null 2>&1
-                                                                       printf "%-24s" "| ${jsnval}${tmp_val}"
-                                                                       tmp_val=""
-                                                                       ;;
-                                                       esac
+                                                                               while [ -n "${jsnval}" ]; do
+                                                                                       printf "\n%-25s%-15s%-24s%-24s%-24s%-24s" "" "|" "|" "|" "|" "| ${jsnval:0:24}"
+                                                                                       jsnval="${jsnval:24}"
+                                                                               done
+                                                                               ;;
+                                                                       *)
+                                                                               json_get_var jsnval "${detail}" >/dev/null 2>&1
+                                                                               printf "%-24s" "| ${jsnval}${tmp_val}"
+                                                                               tmp_val=""
+                                                                               ;;
+                                                               esac
+                                                       done
+                                                       printf "\n"
+                                                       json_select ".."
                                                done
-                                               printf "\n"
-                                               json_select ".."
-                                       done
-                                       printf "%s\n" "    ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------"
-                                       printf "%-25s%-15s%-24s%-24s%-24s%-24s\n" "    ${sum_sets}" "| ${sum_cntelements}" "| ${sum_setinbound} (${sum_cntinbound})" "| ${sum_setoutbound} (${sum_cntoutbound})" "| ${sum_setports}" "| ${sum_setelements}"
-                               fi
-                       } >>"${report_txt}"
+                                               printf "%s\n" "    ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------"
+                                               printf "%-25s%-15s%-24s%-24s%-24s%-24s\n" "    ${sum_sets}" "| ${sum_cntelements}" "| ${sum_setinbound} (${sum_cntinbound})" "| ${sum_setoutbound} (${sum_cntoutbound})" "| ${sum_setports}" "| ${sum_setelements}"
+                                       fi
+                               } >>"${report_txt}"
+                       fi
                fi
        fi
 
@@ -1744,11 +1746,11 @@ f_report() {
                        ;;
                "json")
                        if [ "${ban_nftcount}" = "1" ] && [ "${ban_map}" = "1" ]; then
-                               jsn="$("${ban_catcmd}" ${report_jsn} ${map_jsn})"
-                               printf "[%s]]\n" "${jsn}"
+                               jsn="$("${ban_catcmd}" ${report_jsn} ${map_jsn} 2>/dev/null)"
+                               [ -n "${jsn}" ] && printf "[%s]]\n" "${jsn}"
                        else
-                               jsn="$("${ban_catcmd}" ${report_jsn})"
-                               printf "[%s]\n" "${jsn}"
+                               jsn="$("${ban_catcmd}" ${report_jsn} 2>/dev/null)"
+                               [ -n "${jsn}" ] && printf "[%s]\n" "${jsn}"
                        fi
                        ;;
                "mail")