Skip to content

Instantly share code, notes, and snippets.

@h0tw1r3
Created Oct 13, 2016
Embed
What would you like to do?
Filter IPv4 addresses by network
#!/bin/bash
# NetAddr version 0.2 - Filter IPv4 addresses by network
# Copyright 2016 Jeffrey Clark <github.com/h0tw1r3>
# Copyright 2009 Ole Christian Tvedt <olechrt@stud.ntnu.no>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License can
# be found at <http://www.gnu.org/licenses/>.
# Print usage and exit.
function usage {
echo -e "Usage:\n\t$(basename "$0") <CIDR> [IP]" >&2
echo "If IP argument, exit code 1 if not in same network as <CIDR>. Otherwise IP addresses are read from standard input. An
y address in the same network as <CIDR> will be echoed to standard output." >&2
exit 1
}
[[ $# -lt 1 || $1 = '-h' ]] && usage
# Check validity of IP address.
function validip {
[[ $# -ne 4 ]] && return 1;
for (( S=0; S<4; S++ )); do
[[ $1 -lt 0 || $1 -gt 255 ]] && return 1
shift
done
return 0
}
function testip {
INPUT=$1
[[ -z "$INPUT" || "${INPUT:0:1}" == "#" ]] && return 0
INIP=($(echo "$INPUT" | sed -ne 's:^'"$IPRE"'$:\1 \2 \3 \4:p'))
if ! validip "${INIP[@]}"; then
return 1
fi
for (( I=0; I<4; I++ )); do
[[ $(( ${INIP[$I]} & ${MASK[$I]} )) -ne ${NETWORK[$I]} ]] && return 1
done
return 0
}
IPRE='\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)'
# Put IP address in an array.
IP=($(echo "$1" | sed -ne 's:^'"$IPRE"'/.*$:\1 \2 \3 \4:p'))
if ! validip "${IP[@]}"; then
echo "Error: Invalid IP address in CIDR." >&2;
exit 1
fi
# Put network mask in an array.
MASK=($(echo "$1" | sed -ne 's:^[^/]*/'"$IPRE"'$:\1 \2 \3 \4:p'))
if [ ${#MASK[@]} -ne 4 ]; then
BITCNT=($(echo "$1" | sed -ne 's:^[^/]*/\([0-9]\+\)$:\1:p'))
[[ -z "$BITCNT" ]] && usage
BITCNT=$(( ((2**${BITCNT})-1) << (32-${BITCNT}) ))
for (( I=0; I<4; I++ )); do
MASK[$I]=$(( ($BITCNT >> (8 * (3 - $I))) & 255 ))
done
fi
if ! validip "${MASK[@]}"; then
echo "Error: Invalid network mask in CIDR." >&2;
exit 1
fi
# Find network address.
NETWORK=()
for (( I=0; I<4; I++ )); do
NETWORK[$I]=$(( ${IP[$I]} & ${MASK[$I]} ))
done
if [ $# -gt 1 ]; then
testip $2
exit $?
fi
# Read input addresses
while read INPUT; do
if testip $INPUT; then
echo $INPUT
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment