算法找到CIDR标记的IPv4网络的两个IPv4地址之间 [英] algorithm to find IPv4 networks in CIDR notation between two IPv4 addresses

查看:151
本文介绍了算法找到CIDR标记的IPv4网络的两个IPv4地址之间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找出所有在这两个网络之间CIDR标记的IPv4网络:

I would like to find out all the IPv4 networks in CIDR notation between those two networks:

10.11.3.64-10.11.3.127
10.11.52.0-10.11.52.255

IPv4网络应该有短子网掩码越好。

IPv4 networks should have as short subnet-mask as possible.

这是相当容易 10.11.3.127 转换成二进制,添加 1 和转换回十进制,以获得该网络的第一个地址。然后转换 10.11.52.0 成二进制,减 1 和转换回十进制,以获得的最后一个地址网络。然而,任何建议的算法是聪明才能使用,找出里面的CIDR块 10.11.3.128-10.11.51.255 范围是多少?就在哪个方向,我应该想到的建议将有望足够:)

It's fairly easy to convert 10.11.3.127 into binary, add 1 and convert back to decimal in order to get the first address of the network. Then convert 10.11.52.0 into binary, subtract 1 and convert back to decimal in order to get the last address of the network. However, any suggestions which algorithm is clever to use in order to find out the CIDR blocks inside the 10.11.3.128-10.11.51.255 range? Just a suggestion in which direction should I think would hopefully be enough :)

推荐答案

我真的很喜欢这个问题,我接过来一看,昨晚,决定给它一个镜头。在这一点上我有概念的shell脚本工作的证明。

I really like this problem, I took a look last night and decided to give it a shot. At this point I have a proof of concept shell script working.

声明:


  1. 这是一个概念证明只有

  2. 我种在这里重新发明了轮子,因为我没有使用任何TCP / IP库

  3. 我并没有实现输入验证

  4. 如果用一种程序语言,而不是bash中,虽然这种特异性网络范围也不是那么慢这code可能会更快

值得一提的另一件事是,我的理解:

Another thing worth mentioning is that my understanding of:

IPv4网络应该有短子网掩码越好。

是,我们应该从尝试 8 保留网络达提供最大的CIDR,在这种情况下位的 25

is that we should try from 8 bits reserved to network up to the greatest cidr provided, in this case 25.

OK,让我们看到了工作中的脚本:

OK, let us see the script in action:

[root@TIAGO-TEST2 tmp]# time bash  ip.sh   10.11.3.64/25 10.11.52.0/24 
10.11.3.128/25
10.11.4.0/22
10.11.8.0/21
10.11.16.0/20
10.11.32.0/20
10.11.48.0/22

real    0m48.376s
user    0m6.174s
sys     0m34.644s

下面以code:

Below the code:

#! /bin/bash

function split_octet {
    sed -re "s/\./ /g" <<< "$1"
}

function dec2bin {
    perl -e 'printf "%0'"$1"'b\n",'"$2"';'
}

function bin2dec {
    perl -le 'print 0b'"$1"';'
}

function ip2bin {
    str=""
    for octet in $(split_octet $1); do
        str="${str}$(dec2bin 8 $octet)"
    done
    echo "$str"
}

function bin2ip {
    str=""
    for octet in $(grep -Eo '.{8}' <<< $1); do
        dec=$(bin2dec $octet)
        str="${str}.${dec}"
    done
    echo "$str" | sed -re 's/^\.|\.$//g'
}

function ip2dec {
    ip=$1
    bin2dec $(ip2bin $ip )
}

function dec2ip  {
    dec=$1
    bin2ip $(dec2bin 32 $dec )
}

function AND {
    perl -e '   $a=0b'"$1"' & 0b'"$2"';
                        printf "%032b\n",$a
                    '
}

function OR {
    perl -e '   $a=0b'"$1"' | 0b'"$2"';
                        printf "%032b\n",$a
                    '
}

function NOT {
    perl -le '  $a= (~ 0b'"$1"') & 0xFFFFFFFF; 
                            printf "%032b\n",$a
                     '
}

function get_network {
    ip=$1; mask=$2;

    if [ -n "$ip" -a -n "$mask" ];then
    echo $(bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask)))
        return
    fi

    grep -qP "\d+\.\d+\.\d+.\d+/\d+" <<< "$ip"
    if [ "$?" == 0 ];then
        ip=$(get_ip_from_cidr $1 )
        mask=$(get_mask_from_cidr $1)
        echo $( bin2ip $(AND $(ip2bin $ip) $(ip2bin $mask)))
    fi
}

function get_broadcast {
    ip=$1; mask=$2;

    if [ -n "$ip" -a -n "$mask" ];then
        echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) ))
        return
    fi

    grep -qP "\d+\.\d+\.\d+.\d+/\d+" <<< "$ip"
    if [ "$?" == 0 ];then
        ip=$(get_ip_from_cidr $1 )
        mask=$(get_mask_from_cidr $1)
        echo $( bin2ip $(OR $(ip2bin $ip) $(NOT $(ip2bin $mask) ) ))
    fi

}

function get_ip_from_cidr {
    awk -F/ '{print $1}' <<< "$1"
}

function get_mask_from_cidr {
    mask=$(awk -F/ '{print $2}' <<< "$1")
    mask=$(cidr $mask)
    mask=$(bin2ip $mask)
    echo $mask
}

function cidr {
    perl -e '
                        $n='"$1"';
                        $diff=32-$n;
                        print "1"x$n . "0"x$diff;
                    '
}


snet_cidr=$1
enet_cidr=$2

largest_cidr=$(echo -e "$snet_cidr\n$enet_cidr"| awk -F/ '{print $2}' | sort -rn | head -1 )

snet_dec=$( ip2dec $(get_ip_from_cidr $snet_cidr))
enet_dec=$( ip2dec $(get_ip_from_cidr $enet_cidr))

sbc_ip=$(get_broadcast $snet_cidr)
ebc_ip=$(get_broadcast $enet_cidr)

sbc_dec=$(ip2dec $sbc_ip)
ebc_dec=$(ip2dec $ebc_ip)

counter=$sbc_dec

while [ $counter -lt $enet_dec ];do
    tip=$(dec2ip $counter)
    for cidr in $(seq 8 $largest_cidr) ; do 
        tnet_ip=$(get_network $tip/$cidr)
        tnet_cidr=$tnet_ip/$cidr
        tbc_ip=$(get_broadcast $tnet_cidr)
        tnet_dec=$( ip2dec $(get_ip_from_cidr $tnet_cidr))
        tbc_dec=$(ip2dec $tbc_ip)
        if [ $sbc_dec -lt $tnet_dec -a $enet_dec -gt $tbc_dec ];then
            echo $tnet_cidr 
            counter=$tbc_dec
            break
        fi  
    done
    let counter++
done

修改这可能是一个好主意,解释这些变量是:

Edit It's probably a good idea to explain what those variables are:


  1. snet_cidr:在CIDR标记启动网

  2. enet_cidr:年底净CIDR

  3. snet_dec:十进制开始净

  4. enet_dec:年底净十进制

  5. sbc_ip:开始广播IP

  6. ebc_ip:结束广播IP

  7. sbc_dec:开始广播IP

  8. ebc_dec:结束广播IP

和当你看到TNET或TBC是临时网,广播温度,温度,因为它是内循环。

And wherever you see tnet or tbc is temp net, temp broadcast, temp because it's inside the loop.

这篇关于算法找到CIDR标记的IPv4网络的两个IPv4地址之间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