Keluarkan semua alamat IPv4 unicast publik berkelas yang valid


10

Alamat IPv4 adalah lebar 32 bit, dan dengan demikian ukuran ruang alamat adalah 2 32 , atau 4.294.967.296. Namun, ini hanya batas atas teoretis. Ini bukan representasi akurat dari semua alamat yang sebenarnya dapat digunakan di internet publik.

Untuk keperluan tantangan ini, diasumsikan bahwa semua pengalamatan bersifat classful . Pada kenyataannya, pembagian ruang alamat kelas telah digantikan oleh CIDR (Classless Inter-Domain Routing dan VLSM (Variable Length Subnet Masking) , tetapi ini diabaikan untuk tantangan ini.

Menurut skema alamat classful, ada 3 kelas:

  • Kelas A - 0.0.0.0untuk 127.255.255.255dengan /8panjang netmask
  • Kelas B - 128.0.0.0untuk 191.255.255.255dengan /16panjang netmask
  • Kelas C - 192.0.0.0ke 223.255.255.255dengan /24panjang netmask

Kelas D (multicast) dan E (dicadangkan) juga ditentukan, tetapi ini tidak digunakan untuk alamat unicast publik.

Setiap kelas dibagi menjadi jaringan sesuai dengan netmask untuk kelas itu.

Dengan demikian 3.0.0.0adalah contoh dari jaringan Kelas A. Panjang netmask untuk Kelas A adalah 8, jadi ruang alamat lengkap untuk jaringan ini adalah 3.0.0.0untuk 3.255.255.255. Namun, alamat pertama ( 3.0.0.0) dicadangkan sebagai alamat jaringan dan alamat terakhir ( 3.255.255.255) dicadangkan sebagai alamat siaran untuk jaringan itu. Dengan demikian rentang sebenarnya dari alamat yang dapat digunakan adalah 3.0.0.1ke 3.255.255.2542 24 - 2 (= 16.777.214) total alamat.

Demikian pula, 200.20.30.0adalah contoh dari jaringan Kelas C. Panjang netmask untuk Kelas C adalah 24, jadi ruang alamat lengkap untuk jaringan ini adalah 200.20.30.0untuk 200.20.30.255. Menghapus jaringan dan menyiarkan alamat meninggalkan kisaran sebenarnya dari alamat yang dapat digunakan adalah 200.20.30.1ke 200.20.30.2542 8 - 2 (= 254) alamat total.

Ada batasan lebih lanjut pada rentang alamat yang dapat digunakan untuk unicast publik. Menurut RFC 6890 , rentang yang tidak diizinkan adalah:

  • 0.0.0.0/8 - Jaringan lokal
  • 10.0.0.0/8 - Penggunaan Pribadi
  • 100.64.0.0/10 - Ruang Alamat Bersama
  • 127.0.0.0/8 - Loopback
  • 169.254.0.0/16 - Tautan Lokal
  • 172.16.0.0/12- Penggunaan Pribadi
  • 192.0.0.0/24 - Penugasan Protokol IETF
  • 192.0.2.0/24 - Dicadangkan untuk digunakan dalam dokumentasi
  • 192.88.99.0/24 - 6to4 Relay Anycast
  • 192.168.0.0/16 - Penggunaan Pribadi
  • 198.18.0.0/15 - Pembandingan
  • 198.51.100.0/24 - Dicadangkan untuk digunakan dalam dokumentasi
  • 203.0.113.0/24 - Dicadangkan untuk digunakan dalam dokumentasi

Perhatikan bahwa daftar di atas menggunakan netmask VLSR untuk menentukan rentang secara efisien. Dalam semua kecuali satu kasus, panjang topeng yang diberikan memiliki spesifisitas kurang dari atau sama dengan panjang topeng berkelas normal untuk awal kisaran. Dengan demikian masing-masing rentang VLSR ini setara dengan satu atau lebih jaringan classful. Misalnya 172.16.0.0/12setara dengan jaringan Kelas B 172.16.0.0untuk 172.31.0.0atau kisaran alamat 172.16.0.0untuk 172.31.255.255.

Pengecualian untuk aturan ini adalah 100.64.0.0/10rentang VLSR, yang lebih spesifik daripada kisaran 100.0.0.0Kelas A yang mengandung . Dengan demikian 100.0.0.0akan ditangani seperti rentang Kelas A lainnya dengan pengecualian memiliki lubang alamat 4.194.304 di tengah. Alamat yang valid dalam kisaran Kelas A ini adalah 100.0.0.0untuk 100.63.255.255dan 100.128.0.0untuk 100.255.255.254, total 2 24 - 2 22 - 2 (= 12.582.910) total alamat.

Tujuan dari tantangan ini adalah untuk mengeluarkan semua alamat IPv4 Kelas A, B, dan C unicast yang dapat ditetapkan secara sah ke host internet publik (yaitu tidak termasuk yang dirinci di atas).

  • Tidak ada input yang akan diberikan dan seharusnya tidak diharapkan.

  • Output mungkin dalam bentuk apa pun nyaman untuk bahasa Anda, misalnya array, daftar, string yang dibatasi. Alamat harus berupa output dalam format desimal bertitik standar.

  • Urutan output tidak masalah.

  • Dibangun secara khusus yang memberikan rentang alamat yang diperlukan tidak diizinkan. Demikian pula, setiap metode untuk memeriksa tabel routing BGP (atau protokol lainnya) secara dinamis untuk internet publik dilarang.

Alamat yang paling rendah secara numerik adalah 1.0.0.1dan yang paling tinggi secara numerik 223.255.255.254.


Tantangan ini mirip dengan Mencetak semua alamat IPv6 , tetapi karena pembatasan harus memerlukan implementasi yang berbeda-beda.

Jawaban:


2

PowerShell, 648 641 625 byte

for([uint64]$a=16MB;$a-lt2GB-16mb;$a++){if(($a%16mb)*(($a+1)%16mb)*($a-lt160MB-or$a-gt176MB)*($a-lt1604MB-or$a-ge1608MB)){([ipaddress]$a).IPAddressToString}}
for($a=2GB;$a-lt3GB;$a++){if(($a%64kb)*(($a+1)%64kb)*($a-lt2785152kb-or$a-gt2720mb)*($a-lt2753mb-or$a-gt2754mb)){([ipaddress]$a).IPAddressToString}}
for($a=3221225728;$a-lt3.5GB;$a++){if(($a%256)*(($a+1)%256)*(($a-lt3221225984-or$a-gt3221226240))*(($a-lt3227017984-or$a-gt3151385kb))*(($a-lt3156480kb-or$a-gt3156544kb))*(($a-lt3245184kb-or$a-gt3245312kb))*(($a-lt3247321kb-or$a-gt3325256959))*(($a-lt3405803776-or$a-gt3405804032))){([ipaddress]$a).IPAddressToString}}

Sunting 1 - Saya telah menghentikan semua operator dua kekuatan yang tersisa, yang menghemat 7 byte tambahan.
Sunting 2 - Memindahkan para [uint64]pemeran ke deklarasi pertama $ayang menghilangkan dua pemeran ulang lainnya yang menghemat 16 byte.

Tiga baris, Kelas A / Kelas B / Kelas C. Dibiarkan sebagai baris terpisah untuk dibaca. ;-)

