Выведите все действительные классные публичные одноадресные IPv4-адреса


10

Адреса IPv4 имеют ширину 32 бита, поэтому размер адресного пространства составляет 2 32 , или 4 294 967 296. Однако это только теоретическая верхняя граница. Это не точное представление всех адресов, которые могут фактически использоваться в общедоступном Интернете.

Для целей этой задачи предполагается, что вся адресация является классной . В действительности, классовое подразделение адресного пространства было заменено CIDR (Бесклассовая междоменная маршрутизация и VLSM (Маскировка подсети переменной длины) , но это игнорируется для этой задачи.

Согласно классной адресной схеме, существует 3 класса:

  • Класс А - 0.0.0.0чтобы 127.255.255.255с /8NETMASK длиной
  • Класс B - 128.0.0.0чтобы 191.255.255.255с /16NETMASK длиной
  • Класс C - 192.0.0.0чтобы 223.255.255.255с /24NETMASK длиной

Классы D (многоадресная) и E (зарезервированные) также определены, но они не используются для общедоступных одноадресных адресов.

Каждый класс подразделяется на сети в соответствии с маской сети для этого класса.

Таким образом, 3.0.0.0пример сети класса А. Длина маски подсети для класса А составляет 8, так что полное адресное пространство этой сети , 3.0.0.0чтобы 3.255.255.255. Однако первый адрес ( 3.0.0.0) зарезервирован как сетевой адрес, а последний адрес ( 3.255.255.255) зарезервирован как широковещательный адрес для этой сети. Таким образом, фактический диапазон используемых адресов 3.0.0.1для 3.255.255.254которого составляет 2 24 - 2 (= 16,777,214) весь адрес.

Точно так же 200.20.30.0пример сети класса C. Длина маски подсети для класса С составляет 24, так что полное адресное пространство этой сети , 200.20.30.0чтобы 200.20.30.255. Удаление сети и широковещательные адреса оставляют фактический диапазон используемых адресов 200.20.30.1для 200.20.30.254которого составляет 2 8 - 2 (= 254) весь адрес.

Существуют дополнительные ограничения на диапазоны адресов, которые могут использоваться для одноадресной рассылки. Согласно RFC 6890 запрещенные диапазоны:

  • 0.0.0.0/8 - Локальные сети
  • 10.0.0.0/8 - Частное использование
  • 100.64.0.0/10 - Общее адресное пространство
  • 127.0.0.0/8 - петля
  • 169.254.0.0/16 - Ссылка Локальная
  • 172.16.0.0/12- Частное использование
  • 192.0.0.0/24 - Назначения протокола IETF
  • 192.0.2.0/24 - Зарезервировано для использования в документации
  • 192.88.99.0/24 - 6to4 эстафета Anycast
  • 192.168.0.0/16 - Частное использование
  • 198.18.0.0/15 - Бенчмаркинг
  • 198.51.100.0/24 - Зарезервировано для использования в документации
  • 203.0.113.0/24 - Зарезервировано для использования в документации

Обратите внимание, что в приведенном выше списке используются маски VLSR для эффективного указания диапазона. Во всех случаях, кроме одного, заданная длина маски имеет специфичность, меньшую или равную нормальной длине классной маски для начала диапазона. Таким образом, каждый из этих диапазонов VLSR эквивалентен одной или нескольким классным сетям. Например , 172.16.0.0/12эквивалентна сети класса B 172.16.0.0до 172.31.0.0или диапазон адресов 172.16.0.0к 172.31.255.255.

Исключением из этого правила является 100.64.0.0/10диапазон VLSR, который является более конкретным, чем содержащий 100.0.0.0диапазон класса A. Таким образом, 100.0.0.0будет обрабатываться, как и другие диапазоны класса A, за исключением того, что в середине имеется дыра с 4 194 304 адресами. Действительными адресами в этом диапазоне класса А будут 100.0.0.0до 100.63.255.255и 100.128.0.0до 100.255.255.254, всего 2 24 - 2 22 - 2 (= 12 582 910) адресов.

Цель этой задачи состоит в том, чтобы вывести все IPv4-адреса классов A, B и C одноадресной рассылки, которые могут быть правильно назначены общедоступному узлу Интернета (т.е. исключая адреса, подробно описанные выше).

  • Вклад не будет дан, и не следует ожидать.

  • Вывод может быть в любой форме, удобной для вашего языка, например, массив, список, строка с разделителями. Адреса должны выводиться в стандартном десятичном формате с точками.

  • Порядок вывода не имеет значения.

  • Встроенные функции, которые специально предоставляют требуемые диапазоны адресов, запрещены. Точно так же запрещены любые методы динамической проверки таблицы маршрутизации BGP (или другого протокола) для общедоступного Интернета.

Численно самый низкий адрес будет, 1.0.0.1а численно самый высокий будет 223.255.255.254.


Эта задача аналогична распечатке всех адресов IPv6 , но из-за ограничений должна требоваться нетривиально другая реализация.

Ответы:


2

PowerShell, 648 641 625 байт

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}}

Правка 1 - я проиграл все оставшиеся операторы степеней двух, что сэкономило дополнительные 7 байтов.
Редактировать 2 - перемещено [uint64]приведение к первому объявлению, $aкоторое исключило два других повторных приведения, которые сохранили 16 байтов.

Три строки, класс A / класс B / класс C. Оставлены как отдельные строки для удобства чтения. ;-)

Два ключевых момента для понимания того, что происходит:

  • PowerShell имеет операторы двух степеней KB, MB, GB. Например, 4KBвернется 4096как int. Мы используем это в нескольких местах, чтобы сбрить десятки байтов.
  • Класс .NET [ipaddress]попытается проанализировать числовое значение как IP-адрес, взяв двоичное представление числа. Мы используем этот конструктор с IPAddressToStringаргументом для вывода.

Соединяя эти две вещи, мы можем просто рассматривать IP-адреса как числа и проходить через них с помощью for()цикла. Например, первый цикл для подсетей класса A идет от 16MBк 2GB-16MBили от 16777216к 2130706432. Двоичное представление 16777216- это 1000000000000000000000000или, 00000001.00000000.00000000.00000000если мы разделим его на 8-битные порции, чтобы мы могли легко увидеть, что соответствует 1.0.0.0десятичной записи в точках. Точно так же 2130706432может быть написано как 01111111000000000000000000000000или 01111111.00000000.00000000.00000000или 127.0.0.0. Каждое целое число, или целое число степени два, используемое здесь, может быть переписано как IP-адрес таким способом.

Итак, для каждой итерации цикла мы создаем if()оператор, чтобы отсеять исключенные адреса, умножив отдельные операторы вместе. Так как первое утверждение в каждом ifпредставляет собой целое число (благодаря тестированию по модулю), остальные логические значения преобразуются либо 0или 1за ложный / истинные. Если любое из утверждений ложно, все умножение превратится в 0и, следовательно, будет ложным. Таким образом, только если все утверждения верны, мы выведем результат синтаксического анализа.

Слегка безжалостный:

# 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

Пакет, 1930 1884 1848 1830 байтов

@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

Редактировать: 46 46 байтов сохранены , удалив ненужные пробелы. Сохранено 18 байт с использованием exit/bвместо goto:eof.


1
Я считаю 1872 байта. Тебе технически это тоже не нужно @echo off.
Эддисон Крамп

@FlagAsSpam Вероятно, CR; Блокнот любит их сохранять.
Нил

Я думаю, что вы можете удалить их, так как мы считаем Unix UTF-8 байтов.
Эддисон Крамп
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.