# # Bash source file for IPV4 computing - netfunc v0.15 # # (C) 2011-2012 Felix Hauri - felix@f-hauri.ch # Licensed under terms of GPL v3. www.gnu.org # after sourcing script: # syntaxe: ipcalc xxx.xxx.xxx.xxx/yy or ipcalc xxx.xxx.xxx.xxx zzz.zzz.zzz.zzz # where xxx is the basic ip address for compute, yy is the length or de mask # and/or zzz is the mask in standard ipv4 notation. # Compute and display network, broadcast, host/net and class address # display all address both in standard ipv4 notation and binary. # In order to prevent forks, last optional argument to functions is a # variable name to be populated by function result. # to be sourced! Quit function list: source this or run : grep '()' shopt -s extglob if [ "${BASH_SOURCE[0]}" ];then _srcFuncList="$(basename "${BASH_SOURCE[0]%%[_.]*}")FList" eval "$_srcFuncList() { if [[ \$# -gt 0 ]] ;then sed ' s/() *{ *#/ :/;ta;bb;:a;;s/^\(.\{12\}\) *:/\n - \1/p; :c;N;s/^.*\n *# / /p;tc;:b;1,3s/^# //p;d ' '${BASH_SOURCE[0]}' echo else sed ' s/() *{ *#/ :/;ta;bb;:a;;s/^\(.\{12\}\) *:/ - \1/p; :b;1,3s/^# //p;d ' '${BASH_SOURCE[0]}' fi printf ' - %-11s %s\n' $_srcFuncList 'List functions (this.) [-v]' }" [[ $1 == -q ]] || [[ $1 == --quiet ]] || "$_srcFuncList" unset _srcFuncList fi int2ip() { # integer to IPv4 # int2ip [-v VARNAME] [ ...] if [[ $1 == -v ]];then local -n _outar="$2";shift 2;else local _outar;fi _outar=() local _arg for _arg ;do printf -v _arg "%d.%d.%d.%d" \ $((_arg>>24)) $((_arg>>16&255)) $((_arg>>8&255)) $((_arg&255)) _outar+=("$_arg") done [[ ${_outar@A} != declare\ -a\ _outar=* ]] || printf '%s\n' "${_outar[@]}" } int2rev() { # 3 most significant bytes, for reverse DNS X.X.X.in-addr.arpa # int2rev [-v VARNAME] if [[ $1 == -v ]];then local -n _out="$2";shift 2;else local _out;fi printf -v _out "%d.%d.%d" $(($1>>8&255)) $(($1>>16&255)) $(($1>>24)) [[ ${_out@A} != _out=* ]] || echo "$_out" } checkIsIp() { # throw an error if not valid IPv4 # checkIsIp [-v VARNAME] local _iPointer _i _a _vareq=() if [[ $1 == -v ]];then _vareq=(-v "$2");shift 2;fi for _i ;do case $_i in *[^0-9.]* ) return 1 ;; esac read -ra _a <<<"${_i//./ }" [ ${#_a[@]} -eq 4 ] || return 1 for _iPointer in "${_a[@]}" ;do (( _iPointer == ( _iPointer & 255 ) )) || return 2 done done ip2int "${_vareq[@]}" "${@}" } ip2int() { # IPv4 to integer 32 bits value. # ip2int [-v VARNAME] if [[ $1 == -v ]];then local -n _out="$2";shift 2;else local _out;fi local _a read -ra _a <<<"${1//./ }" printf -v _out "%u" $(( _a[0] << 24 | _a[1] << 16 | _a[2] << 8 | _a[3] )) [[ ${_out@A} != _out=* ]] || echo "$_out" } mask2int() { # from mask len to integer value of IPv4 mask # mask2int [-v VARNAME] if [[ $1 == -v ]];then local -n _out="$2";shift 2;else local _out;fi printf -v _out "%u" $(( ( ~0 ^ ~0<<32 ) ^ ( ~0 ^ ~0<<(32-$1) ) )) [[ ${_out@A} != _out=* ]] || echo "$_out" } int2mlen() { # compute mask len from integer value of IPv4 mask # int2mlen [-v VARNAME] if [[ $1 == -v ]];then local -n _out="$2";shift 2;else local _out;fi local _mlen int2bin -v _mlen "$1" _mlen=${_mlen// } _mlen=${_mlen##*(1)} printf -v _out "%d" $((32-${#_mlen})) [[ ${_out@A} != _out=* ]] || echo "$_out" } be2int() { # Big Endian to INTeger, ( for reading proc/net/route ) # be2int [-v VARNAME] if [[ $1 == -v ]];then local -n _out="$2";shift 2;else local _out;fi printf -v _out %u $(( 16#${1::2} | ( 16#${1:2:2} <<+8 )| ( 16#${1:4:2} <<+16 )| ( 16#${1:6} <<+24 ) )) [[ ${_out@A} != _out=* ]] || echo "$_out" } int2uu() { # 1st run generate int2uu() to render bash's 64# from integer # int2uu [-v VARNAME] local string func # shellcheck disable=2016 # Expressions don't expand in single quotes, printf -v string '${array[$1>>%d&63]} ' {60..0..-6} IFS='' read -rd '' func <<-EOF () { if [[ \$1 == -v ]] ;then local -n _out="\$2";shift 2 else local _out fi local array=({0..9} {a..z} {A..Z} @ _) printf -v _out %s ${string/>>0} _out=\${_out##*(0)} [[ \${_out@A} != _out=* ]] || echo "\$_out" } EOF eval "${FUNCNAME[0]}$func" ${FUNCNAME[0]} "$@" } int2bin() { # 1st run generate int2bin to render 32bits, mark mask with a dot. # int2bin [-v VARNAME] local string func printf -v func %8s '' # shellcheck disable=2016 # Expressions don't expand in single quotes, printf -v string '$((($1>>%d)&1)) ' {31..1} IFS='' read -rd '' func <<-EOF () { if [[ \$1 == -v ]] ;then local -n _out="\$2";shift 2 else local _out fi local _p printf -v _out \ '${func// /%d} ${func// /%d} ${func// /%d} ${func// /%d}' \ $string \$(( \$1 & 1 )) [ "\$2" ] && _p=\$((\$2+(\$2>8)+(\$2>16)+(\$2>24))) && printf -v _out %s.%s "\${_out:0:_p}" "\${_out:_p}" [[ \${_out@A} != _out=* ]] || echo "\$_out" } EOF eval "${FUNCNAME[0]}$func" ${FUNCNAME[0]} "$@" } rangeIp() { # Generate array of integer representation of IPv4 from argument # int2bin [expr[,expr..]] # where ``expr'' is # 'xxx.xx.xx.xxx', 'xxx.xx.xx.xxx/masklen' or 'xxx.xx.xx.xxx-yyy.yy.yy.yyy' if [[ $1 == -v ]];then local -n _res="$2";shift 2;else local _res;fi local first last iFirst iLast i="$*" _out=() local fields delims i=${i// /,} read -ra fields <<<"${i//[,\/-]/ }" read -ra delims <<<"${i//[0-9.]/ }" first=${fields[0]} checkIsIp -v iFirst "$first" || return 1 read -ra first <<<"${first//./ }" read -ra fields <<<"${fields[@]:1}" while [ "${fields[0]}" ] ;do read -ra last <<<"${fields[0]//./ }" case ${delims[0]} in , ) last[0]="${first[*]:0:4-${#last[@]}} ${last[*]}" _out[$iFirst]="" first=("${last// /.}") checkIsIp -v iFirst "${first[0]}" || return 2 read -ra first <<<"${first//./ }" ;; - ) last[0]="${first[*]:0:4-${#last[@]}} ${last[*]}" last[0]=${last// /.} checkIsIp -v iLast "${last[0]}" || return 3 for ((i=iFirst;i<=iLast;i++));do _out[i]="" done read -ra first <<<"${last//./ }" ;; / ) mask2int -v iLast "${last[0]}" iFirst=$((iFirst & iLast)) iLast=$((iFirst | ( iLast ^ ( ~0 ^ ~0<<32 ) ) )) for ((i=iFirst;i<=iLast;i++));do _out[i]="" done int2ip -v first $iLast read -ra first <<<"${first//./ }" ;; esac read -ra delims <<<"${delims[@]:1}" read -ra fields <<<"${fields[@]:1}" done _out[iFirst]="" _res=("${!_out[@]}") [[ ${_res@A} != declare\ -a\ _res=* ]] || echo "${_res[@]}" } _mPingTimeout=1.6 multiping() { # One ping on many target. Use integer representation of IPv4 # multiping [integer [integer...]] if [[ $1 == -v ]] ;then local _var=: ip time i a intip # shellcheck disable=2178 # Incorrect handling of nameref local -n _out="$2" shift 2 _out=() else local _var='' _out=() ip time i a intip fi while read -r a _ _ ip _ _ time _;do [[ $a == 64 ]] && ip2int -v intip "${ip%:}"&& time=${time#*=}&& _out[intip]=${time// } done < <( for i ;do int2ip -v ip "$i" ping -nc 1 -W "$_mPingTimeout" "$ip" & sleep .002 done 2> >(grep -v 'ping broadcast' >&2) wait ) if [ -z "$_var" ];then for i in "${!_out[@]}";do int2ip -v a "$i" printf "%-16s %8s\n" "$a" "${_out[i]:---}" done fi } declare -a _ipResInv ip2hnam () { # Fork to `host` and store in _ipResInv, if not already stored. # ip2hnam [-v VARNAME] local _len _int _lh _rh _var="" while [[ ${1::1} == - ]] ;do case ${1:1} in l ) _len=$2 ; shift 2;; v ) local -n _host=$2 ; _var=1 ; shift 2;; * ) echo "Unknown option $1"; return 1;; esac done [[ -z "$_var" ]] && local _host ip2int -v _int "$1" if [[ -v _ipResInv[_int] ]] ;then _host=${_ipResInv[_int]} else read -ra _host < <(host "$1") if [[ ${_host[3]} == pointer ]]; then _host=("${_host[4]%%.*}") _ipResInv[_int]="${_host[0]}" else _host=("$1") fi fi [ "$_len" ] && [[ $_len -lt ${#_host} ]] && if [[ $1 == "${_host[0]}" ]];then _lh=$((_len/2-1)) _rh=$((_len-_lh-2)) _host=("${_host::$_lh}..${_host: -$_rh}") return 1 else _rh=$((_len/2-1)) _lh=$((_len-_rh-2)) _host=("${_host::$_lh}..${_host: -$_rh}") fi [[ $1 == "${_host[0]}" ]] && return 1 [[ ${_host@A} != _host=* ]] || echo "${_host[0]}" } declare -A _ipResolv hname2ip () { # Fork to `host` and store in _ipResolv, if not already stored. # hname2ip [-v VARNAME] # shellcheck disable=2178 # Incorrect handling of nameref if [[ $1 == -v ]];then local -n _out="$2";shift 2;else local _out;fi local _host if [ -v _ipResolv["$1"] ];then _out="${_ipResolv["$1"]}" else while read -ra _host ;do [[ ${_host[2]} == address ]] && \ _out="${_host[3]}" _ipResolv["$1"]="${_host[3]}" done < <(host "$1") fi [ -v _out ] || return 1 [[ ${_out@A} != _out=* ]] || echo "$_out" } isup () { # Monitor ping many targets simultaneously (hit any key to quit) # isup [...] local _i _ip _ipRange _fmtStr _pings _times _names _ck _lck=-1 _now \ _elap _sleep _hdLne _lnCnt=0 _started _started=${EPOCHREALTIME/.} while [ "$1" ];do if rangeIp -v _ip "$1" ;then for _i in "${_ip[@]}" ;do _ipRange[_i]="" done elif checkIsIp -v _ip "$1" ;then _ipRange[_ip]='' else hname2ip -v _ip "$1" && ip2int -v _ip "$_ip" && _ipRange[_ip]="" fi shift done _ipRange=("${!_ipRange[@]}") for _i in "${_ipRange[@]}" ;do int2ip -v _ip "$_i" ip2hnam -v _ip -l 7 "$_ip" printf -v _names[_i] %s "$_ip" done _fmtStr=${_names[*]} _fmtStr=" %9.4f %3d ${_fmtStr//+([^ ])/%8s}" # shellcheck disable=2059 # Format string was built printf -v _hdLne "${_fmtStr/.4f*3d/s %3s}" Elaps Cnt "${_names[@]}" while :;do _ck=0 _now=${EPOCHREALTIME/.} unset _pings _times multiping -v _pings "${_ipRange[@]}" _elap=${EPOCHREALTIME/.} _sleep=$((1000000-_elap+_now)) [ $_sleep -gt 0 ] && _sleep=00000$_sleep && printf -v _sleep "%f" ${_sleep::-6}.${_sleep: -6} _elap=00000$((_elap-_started)) printf -v _elap "%f" ${_elap:0: -6}.${_elap: -6} for ((_i=0;_i<${#_ipRange[@]};_i++)) ; do _times[${_ipRange[$_i]}]=${_pings[${_ipRange[_i]}]:---} [ "${_pings[_ipRange[_i]]}" ] && ((_ck+=2**_i)) done if [ "$_lck" ] && [ $_lck -ne "$_ck" ] ;then echo if [ $((_lnCnt--)) -lt 1 ] ;then _lnCnt=${LINES:-24} echo "$_hdLne" fi fi _lck=$_ck # shellcheck disable=2059 # Format string was built printf "\r$_fmtStr" "$_elap" "${#_pings[@]}" "${_times[@]}" [ "${_sleep//*-*}" ] || read -rt 0 -sn1 _ && read -st ${_sleep//*-*/.1} -rn1 _ && echo && break done } mping() { # quick ping scan IPv4 ranges and resolv host name of waked hosts # mping [-v VARNAME] ... local _list _i _nam _pings _ip _var=() [[ $1 == -v ]] && local -n _out="$2" && _out=() _var=(-v "$2") && shift 2 if ! [[ $1 ]] ;then local _netList _net _loc getLocalNet -v _netList _netList=("${_netList[@]#*:}") _netList=("${_netList[@]%:*}") ${FUNCNAME[0]} "${_var[@]}" ${_netList[@]/*\/0} return fi _i="$*" rangeIp -v _list "${_i// /,}" multiping -v _pings "${_list[@]}" for _i in "${!_pings[@]}";do int2ip -v _ip "$_i" ip2hnam -v _nam "$_ip" printf " - %-15s %-18s %s\n" "$_ip" "$_nam" "${_pings[_i]}" [[ ${_var[0]} == -v ]] && _out[$_i]=$_ip:$_nam done } case ${LANG:-$LC_ALL} in *.utf8|*.UTF8|*.utf-8|*.UTF-8) _nf_brds=($'\U2500' $'\U2501' $'\U2502' \ $'\U2503' $'\U250F' $'\U252F' $'\U2513' $'\U2520' $'\U253C' $'\U2528' \ $'\U2517' $'\U2537' $'\U251B' $'\U25B8');; *) _nf_brds=('-' '-' '|' '|' '+'{,,,,,,,,} '>') ;; esac _ipC_fmtPrint(){ # format print lines for ipcalc local __ip __bin __dist __crt='' int2ip -v __ip "$1" int2bin -v __bin "$1" "$_mlen" __dist=$(($1-_base)) (($1-_int)) || __crt="${_nf_brds[13]}" shift printf '%s%1s%-12s%s%-15s%s%11s%s%s%s\n' "${_nf_brds[3]}" "$__crt" "$*" \ "${_nf_brds[2]}" "$__ip" "${_nf_brds[2]}" "#$__dist" \ "${_nf_brds[2]}" "${__bin/./${_nf_brds[2]}}" "${_nf_brds[3]}" } ipcalc() { # compute and render network submited as [ip mask] or [ip/masklen] # ipcalc [| ] local _int _ip _mask _mlen _imask _base _bin _broadcast _class \ _crt _bl _sl _igate _gwnam _hstnam if ! [[ $1 ]] ;then local _netList _net _loc getLocalNet -v _netList for _net in "${_netList[@]}";do IFS=: read -ra _loc <<<"$_net:" printf '\e[1mInterface: %s\e[0m\n' "${_loc[0]}" # shellcheck disable=SC2154 # ${_gw} is referenced but not assigned ${FUNCNAME[0]} "${_loc[@]:1:2}" Local ${_gw+Gateway} done return fi checkIsIp -v _int "${1%/*}" || { echo "Not an IP: '$1'"; return 1;} if [[ $1 != "${1#*/}" ]] ;then _mlen=${1#*/} case $_mlen in *[^0-9]* | '' ) echo "Not a mask len: '${1#*/}'"; return 2;; esac mask2int -v _imask "$_mlen" int2ip -v _mask "$_imask" elif [ "$2" ];then checkIsIp -v _imask "$2" || { echo "Not an IP: '$2'"; return 3;} int2bin -v _mlen "$_imask" '' _mlen=${_mlen// } _mlen=${_mlen%%*(0)} _mask=$2 case $_mlen in *0* ) echo "Not a mask: '$2'"; return 4;; esac _mlen=${#_mlen} shift else echo "Mask missing." return 5 fi if [[ "$3" ]] ;then _hstnam="$3" else ip2hnam -v _hstnam "${1%/*}" || _hstnam=Host fi if [[ "$2" ]] ;then checkIsIp -v _igate "$2" || { echo "Not an IP: '$2'"; return 6;} if [[ "$4" ]] ;then _gwnam="$4" else ip2hnam -v _gwnam -l 12 "$2" || _gwnam=Gateway fi fi _base=$((_int & _imask)) _broadcast=$(( _int | ( _imask ^ ( ( 1<<32 ) -1 )) )) printf -v _sl '%*s' 36 '' _bl=${_sl// /"${_nf_brds[1]}"} _sl=${_sl// /"${_nf_brds[0]}"} printf '%b%s%b%s%b%s%b%s%b%s%b\n' "${_nf_brds[4]}" "${_bl:23}" \ "${_nf_brds[5]}" "${_bl:21}" "${_nf_brds[5]}" "${_bl:25}" \ "${_nf_brds[5]}" "${_bl::_mlen+(_mlen-1)/8}" "${_nf_brds[5]}" \ "${_bl:: 35 - _mlen - (_mlen-1) / 8 }" "${_nf_brds[6]}" _ipC_fmtPrint $_base Network base int2bin -v _bin "$_imask" "$_mlen" printf '%s %-12s%s%-15s%s/%-10s%s%s%s\n' "${_nf_brds[3]}" Mask \ "${_nf_brds[2]}" "$_mask" "${_nf_brds[2]}" "$_mlen" \ "${_nf_brds[2]}" "${_bin/./${_nf_brds[2]}}" "${_nf_brds[3]}" _ipC_fmtPrint $_broadcast Broadcast int2bin -v _class $_base '' _class=${_class%%0*} _crt=$(( _broadcast - _base - 1 )) (( _crt < 1 )) && _crt=1 printf -v _class \\%03o $((65+${#_class})) printf '%s %-12s%s%-15s%s%-11b%s%*s%s%*s%s\n' "${_nf_brds[3]}" Host/net \ "${_nf_brds[2]}" $_crt "${_nf_brds[2]}" "Class $_class" \ "${_nf_brds[2]}" $((_mlen+(_mlen-1)/8)) '' "${_nf_brds[2]}" \ $((35-_mlen-(_mlen-1)/8)) '' "${_nf_brds[3]}" if [ $((_broadcast - _base)) -gt 1 ];then printf '%b%s%b%s%b%s%b%s%b%s%b\n' "${_nf_brds[7]}" "${_sl:23}" \ "${_nf_brds[8]}" "${_sl:21}" "${_nf_brds[8]}" "${_sl:25}" \ "${_nf_brds[8]}" "${_sl::_mlen+(_mlen-1)/8}" "${_nf_brds[8]}" \ "${_sl:: 35 - _mlen - (_mlen-1) / 8 }" "${_nf_brds[9]}" if (( _igate == ( 1+ _base ))) ;then _ipC_fmtPrint "$_igate" "$_gwnam" else _ipC_fmtPrint $((_base+1)) First host fi (( ( ( _base + 1 ) < _igate ) & ( _igate < _int ) )) && _ipC_fmtPrint "$_igate" "$_gwnam" (( ( ( _base + 1 ) < _int ) & ( _int < ( _broadcast - 1 ) ) )) && _ipC_fmtPrint "$_int" "$_hstnam" (( ( _int < _igate ) & ( _igate < ( _broadcast - 1 ) ) )) && _ipC_fmtPrint "$_igate" "$_gwnam" if (( _igate == ( _broadcast -1))) ;then _ipC_fmtPrint "$_igate" "$_gwnam" else _ipC_fmtPrint $((_broadcast-1)) Last host fi fi printf '%b%s%b%s%b%s%b%s%b%s%b\n' "${_nf_brds[10]}" "${_bl:23}" \ "${_nf_brds[11]}" "${_bl:21}" "${_nf_brds[11]}" "${_bl:25}" \ "${_nf_brds[11]}" "${_bl::_mlen+(_mlen-1)/8}" "${_nf_brds[11]}" \ "${_bl:: 35 - _mlen - (_mlen-1) / 8 }" "${_nf_brds[12]}" } # shellcheck disable=SC2154 # ${headline[@],,} is referenced but not assigned getLocalNet() { # Get local config from /proc/net/ pseudo files # getLocalNet [-v VARNAME] # shellcheck disable=SC2178 # _outar is still an array if [[ $1 == -v ]];then local -n _outar="$2";shift 2;else local _outar;fi _outar=() local headline _oIP _oMsk _oGate _tag _ip _lip _lnet _ints _imsk _base _oIf _gates while read -r _tag _ip;do case $_tag in "+--" ) IFS=' /' read -r _ _ip _tag _ <<<"$_ip" [[ $_tag == 2 ]] && mask2int -v _lnet "$_ip";; \|-- ) _lip=$_ip ;; Local: ) break ;; /32 ) if [[ $_ip == host\ LOCAL ]] && [[ $_lip != 127.0.0.* ]];then ip2int -v _ints[${#_ints[@]}] "$_lip" mask2int -v _imsk[${#_imsk[@]}] "${_lnet:-32}" fi ;; esac done < /proc/net/fib_trie { read -ra headline local "${headline[@],,}" while read -r "${headline[@],,}";do if [[ $gateway == 00000000 ]] ;then be2int -v _base "$destination" be2int -v _mask "$mask" for _tag in "${!_ints[@]}" ;do (( (_ints[_tag] & _mask ) == _base )) && _oIP[_tag]=${_ints[_tag]} _oMsk[_tag]="$_mask" \ _oIf[_tag]="$iface" done elif [[ $destination == 00000000 ]] && [[ $destination == "$mask" ]] then be2int -v _ip "$gateway" _gates[_ip]="$iface" else be2int -v _base "$destination" be2int -v _mask "$mask" be2int -v _ip "$gateway" for _tag in "${!_ints[@]}" ;do (( (_ints[_tag] & _mask ) == _base )) && _oIP[_tag]=${_ints[_tag]} _oMsk[_tag]="$_mask" \ _oIf[_tag]="$iface" _gates[_ip]="$iface" done fi done for _ip in "${!_gates[@]}" ;do for _tag in "${!_oIP[@]}" ;do (( (_oIP[_tag] & _oMsk[_tag] ) == (_ip & _oMsk[_tag] ) )) && [[ ${_oIf[_tag]} == "${_gates[_ip]}" ]] && _oGate[_tag]=$_ip done done } < /proc/net/route for _tag in "${!_oIP[@]}" ;do int2ip -v _ip "${_oIP[_tag]}" int2mlen -v _lip "${_oMsk[_tag]}" [[ "${_oGate[_tag]}" ]] && int2ip -v gateway "${_oGate[_tag]}" || gateway='' printf -v _outar[${#_outar[@]}] "%s:%s/%d:%s" "${_oIf[_tag]}" \ "$_ip" "$_lip" "$gateway" done [[ ${_outar@A} != declare\ -a\ _outar=* ]] || printf '%s\n' "${_outar[@]}" } commonNet() { # compute smallest common network for many IP/net # commonNet [ip address]... local int bin1 bin2 mlen ips rangeIp -v int "$@" int2bin -v bin1 "${int[0]}" int2bin -v bin2 "${int[@]: -1}" int2ip -v ips "${int[0]}" "${int[@]: -1}" bin1=${bin1// } bin2=${bin2// } for ((mlen=32; mlen; mlen--)) ;do [[ ${bin1::mlen} == "${bin2::mlen}" ]] && break done ipcalc "${ips[0]}/$mlen" "${ips[1]}" IP\ {min,max} } _reCidrAddIpFromTo() { # add CIDR in whole array as=([intIP start]="intIP end") if [[ $1 == -v ]];then local -n _wList="$2";shift 2;else local _wList;fi local _start _end _i for _i in "${!_wList[@]}" ;do [[ $1 -ge $((_i+1)) ]] && [[ $1 -le $((_wList[_i]+1)) ]] && _start=$_i [[ $2 -ge $((_i-1)) ]] && [[ $2 -le $((_wList[_i]-1)) ]] && _end=$_i done if [[ $_start ]] ;then if [[ $_end ]] ;then if [[ $_start -lt $_end ]] ;then _wList[_start]=${_wList[_end]} unset "_wList[_end]" fi else if [[ $1 -lt $_start ]];then _wList[$1]=${_wList[_start]} unset "_wList[_start]" _start=$1 fi [[ $2 -gt ${_wList[_start]} ]] && _wList[_start]=$2 fi else if [[ $_end ]] ;then if [[ $1 -lt $_end ]];then _wList[$1]=${_wList[_end]} unset "_wList[_end]" _end=$1 fi [[ $2 -gt ${_wList[_end]} ]] && _wList[_end]=$2 else _wList[$1]=$2 fi fi } _reCidrAddCidr() { # Format 1 CIDR for adding to reCidrListe # shellcheck disable=2034 # Incorrect handling of nameref if [[ $1 == -v ]];then local -n _wAr="$2";shift 2;else local _wAr;fi local mask=${1#*/} ip=${1%/*} imask [[ ${mask//*.*} ]] || mask=32 mask2int -v imask $mask ip2int -v ip "${ip}" _reCidrAddIpFromTo -v _wAr $((ip&imask)) $((ip | ((~0 ^ ~0<<+32) ^ imask))) } _reCidrComputeMask() { # Internal compute CIDR from limits (start-end) if [[ $1 == -v ]];then local -n _arr="$2";shift 2;else local _arr;fi local _out local -i mask imask while [ "$1" ];do mask=32 while mask2int -v imask $((mask-1)) && [[ $1 == $(( ($1>>(33-mask))<<(33-mask) )) ]] && [[ $2 -ge $(( $1 | ((~0 ^ ~0<<+32) ^ imask) )) ]] ;do mask+=-1 done int2ip -v _out "$1" _arr+=("$_out/$mask") mask2int -v imask $mask if [[ $2 -gt $(( $1 | ((~0 ^ ~0<<+32) ^ imask) )) ]] ;then set -- $(( 1+($1 | ((~0 ^ ~0<<+32) ^ imask)) )) "$2" else shift 2 fi done [[ ${_arr@A} != declare\ -a\ _arr=* ]] || echo "${_arr[*]}" } reCIDR() { # Compute shortened list of CIDR for argument or STDIN # reCIDR [ip address/masklen]... # reCIDR