Dua poin kunci untuk memahami apa yang terjadi:

  • PowerShell memiliki kekuatan-dari-dua operator KB, MB, GB. Misalnya, 4KBakan kembali 4096sebagai int. Kami memanfaatkan itu di beberapa lokasi untuk mencukur lusinan byte.
  • Kelas .NET [ipaddress]akan mencoba mengurai nilai numerik sebagai alamat IP dengan mengambil representasi biner angka tersebut. Kami menggunakan konstruktor itu dengan IPAddressToStringargumen untuk keluaran.

Dengan menggabungkan kedua hal itu, kami dapat memperlakukan alamat IP sebagai angka dan memutarnya dengan satu for()lingkaran. Misalnya, loop pertama untuk subnet Kelas A beralih dari 16MBke 2GB-16MB, atau dari 16777216ke 2130706432. Representasi biner 16777216adalah 1000000000000000000000000atau 00000001.00000000.00000000.00000000jika kita membaginya menjadi potongan 8-bit sehingga kita dapat dengan mudah melihat yang sesuai dengan 1.0.0.0notasi desimal bertitik. Demikian pula, 2130706432dapat ditulis sebagai 01111111000000000000000000000000atau 01111111.00000000.00000000.00000000atau 127.0.0.0. Setiap integer, atau power-of-two integer, yang digunakan di sini dapat ditulis ulang sebagai alamat IP dengan cara ini.

Jadi, untuk setiap iterasi loop, kami membuat if()pernyataan untuk menyingkirkan alamat yang dikecualikan, dengan mengalikan pernyataan individual menjadi satu. Karena pernyataan pertama di masing if- masing adalah bilangan bulat (berkat pengujian modulo), nilai Boolean yang tersisa dikonversi menjadi salah 0atau 1untuk false / true. Jika salah satu dari pernyataan itu salah, seluruh perkalian akan berubah menjadi 0dan dengan demikian salah. Jadi, hanya jika semua pernyataan itu benar, akan kami hasilkan hasil parsing.

Sedikit Tidak Disatukan:

# Class A
for($a=16MB;$a-lt2GB-16mb;$a++){
  $b=($a%16mb)                     # x.0.0.0
  $b*=(($a+1)%16mb)                # x.255.255.255
  $b*=($a-lt160MB-or$a-gt176MB)    # 10.0.0.0/8
  $b*=($a-lt1604MB-or$a-ge1608MB)  # 100.64.0.0/10
  if($b){([ipaddress]::Parse($a)).IPAddressToString}
}

