#!/bin/bash # # simplify-subnets.sh # # Developed by Ondrej Jombik # Copyright (c) 2018 Platon Group, http://platon.sk/ # Licensed under terms of GNU General Public License. # All rights reserved. # # Changelog: # 2018-05-07 - created # 2018-05-08 - merging multiple C-class into one B-class # based on C-class subnets counting # # $Platon: scripts/shell/firewall/firewall.d/subnets/simplify-subnets.sh,v 1.6 2018/05/08 00:51:39 nepto Exp $ # Minimum amount of C-classes to be merged into one B-class MIN_C_CLASS_MERGE=120; SUBNET_FILE="$1"; if [ -z "$SUBNET_FILE" ]; then echo "Usage: $0 "; exit 1; fi # Simple subnet implementation of pow() # It returns 1 for /24, 2 for /23, 4 for /22, and so on c_class_subnets_count () # {{{ { local pow ret i pow=$(( 24 - $1 )) ret=1 i=1 while [ $i -le $pow ]; do ret=$(( ret * 2 )) i=$(( i + 1 )) done echo $ret; } # }}} prev_C=''; prev_B=''; cnt_CinB=1; while IFS='' read -r line; do if [ -z "$line" -o "${line#\#}"x != "${line}x" ]; then echo "$line"; continue; fi subnet="`echo "$line" | cut -f1 -d/`"; mask="`echo "$line" | cut -f2 -d/`"; if [ "$mask" -gt 24 ]; then mask=24; fi subnet_C="`echo "$subnet" | sed 's/\.[0-9]\+$/.0/'`"; subnet_B="`echo "$subnet" | sed 's/\.[0-9]\+\.[0-9]\+$/.0.0/'`"; if [ -z "$to_write" ]; then prev_C="$subnet_C"; prev_B="$subnet_B"; to_write="$subnet_C/$mask"; fi if [ "$subnet_C" = "$prev_C" ]; then continue; fi if [ "$subnet_B" = "$prev_B" ]; then to_write="$to_write"$'\n'; # newline to_write="$to_write$subnet_C/$mask"; prev_C="$subnet_C"; # /24=1, /23=2, /22=4, /21=8, ... subnet_count="`c_class_subnets_count $mask`"; cnt_CinB=$(( cnt_CinB + subnet_count )); continue; fi # Output if [ "$cnt_CinB" -gt "$MIN_C_CLASS_MERGE" ]; then echo "# Merged $cnt_CinB C-classes into one B-class"; echo "$prev_B/16"; else if [ "$cnt_CinB" -gt 1 ]; then echo "# Found $cnt_CinB similar networks"; echo "$to_write"; else if [[ "$to_write" = */24 ]]; then echo "# Simplified to C-class"; echo "$to_write"; else echo "# Unchanged network"; echo "$to_write"; fi fi fi to_write="$subnet_C/$mask"; prev_B="$subnet_B"; prev_C="$subnet_C"; cnt_CinB=1; done < "$SUBNET_FILE";