#!/bin/bash # NetAddr version 0.1 - Filter IPv4 addresses by network # Copyright 2009 Ole Christian Tvedt # 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 . # Print usage and exit. function usage { echo -e "Usage:\n\t$(basename "$0") " >&2 echo "IP addresses are read from standard input. Any address in the" >&2 echo "same network as will be echoed to standard output." >&2 exit 1 } [[ $# -lt 1 ]] && 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 } 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; usage; 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; usage; fi # Find network address. NETWORK=() for (( I=0; I<4; I++ )); do NETWORK[$I]=$(( ${IP[$I]} & ${MASK[$I]} )) done # Read input addresses while read INPUT; do [[ -z "$INPUT" || "${INPUT:0:1}" == "#" ]] && continue INIP=($(echo "$INPUT" | sed -ne 's:^'"$IPRE"'$:\1 \2 \3 \4:p')) if ! validip "${INIP[@]}"; then echo "Warning: Input IP \"$INPUT\" is invalid." >&2 continue fi for (( I=0; I<4; I++ )); do [[ $(( ${INIP[$I]} & ${MASK[$I]} )) -ne ${NETWORK[$I]} ]] && continue 2 done echo "$INPUT" done