2014-09-19 31 views
5

Tôi muốn tìm hiểu tất cả các mạng IPv4 trong ký hiệu CIDR giữa hai mạng:thuật toán để tìm mạng IPv4 trong ký hiệu CIDR giữa hai địa chỉ IPv4

10.11.3.64-10.11.3.127 
10.11.52.0-10.11.52.255 

mạng IPv4 nên có càng ngắn subnet-mask như khả thi.

Thật dễ dàng để chuyển đổi 10.11.3.127 thành nhị phân, thêm 1 và chuyển đổi về số thập phân để nhận địa chỉ đầu tiên của mạng. Sau đó chuyển đổi 10.11.52.0 thành nhị phân, trừ 1 và chuyển đổi về số thập phân để nhận địa chỉ cuối cùng của mạng. Tuy nhiên, bất kỳ đề xuất nào thuật toán thông minh để sử dụng để tìm ra các khối CIDR bên trong phạm vi 10.11.3.128-10.11.51.255? Chỉ cần một gợi ý mà theo hướng tôi nên nghĩ hy vọng là đủ :)

+0

Giải thích 'Mạng IPv4 phải có mặt nạ mạng con ngắn càng tốt.' – hek2mgl

+0

@ hek2mgl Điều này có nghĩa là tiền tố IPv4 phải càng lớn càng tốt. Ví dụ phạm vi mạng '10.11.3.128-10.11.51.255' có thể được trình bày trong ký hiệu CIDR với' 10.11.3.128/25' và sau đó từ '10.11.4.0/24' thành' 10.11.51.0/24' bằng cách sử dụng/24 tiền tố trong khi thực sự những '/ 24' đó có thể được tổng hợp. – Martin

+0

hoặc từ '10.11.3.128/0' đến' 10.11.51.255/0' bằng tiền tố 32 bit thực sự là tiền tố lớn nhất có thể cho IPV4 .. đó là lý do tôi hỏi .. – hek2mgl

Trả lời

2

Nếu bạn muốn có mặt nạ ngắn nhất (mạng lớn nhất), hãy bắt đầu với địa chỉ thấp nhất (10.11.3.128) và đặt mặt nạ nhỏ nhất có thể, bắt đầu tại địa chỉ sau và đặt trên mặt nạ nhỏ nhất có thể, vv Chỉ cần không vượt quá địa chỉ lớn nhất của dãy núi này:

  1. 10.11.3.128/25 (10.11.3.128 để 10.11.3.255) bất cứ điều gì nhỏ hơn là không hợp lệ
  2. 10.11.4.0/22 ​​(10.11.4.0 đến 10.11.7.255) mọi thứ nhỏ hơn không hợp lệ
  3. 10.11.8.0/21 (10.11.8.0 đến 10.11.15.255) anyt hing nhỏ hơn không hợp lệ
  4. 10.11.16.0/20 (10.11.16.0 đến 10.11.31.255) mọi thứ nhỏ hơn không hợp lệ
  5. 10.11.32.0/20 (10.11.32.0 đến 10.11.47.255)/19 hợp lệ, nhưng sẽ quá xa
  6. 10.11.48.0/22 ​​(10.11.48.0 để 10.11.51.255)/20 và/21 có hiệu lực, nhưng sẽ đi quá xa

Nhìn vào này trong hệ nhị phân, nó trở nên rõ ràng. Mặt nạ được ANDed với mạng con (bất kỳ vị trí nào có số không trong mạng con hoặc mặt nạ trở thành số không; vị trí phải có vị trí trong cả mạng con và mặt nạ để có mặt con). Nếu bạn VÀ một mạng con và một mặt nạ, và nó không bằng subnet, nó không hợp lệ.

Tất cả các tính toán địa chỉ IP cần được thực hiện theo dạng nhị phân. Ký hiệu chấm thập phân là tốt cho khả năng đọc của con người, nhưng không nên được sử dụng để thực hiện các phép tính địa chỉ IP.

2

Tôi thực sự thích vấn đề này, tôi đã xem qua đêm qua và quyết định cho nó một shot. Tại thời điểm này tôi có một bằng chứng về kịch bản shell script làm việc.

Disclaimer:

  1. Đây là một bằng chứng của khái niệm chỉ
  2. tôi loại được tái phát minh ra bánh xe ở đây vì tôi không sử dụng bất kỳ/thư viện TCP IP
  3. tôi đã không thực hiện xác nhận đầu vào
  4. Mã này có thể nhanh hơn nhiều nếu được viết bằng ngôn ngữ lập trình thay vì bash, mặc dù phạm vi mạng specif này không quá chậm

Một điều đáng nói là sự hiểu biết của tôi về:

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

là chúng ta nên cố gắng từ bit dành cho mạng lên đến cidr lớn nhất cung cấp, trong trường hợp này .

OK, chúng ta hãy xem các kịch bản trong hành động:

[[email protected] 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 

Dưới mã:

#! /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 

Sửa Nó có thể là một ý tưởng tốt để giải thích những gì các biến là:

  1. snet_cidr: bắt đầu lưới trong ký hiệu cidr
  2. enet_cidr: cuối ròng trong cidr
  3. snet_dec: bắt đầu ròng trong thập phân
  4. enet_dec: cuối ròng trong thập phân
  5. sbc_ip: bắt đầu phát sóng ip
  6. ebc_ip: cuối phát sóng ip
  7. sbc_dec: bắt đầu phát sóng ip
  8. ebc_dec: cuối phát sóng ip

Và bất cứ nơi nào bạn nhìn thấy tnet hoặc tbc là net tạm thời, tạm thời quảng bá, tạm thời vì nó insid e vòng lặp.

Các vấn đề liên quan