Bash script to list all IPs in prefix

后端 未结 11 1565
[愿得一人]
[愿得一人] 2020-12-23 12:23

I\'m trying to create script that I can input a set of prefixes, which will then list all IP addresses within the prefixes (including network/host/broadcast).

An ex

相关标签:
11条回答
  • 2020-12-23 13:02

    I think this little script I hacked together does the trick. If not, it's definitely a starting point! Good luck.

    #!/bin/bash                                                                                                                                                                                                                                                              
    
    ############################                                                                                                                                                                                                                                             
    ##  Methods                                                                                                                                                                                                                                                              
    ############################                                                                                                                                                                                                                                             
    prefix_to_bit_netmask() {
        prefix=$1;
        shift=$(( 32 - prefix ));
    
        bitmask=""
        for (( i=0; i < 32; i++ )); do
            num=0
            if [ $i -lt $prefix ]; then
                num=1
            fi
    
            space=
            if [ $(( i % 8 )) -eq 0 ]; then
                space=" ";
            fi
    
            bitmask="${bitmask}${space}${num}"
        done
        echo $bitmask
    }
    
    bit_netmask_to_wildcard_netmask() {
        bitmask=$1;
        wildcard_mask=
        for octet in $bitmask; do
            wildcard_mask="${wildcard_mask} $(( 255 - 2#$octet ))"
        done
        echo $wildcard_mask;
    }
    
    
    
    #######################                                                                                                                                                                                                                                                  
    ##  MAIN                                                                                                                                                                                                                                                                 
    #######################                                                                                                                                                                                                                                                  
    for ip in $@; do
        net=$(echo $ip | cut -d '/' -f 1);
        prefix=$(echo $ip | cut -d '/' -f 2);
    
        bit_netmask=$(prefix_to_bit_netmask $prefix);
    
        wildcard_mask=$(bit_netmask_to_wildcard_netmask "$bit_netmask");
    
        str=
        for (( i = 1; i <= 4; i++ )); do
            range=$(echo $net | cut -d '.' -f $i)
            mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
            if [ $mask_octet -gt 0 ]; then
                range="{0..$mask_octet}";
            fi
            str="${str} $range"
        done
        ips=$(echo $str | sed "s, ,\\.,g"); ## replace spaces with periods, a join...                                                                                                                                                                                        
        eval echo $ips | tr ' ' '\012'
    
    done
    
    0 讨论(0)
  • 2020-12-23 13:10

    You can use this script
    (you need to have "bc" installed on your system):

    for ip in $@ ;do
            net=$(echo $ip | cut -d '/' -f 1);
            prefix=$(echo $ip | cut -d '/' -f 2);
            o1=$(echo $net | cut -d '.' -f4);
            o2=$(echo $net | cut -d '.' -f3);
            o3=$(echo $net | cut -d '.' -f2);
            o4=$(echo $net | cut -d '.' -f1);
            len=$(echo "2^(32 - $prefix)"|bc);
            for i in `seq $len`;do
                    echo "$o4.$o3.$o2.$o1";
                    o1=$(echo "$o1+1"|bc);
                    if [ $o1 -eq 256 ]; then
                            o1=0;
                            o2=$(echo "$o2+1"|bc);
                            if [ $o2 -eq 256 ]; then
                                    o2=0;
                                    o3=$(echo "$o3+1"|bc);
                                    if [ $o3 -eq 256 ]; then
                                            o3=0;
                                            o4=$(echo "$o4+1"|bc);
                                    fi
                            fi
                    fi
            done
    done
    
    0 讨论(0)
  • 2020-12-23 13:12

    I too was looking for this solution and found that @scherand script worked great. I also have added to this script to give you more option. Help File below.

    THIS SCRIPT WILL EXPAND A CIDR ADDRESS.

    SYNOPSIS

    ./cidr-to-ip.sh [OPTION(only one)] [STRING/FILENAME]
    

    DESCRIPTION

    -h Displays this help screen

    -f Forces a check for network boundary when given a STRING(s)

    -i Will read from an Input file (file should contain one CIDR per line) (no network boundary check)

    -b Will do the same as –i but with network boundary check

    EXAMPLES

    ./cidr-to-ip.sh 192.168.0.1/24

    ./cidr-to-ip.sh 192.168.0.1/24 10.10.0.0/28

    ./cidr-to-ip.sh -f 192.168.0.0/16

    ./cidr-to-ip.sh -i inputfile.txt

    ./cidr-to-ip.sh -b inputfile.txt

    #!/bin/bash    
    
    ############################
    ##  Methods
    ############################   
    prefix_to_bit_netmask() {
        prefix=$1;
        shift=$(( 32 - prefix ));
    
        bitmask=""
        for (( i=0; i < 32; i++ )); do
            num=0
            if [ $i -lt $prefix ]; then
                num=1
            fi
    
            space=
            if [ $(( i % 8 )) -eq 0 ]; then
                space=" ";
            fi
    
            bitmask="${bitmask}${space}${num}"
        done
        echo $bitmask
    }
    
    bit_netmask_to_wildcard_netmask() {
        bitmask=$1;
        wildcard_mask=
        for octet in $bitmask; do
            wildcard_mask="${wildcard_mask} $(( 255 - 2#$octet ))"
        done
        echo $wildcard_mask;
    }
    
    check_net_boundary() {
        net=$1;
        wildcard_mask=$2;
        is_correct=1;
        for (( i = 1; i <= 4; i++ )); do
            net_octet=$(echo $net | cut -d '.' -f $i)
            mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
            if [ $mask_octet -gt 0 ]; then
                if [ $(( $net_octet&$mask_octet )) -ne 0 ]; then
                    is_correct=0;
                fi
            fi
        done
        echo $is_correct;
    }
    
    #######################
    ##  MAIN
    #######################
    OPTIND=1;
    getopts "fibh" force;
    
    shift $((OPTIND-1))
    if [ $force = 'h' ]; then
        echo ""
        echo -e "THIS SCRIPT WILL EXPAND A CIDR ADDRESS.\n\nSYNOPSIS\n  ./cidr-to-ip.sh [OPTION(only one)] [STRING/FILENAME]\nDESCRIPTION\n -h  Displays this help screen\n -f  Forces a check for network boundary when given a STRING(s)\n    -i  Will read from an Input file (no network boundary check)\n  -b  Will do the same as –i but with network boundary check\n\nEXAMPLES\n    ./cidr-to-ip.sh  192.168.0.1/24\n   ./cidr-to-ip.sh  192.168.0.1/24 10.10.0.0/28\n  ./cidr-to-ip.sh  -f 192.168.0.0/16\n    ./cidr-to-ip.sh  -i inputfile.txt\n ./cidr-to-ip.sh  -b inputfile.txt\n"
        exit
    fi
    
    if [ $force = 'i' ] || [ $force = 'b' ]; then
    
        old_IPS=$IPS
        IPS=$'\n'
        lines=($(cat $1)) # array
        IPS=$old_IPS
            else
                lines=$@
    fi
    
    for ip in ${lines[@]}; do
        net=$(echo $ip | cut -d '/' -f 1);
        prefix=$(echo $ip | cut -d '/' -f 2);
        do_processing=1;
    
        bit_netmask=$(prefix_to_bit_netmask $prefix);
    
        wildcard_mask=$(bit_netmask_to_wildcard_netmask "$bit_netmask");
        is_net_boundary=$(check_net_boundary $net "$wildcard_mask");
    
        if [ $force = 'f' ] && [ $is_net_boundary -ne 1 ] || [ $force = 'b' ] && [ $is_net_boundary -ne 1 ] ; then
            read -p "Not a network boundary! Continue anyway (y/N)? " -n 1 -r
            echo    ## move to a new line
            if [[ $REPLY =~ ^[Yy]$ ]]; then
                do_processing=1;
            else
                do_processing=0;
            fi
        fi  
    
        if [ $do_processing -eq 1 ]; then
            str=
            for (( i = 1; i <= 4; i++ )); do
                range=$(echo $net | cut -d '.' -f $i)
                mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
                if [ $mask_octet -gt 0 ]; then
                    range="{$range..$(( $range | $mask_octet ))}";
                fi
                str="${str} $range"
            done
            ips=$(echo $str | sed "s, ,\\.,g"); ## replace spaces with periods, a join...
    
            eval echo $ips | tr ' ' '\n'
    else
    exit
        fi
    
    done
    
    0 讨论(0)
  • 2020-12-23 13:13

    This short script will print all the IP addresses in a CIDR range in a few lines of Bash. (I named it prips after the Ubuntu command of the same name. Obviously, if that command is available, use that.)

    prips() {
      local cidr=$1 ; local lo hi a b c d e f g h
    
      # range is bounded by network (-n) & broadcast (-b) addresses.
      lo=$(ipcalc -n "$cidr" | cut -f2 -d=)
      hi=$(ipcalc -b "$cidr" | cut -f2 -d=)
    
      IFS=. read -r a b c d <<< "$lo"
      IFS=. read -r e f g h <<< "$hi"
    
      eval "echo {$a..$e}.{$b..$f}.{$c..$g}.{$d..$h}"
    }
    

    Note that I assume the RedHat Linux (Erik Troan, Preston Brown) version of ipcalc, not the Krischan Jodies version that is installed on some platforms (e.g. Mac OS X).

    Examples:

    $ prips 10.0.0.128/27
    10.0.0.128 10.0.0.129 10.0.0.130 10.0.0.131 10.0.0.132 10.0.0.133 10.0.0.134 10.0.0.135 10.0.0.136 10.0.0.137 10.0.0.138 10.0.0.139 10.0.0.140 10.0.0.141 10.0.0.142 10.0.0.143 10.0.0.144 10.0.0.145 10.0.0.146 10.0.0.147 10.0.0.148 10.0.0.149 10.0.0.150 10.0.0.151 10.0.0.152 10.0.0.153 10.0.0.154 10.0.0.155 10.0.0.156 10.0.0.157 10.0.0.158 10.0.0.159
    

    Calculates correct number of addresses in a /23 networks:

    $ prips 10.0.0.0/23 | wc -w 
    512
    

    Inspecting a few of those addresses using cut:

    $ prips 10.0.0.0/23 | cut -f1-10,256-266 -d' '
    10.0.0.0 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.5 10.0.0.6 10.0.0.7 10.0.0.8 10.0.0.9 10.0.0.255 10.0.1.0 10.0.1.1 10.0.1.2 10.0.1.3 10.0.1.4 10.0.1.5 10.0.1.6 10.0.1.7 10.0.1.8 10.0.1.9
    

    And maybe too slow but also correctly generates the 16 million addresses in a /8 network:

    $ date ; prips 10.0.0.0/8 | wc -w ; date 
    Sat May 20 18:06:00 AEST 2017
    16777216
    Sat May 20 18:06:41 AEST 2017
    
    0 讨论(0)
  • 2020-12-23 13:14

    Wanted to comment on an answer above but don't have the rep yet.

    Using the top solution with NMAP I added this to my .bashrc

    expand-ip() {
      nmap -sL -n -iL "$1" | awk '/Nmap scan report/{print $NF}'
    }
    

    Now I can use this with just expand-ip targs.

    0 讨论(0)
  • 2020-12-23 13:15
    fping -Aaqgr 1 10.1.1.0/24
    

    Simplicity works best

    0 讨论(0)
提交回复
热议问题