# Class B
for($a=2GB;$a-lt3GB;$a++){
  $b=($a%64kb)                           # x.y.0.0
  $b*=(($a+1)%64kb)                      # x.y.255.255
  $b*=(($a-lt2785152kb-or$a-gt2720mb))  # 169.254.0.0/16
  $b*=(($a-lt2753mb-or$a-gt2754mb))      # 172.16.0.0/12
  if($b){([ipaddress]::Parse($a)).IPAddressToString}
}

# Class C
for($a=3221225728;$a-lt3.5GB;$a++){
  $b=($a%256)                               # x.y.z.0
  $b*=(($a+1)%256)                          # x.y.z.255
  $b*=(($a-lt3221225984-or$a-gt3221226240)) # 192.0.2.0/24
  $b*=(($a-lt3227017984-or$a-gt3151385kb)) # 192.88.99.0/24
  $b*=(($a-lt3156480kb-or$a-gt3156544kb)) # 192.168.0.0/16
  $b*=(($a-lt3245184kb-or$a-gt3245312kb)) # 198.18.0.0/15
  $b*=(($a-lt3247321kb-or$a-gt3325256959)) # 198.51.100.0/24
  $b*=(($a-lt3405803776-or$a-gt3405804032)) # 203.0.113.0/24
  if($b){([ipaddress]::Parse($a)).IPAddressToString}
}

1

Batch, 1930 1884 1848 1830 byte

@echo off
for /l %%a in (1,1,9)do call:a1 %%a
for /l %%a in (11,1,99)do call:a1 %%a
for /l %%b in (0,1,63)do call:a2 100 %%b
for /l %%b in (128,1,255)do call:a2 100 %%b
for /l %%a in (101,1,126)do call:a1 %%a
for /l %%a in (128,1,168)do call:b1 %%a
for /l %%b in (0,1,253)do call:b2 169 %%b
call:b2 169 255
call:b1 170
call:b1 171
for /l %%b in (0,1,15)do call:b2 172 %%b
for /l %%b in (32,1,255)do call:b2 172 %%b
for /l %%a in (173,1,191)do call:b1 %%a
call:c3 192 0 1
for /l %%c in (3,1,255)do call:c3 192 0 %%c
for /l %%b in (1,1,87)do call:c2 192 %%b
for /l %%c in (0,1,98)do call:c3 192 88 %%c
for /l %%c in (100,1,255)do call:c3 192 88 %%c
for /l %%b in (89,1,167)do call:c2 192 %%b
for /l %%b in (169,1,255)do call:c2 192 %%b
for /l %%a in (193,1,197)do call:c1 %%a
for /l %%b in (0,1,17)do call:c2 198 %%b
for /l %%b in (20,1,50)do call:c2 198 %%b
for /l %%c in (0,1,99)do call:c3 198 51 %%c
for /l %%c in (101,1,255)do call:c3 198 51 %%c
for /l %%b in (52,1,255)do call:c2 198 %%b
for /l %%a in (199,1,202)do call:c1 %%a
for /l %%c in (0,1,112)do call:c3 203 0 %%c
for /l %%c in (114,1,255)do call:c3 203 0 %%c
for /l %%b in (1,1,255)do call:c2 203 %%b
for /l %%a in (204,1,223)do call:c1 %%a
exit/b
:a1
for /l %%b in (0,1,255)do call:a2 %1 %%b
exit/b
:a2
for /l %%c in (0,1,255)do call:a3 %1 %2 %%c
exit/b
:a3
for /l %%d in (0,1,255)do if not %2%3%%d==000 if not %2%3%%d==255255255 echo %1.%2.%3.%%d
exit/b
:b1
for /l %%b in (0,1,255)do call:b2 %1 %%b
exit/b
:b2
for /l %%c in (0,1,255)do call:b3 %1 %2 %%c
exit/b
:b3
for /l %%d in (0,1,255)do if not %3%%d==00 if not %3%%d==255255 echo %1.%2.%3.%%d
exit/b
:c1
for /l %%b in (0,1,255)do call:c2 %1 %%b
exit/b
:c2
for /l %%c in (0,1,255)do call:c3 %1 %2 %%c
exit/b
:c3
for /l %%d in (1,1,254)do echo %1.%2.%3.%%d

Sunting: Disimpan 46 82 byte dengan menghapus spasi yang tidak perlu. Disimpan 18 byte dengan menggunakan exit/bbukan goto:eof.


1
Saya menghitung 1872 byte. Secara teknis Anda tidak membutuhkannya @echo offjuga.
Addison Crump

@FlagAsSpam Mungkin CRs; Notepad suka menyimpannya.
Neil

Saya pikir Anda dapat menghapusnya, karena kami menghitung dengan Unix UTF-8 byte.
Addison Crump
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.