Создание сетевой программы DHCP server

Методы исследования силовых преобразователей электроэнергии. Протокол динамической настройки узла как альтернатива рутинной ручной настройке параметров сети для сервера или подключаемого устройства. Знание основ DHCP для устранения проблем с сетью.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 19.12.2018
Размер файла 1,5 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

Министерство по развитию информационных технологий и коммуникаций Республики Узбекистан

Ташкентский университет информационных технологий имени Ал-Хорезми

Кафедра А и ПОСУТ

Курсовая работа

По дисциплине: Основы сетевого программирования

Создание сетевой программы DHCP server

Выполнил:

Урманов М.И.

Гр. 423-15

Приняла:

Ахмедова Х.Х.

Ташкент 2018

Введение

преобразователь электроэнергия сервер сеть

Компьютерные сети бывают разных видов и конфигураций: локальные (LAN), глобальные (WAN) и т.д. Если вы подключаетесь к локальной LAN сети или интернету, компьютеру присваивается собственный IP адрес. Он помогает идентифицировать любое устройство, подключенное к сети. В большинстве случаев, когда вы подключаетесь к LAN или Интернету, вы можете заметить, что IP и другая информация, например маска подсети, присваиваются автоматически. Задумывались вы, как это происходит? В этой статье мы попробуем разобрать концепцию DHCP, на которой основываются принципы данного процесса.

DHCP является расширением сетевого протокола IP-протокола 1985 года, протокола Bootstrap (BOOTP). DHCP более продвинутый, и DHCP-серверы могут обрабатывать запросы клиентов BOOTP, если в сегменте сети существуют какие-либо клиенты BOOTP. Используя один центральный сервер BOOTP для обслуживания хостов во многих IP-подсетях, BOOTP представил концепцию ретрансляционного агента, которая позволила пересылать пакеты BOOTP по сетям. Однако BOOTP требовал ручной процесс для добавления информации о конфигурации для каждого клиента и не предоставлял механизм для восстановления IP-адресов, которые больше не используются.

А ведь это очень важный момент! Этот протокол значительно облегчает жизнь системному администратору при настройке и управлении сетями. Он работает как в обычных домашних сетях на бытовых WiFi-роутерах и модемах, так и в крупных корпоративных сетях и помогает компьютеру, ноутбуку или иному сетевому устройству быстро получить АйПи-адрес и идентифицироваться.

1. Задачи и методы исследования силовых преобразователей электроэнергии

1.1 Классификация силовых преобразователей электроэнергии

Что такое DHCP?

DHCP - это протокол динамической настройки узла.

Как можно понять из названия, DHCP предназначен для настройки хоста через удаленный сервер. DCHP поддерживается по умолчанию большинством современных операционных систем, и этот протокол выступает в качестве отличной альтернативы рутинной ручной настройке параметров сети для сервера или подключаемого устройства.

Данный протокол работает на основе модели "Клиент-сервер". Являясь протоколом, DHCP имеет свой собственный метод обмена сообщениями между клиентом и сервером. Ниже представлен состав сообщения DHCP:

Поле

Длина (байты)

Описание

op

1

Тип сообщения

htype

1

Тип адреса аппаратной части

hlen

1

Длина адреса аппаратной части

hops

1

Используемое количество агентов ретрансляции. Клиенты устанавливают значение на 0.

xid

4

ID (уникальный идентификационный номер) транзакции используемой клиентом и серверов во время сессии

secs

2

Прошедшее время (в секундах) с момента запроса клиентом начала процесса

flags

2

Значение флагов

ciaddr

Также интересно:

4

IP-адрес клиента (если имелся ранее).

yiaddr

4

IP-адрес, предложенный сервером клиенту

siaddr

4

IP-адрес сервера

giaddr

4

IP-адрес relay-агента (агента ретрансляции)

chaddr

16

Адрес аппаратной части клиента (в основном MAC).

sname

64

Имя сервера.

file

128

Название загрузочного файла.

options

изменяемая

Дополнительные опции

Знание основ DHCP помогает в устранении различных проблем с сетью. В следующей части статьи мы затронем принципы работы протокола.

Как работает DHCP?

Перед изучением самого процесса, с помощью которого достигается поставленная цель, необходимо понять различные принципы обмена информацией, которые используются в данном процессе.

DHCPDISCOVER

Это сообщение обозначает начало DHCP взаимодействия между клиентом и сервером. Данное сообщение отправляется клиентом (компьютером или устройством), подключенным к сети. В этом сообщении используется 255.255.255.255 как IP-адрес доставки, тогда как исходным адресом является 0.0.0.0

DHCPOFFER

Это сообщение отправляется в ответ на DHCPDISCOVER от сервера DHCP для подключенных клиентов. В этом сообщении содержатся необходимые сетевые настройки.

DHCPREQUEST

Данное сообщение является ответом на DHCPOFFER, и обозначает, что клиент принял отправленные настройки.

DHCPACK

Данное сообщение отправляется на сервер протокола DHCP в ответ на DHCPREQUEST от клиента. Сообщение обозначает конец процесса, начатого с сообщения DHCPDISCOVER. Т.е. DHCPACK - это не что иное, как подтверждение от сервера начала авторизации клиента и принятие параметров конфигурации, полученных в самом начале от сервера.

DHCPNAK

Данное сообщение является противоположностью DHCPACK, описанного выше. Оно отправляется на сервер в случае, если невозможно удовлетворить параметры DHCPREQUEST клиента.

DHCPDECLINE

Сообщение отправляется клиентом на сервер в случае, если IP-адрес, присваиваемый в DHCP уже используется.

DHCPINFORM

Сообщение отправляется серверу в том случае, если клиенту DHCP присвоен статический IP-адрес, а по настройкам конфигурации необходим динамический адрес.

DHCPRELEASE

Сообщение отправляется клиентов в том случае, если он завершает процесс использования сетевого адреса.

Теперь, когда мы познакомились с различными сообщениями в DHCP, можно изучить весь процесс работы, чтобы получить более полное представление. Шаги ниже описываются исходя из того, что все настройки установлены по умолчанию.

Шаг 1.

Когда клиент (компьютер или устройство) загружается или подключается к сети, серверу отправляется сообщение DHCPDISCOVER. Если нет никаких дополнительных данных о конфигурации, то сообщение отправляется с адреса 0.0.0.0 к 255.255.255.255. Если сервер DHCP находится в локальной подсети, то она напрямую получает сообщение, если он находится в другой подсети, то используется агент ретрансляции для передачи запроса к серверу DCHP. Используется протокол передачи UDP через порт 67. Клиент на данном этапе начинает стадию авторизации.

Шаг 2.

В тот момент как сервер получил запрос DHCPDISCOVER, то он отправляет в ответ сообщение DHCPOFFER. Как говорилось ранее, в этом сообщении содержатся все необходимые параметры конфигурации, запрашиваемые клиентом. Например, IP-адрес, необходимый клиенту, а также значение маски подсети и информация о шлюзе. Также сервер сразу заполняет значения MAC-адреса в поле CHADDR. Сообщение отправляется клиенту от адреса 255.255.255.255 напрямую, а если сервер находится в другой подсети, то используются агенты ретрансляции, который отвечает за то, чтобы сообщение было доставлено. В этом случае для передачи применяется протокол UDP через порт 68. На этом этапе клиент начинает подбирать параметры.

Шаг 3.

Клиент формирует сообщение DHCPREQUEST, которое служит ответом на DHCPOFFER от сервера, указав, что он принимает параметры конфигурации, отправленные ему. Если бы было несколько серверов DCHP, то клиент бы получил также несколько сообщений DHCPOFFER, но клиент отвечает только одному серверу, заполняя параметры конфигурации для настройки. Таким образом, он проходит авторизацию с получением IP-адреса от одного конкретного сервера DHCP. Все сообщение от других серверов блокируются. Сообщение DHCPREQUEST по-прежнему будет содержать адрес источника 0.0.0.0, если клиенту все еще нельзя использовать IP-адреса, полученные в сообщении DHCPOFFER. В течение этого этапа клиент получает ответы на свои запросы.

Шаг 4.

Как только сервер получает DHCPREQUEST от клиента, он посылает DHCPACK сообщение о том, что теперь клиент может использовать IP-адрес, назначенный к нему. Клиент окончательно подключается к сети и с настроенными параметрами.

Концепция аренды

В дополнении к остальной необходимой информации о том, как работает DHCP, следует также знать IP-адрес, назначенный в DHCP сервером в аренду клиенту. После истечения срока аренды сервер DHCP может свободно присвоить этот IP-адрес другому компьютеру или устройству, запрашивающему то же самое. Например, сохранение срока аренды 8-10 часов полезно для компьютеров, которые обычно выключают в конце дня. Поэтому аренда должна продлеваться время от времени. После истечения половины срока аренды, DCHP клиент обычно пытается автоматически продлить данный срок. Это делается путем обмена DHCPREQUEST и DHCPACK сообщениями. Благодаря этому начинается стадия обновления данных для клиента.

2. Характеристики силовых полупроводниковых приборов

2.1 Полупроводниковые преобразователи

Что такое DHCP?

DHCP -- Dynamic Host Configuration Protocol -- это протокол динамической настройки узла прикладного уровня по модели OSI. Он разработан ещё в 1993 году, но до сих пор не только не потерял актуальности, но и наоборот -- получил новую версию для работы с протоколом IPv6. Модель работы -- «Клиент-сервер». При этом, у DHCP-сервера есть собственный метод обмена сообщениями между клиентом и сервером. Протокол позволяет выполнить автоматическую настройку протокола IP версии 4, а так же и более новой версии 6, тем самым облегчив процесс настройки сети и исключив вероятность ошибки при ручном вводе данных.

Что делает DHCP-сервер?!

На ДХЦП-сервере системным администратором задаётся определённый диапазон IP-адресов, которые можно выдавать устройствам-клиентам при обращении. При этом дополнительно может настраиваться срок аренды адреса (lease time) в течение которого он закреплён за MAC-адресом компьютера и не может быть занят иным устройством.

У сервера есть три варианта распределения адресов в сети:

1 -- Динамическое. Именно этот вариант работает на 95% серверов. Адрес выдаётся компьютеру на определённый срок (время аренды), по истечению которого АйПи будет считаться свободным и может быть назначен иному компьютеру в сети.

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

3 -- Ручное. В этом случае администратором сервера составляется таблица соответствия IP и MAC-адресов устройств, согласно которой в дальнейшем они и будут получать сетевые параметры. Этот способ практически не используется. Если только в сетях с повышенным уровнем безопасности.

Как работает DHCP сервер

Работа сервера основывается на широковещательных сетевых запросах. Процедура «общения» клиента и сервера выглядить примерно так:

1. Клиент отправляет broadcast-сообщение «Мне нужен IP»

2. Сервер отвечает таким же сообщением «У меня есть адрес xxx.xxx.xxx.xxx. Устроит?»

3. Клиент -- «Да устроит!»

4. Сервер -- «ОК! Адрес xxx.xxx.xxx.xxx зарезервирован за тобой».

Для представленного «общения» используются следующие специальные широковещательные broadcast-запросы.

Вот, для наглядности, схема диалога клиента и сервера ДХЦП:

Диапазон IP-адресов, предназначенных для распределения между клиентами одной сети с помощью протокола DHCP, рассматривается как единый административный блок. Он называется «область действия» -- scope. Если сервер работает с несколькими подсетями, то при настройке службы DHCP, администратор должен создать отдельную область действия для каждой физической подсети.

В идеале, для стабильной работы, для каждого обслуживаемого сегмента сети должно быть как минимум два DHCP-сервера, но для домашнего использования это требование не актуально.

Виды запросов сервера

Схема обмена сообщениями между клиентом и DHCP сервером:

DHCPDISCOVER -- Это сообщение отправляется клиентом при подключении к сети для поиска активного DCHP сервера. При этом в качестве исходного IP используется 0.0.0.0, а в качестве адреса доставки -- 255.255.255.255.

DHCPOFFER -- Ответное сообщение DHCP-сервера на клиентский запрос DHCPDISCOVER, в котором предлагаются определённые сетевые настройки.

DHCPREQUEST -- Broadcast-сообщение от клиента в ответ на DHCPOFFER, сообщающее о том, что он принял настройки.

DHCPACK -- ответное послание клиенту после получения от него DHCPREQUEST, означающее завершение процесса общения. Оно подтверждает о том, что всё согласовано и ПК может работать в сети.

DHCPRELEASE -- Такое широковещательное сообщение отправляется клиентом если он прекращает использования сетевого адреса.

DHCPNAK -- Этот ответ будет отправлен клиенту в случае, если невозможно удовлетворить параметры DHCPREQUEST.

DHCPDECLINE -- Широковещательный ответ серверу в том случае, когда клиент обнаруживает, что присвоенный ему IP-адрес уже используется.

DHCPINFORM -- Сообщение серверу в том случае, если у клиента DHCP прописан статический IP-адрес и он не нуждается в динамическом распределении.

Сообщения протокола DCHP имеют следующие поля:

Поле

Длина (байты)

Описание

op

1

Тип сообщения

htype

1

Тип адреса аппаратной части

hlen

1

Длина адреса аппаратной части

hops

1

Используемое количество агентов ретрансляции. Клиенты устанавливают значение на 0.

xid

4

ID (уникальный идентификационный номер) транзакции используемой клиентом и серверов во время сессии

secs

2

Прошедшее время (в секундах) с момента запроса клиентом начала процесса

flags

2

Значение флагов

ciaddr

4

IP-адрес клиента (если имелся ранее).

yiaddr

4

IP-адрес, предложенный сервером клиенту

siaddr

4

IP-адрес сервера

giaddr

4

IP-адрес relay-агента (агента ретрансляции)

chaddr

16

Адрес аппаратной части клиента (в основном MAC).

sname

64

Имя сервера.

file

128

Название загрузочного файла.

options

изменяемая

Дополнительные опции

Как включить DHCP на сетевом адаптере

В операционной системе Windows 10 DHCP-клиент включен по умолчанию как служба, а на сетевом адаптере необходимо выставить автоматическое получение IP. Для этого нажимаем комбинацию клавиш Win+R чтобы открыть окно «Выполнить» и вводим команду ncpa.cpl.

Нажимаем на кнопку «ОК». Появится окно с сетевыми подключениями Виндовс 10.

На том адаптере, где хотим включить DHCP, кликаем правой кнопкой чтобы появилось контекстное меню. В меню -- выбираем пункт «Свойства».

В следующем окне надо выбрать строчку «IP версии 4(TCP/IPv4)» и нажимаем на кнопку «Свойства» чтобы открыть параметры протокола:

Здесь необходимо поставить галочки на автоматическое получение адресов и нажать на кнопку «ОК».

В операционных системах семейства Linux все настройки прописаны в конфигурационных файлах. Например, в популярной Ubuntu это /etc/network/interfaces. Вот пример конфига, который позволяет включить DHCP на сетевом адаптере eth0:

Здесь:

auto eth0 -- автоматическое включение сетевой карты eth0 при загрузке системы.

iface eth0 inet static -- этой строчкой мы указываем системе, что интерфейс сетевой карты eth0 находится в диапазоне адресов с динамическим получением ip.

Если в системе работает менеджер соединение Network Manager, то можно включить DHCP на сетевом адаптере и в графическом интерфейсе:

DHCP (протокол динамической конфигурации хоста) - это протокол управления сетью, используемый для динамического назначения IP-адреса на любом устройстве или узле в сети, чтобы они могли связываться с использованием IP. DHCP автоматизирует и централизованно управляет этими конфигурациями, а не требует, чтобы сетевые администраторы вручную назначали IP-адреса всем сетевым устройствам. DHCP может быть реализован в небольших локальных сетях, а также в крупных корпоративных сетях.

DHCP назначит новые IP-адреса в каждом местоположении, когда устройства будут перемещены с места на место, что означает, что сетевым администраторам не нужно вручную сначала настраивать каждое устройство с допустимым IP-адресом или перенастраивать устройство с новым IP-адресом, если он перемещается на новое место в сети. Версии DHCP доступны для использования в интернет-протоколе версии 4 (IPv4) и в Internet Protocol версии 6 (IPv6).

Как работает DHCP

DHCP работает на прикладном уровне стека протокола протокола управления передачей / протокола IP (TCP / IP) для динамического назначения IP-адресов DHCP-клиентам и для распределения данных конфигурации TCP / IP клиентам DHCP. Сюда входит информация о маске подсети, IP-адреса шлюза по умолчанию и адреса системы доменных имен (DNS).

DHCP - это протокол клиент-сервер, в котором серверы управляют пулом уникальных IP-адресов, а также информацию о параметрах конфигурации клиента и назначают адреса из этих пулов адресов. Клиенты с поддержкой DHCP отправляют запрос на сервер DHCP всякий раз, когда они подключаются к сети.

Клиенты, настроенные DHCP, передают запрос на сервер DHCP и запрашивают информацию о конфигурации сети для локальной сети, к которой они присоединены. Клиент обычно транслирует запрос для этой информации сразу после загрузки. DHCP-сервер отвечает на запрос клиента, предоставляя информацию о конфигурации IP, ранее указанную сетевым администратором. Это включает в себя определенный IP-адрес, а также период времени, также называемый арендой, для которой распределение действительно. При обновлении задания DHCP-клиент запрашивает одни и те же параметры, но DHCP-сервер может назначить новый IP-адрес на основе политик, установленных администраторами.

DHCP-сервер управляет записью всех IP-адресов, которые он назначает сетевым узлам. Если узел перемещается в сети, сервер идентифицирует его, используя его адрес управления доступом к среде передачи (MAC), что предотвращает случайную настройку нескольких устройств с одним и тем же IP-адресом.

DHCP не является маршрутизируемым протоколом и не является безопасным. DHCP ограничен конкретной локальной сетью (LAN), что означает, что один DHCP-сервер для каждой локальной сети является достаточным или два сервера для использования в случае отказа. Более крупные сети могут иметь глобальную сеть (WAN), содержащую несколько отдельных мест. В зависимости от соединений между этими точками и количеством клиентов в каждом месте можно настроить несколько DHCP-серверов для обработки адресов. Если сетевые администраторы хотят, чтобы DHCP-сервер предоставлял адресацию нескольким подсетям в данной сети, они должны настроить службы ретрансляции DHCP, расположенные на соединительных маршрутизаторах, что запросы DHCP должны пересекаться. Эти агенты ретранслируют сообщения между клиентами DHCP и серверами, расположенными в разных подсетях.

DHCP не имеет встроенного механизма, позволяющего клиентам и серверам аутентифицировать друг друга. Оба уязвимы для обмана (один компьютер притворяется другим) и атаковать, когда клиенты-изгои могут исчерпать пул IP-адресов DHCP-сервера.

Статические и динамические аренды DHCP

При динамическом DHCP клиент не имеет назначенного ему IP-адреса, а вместо этого «арендует» его в течение определенного периода времени. При каждом включении устройства с динамическим IP-адресом он должен связываться с сервером DHCP для аренды другого IP-адреса. Беспроводные устройства - это примеры клиентов, которым назначены динамические IP-адреса при их подключении к сети.

Устройства, назначенные статическим IP-адресам, имеют постоянные IP-адреса и используются для таких устройств, как веб-серверы или коммутаторы.

При динамической настройке DHCP клиенту также может потребоваться выполнить определенные действия, которые приведут к завершению его IP-адреса, а затем снова подключиться к сети с использованием другого IP-адреса. Время аренды DHCP может варьироваться в зависимости от того, как долго пользователю будет необходимо подключение к Интернету в определенном месте. Устройства выпускают свои IP-адреса, когда истекает срок их аренды DHCP, а затем запрашивают обновление с сервера DHCP, если они находятся в сети. DHCP-сервер может назначать новый адрес, а не обновлять старый.

Типичный динамический цикл аренды DHCP выглядит следующим образом:

Клиент получает аренду IP-адреса через процесс распределения запроса с сервера DHCP.

Если клиент уже имеет IP-адрес из существующего лизинга, он должен будет обновить свой IP-адрес при его перезагрузке после его завершения и обратиться к DHCP-серверу, чтобы перераспределить IP-адрес.

Как только аренда активна, клиент, как говорят, связан с арендой и адресом.

По истечении срока аренды клиент свяжется с сервером, который изначально предоставил наименьшее количество обновлений, чтобы он мог продолжать использовать свой IP-адрес.

Если клиент перемещается в другую сеть, его динамический IP-адрес будет прекращен и он запросит новый IP-адрес с DHCP-сервера новой сети.

package net.floodlightcontroller.dhcpserver;

import net.floodlightcontroller.core.*;

import net.floodlightcontroller.core.internal.IOFSwitchService;

import net.floodlightcontroller.core.module.FloodlightModuleContext;

import net.floodlightcontroller.core.module.FloodlightModuleException;

import net.floodlightcontroller.core.module.IFloodlightModule;

import net.floodlightcontroller.core.module.IFloodlightService;

import net.floodlightcontroller.core.types.NodePortTuple;

import net.floodlightcontroller.dhcpserver.web.DHCPServerWebRoutable;

import net.floodlightcontroller.packet.DHCP;

import net.floodlightcontroller.packet.Ethernet;

import net.floodlightcontroller.packet.IPv4;

import net.floodlightcontroller.restserver.IRestApiService;

import net.floodlightcontroller.staticentry.IStaticEntryPusherService;

import net.floodlightcontroller.core.IOFSwitchListener;

import net.floodlightcontroller.topology.ITopologyService;

import net.floodlightcontroller.util.OFMessageUtils;

import org.projectfloodlight.openflow.protocol.*;

import org.projectfloodlight.openflow.types.*;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.util.*;

import java.util.concurrent.ScheduledThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

/**

* SDN DHCP Server

* @author Ryan Izard, rizard@g.clemson.edu, ryan.izard@bigswitch.com

* @edited Qing Wang, qw@g.clemson.edu on 1/3/2018

*

* This module implementing a DHCP DHCPServer. The module can be configured with the REST API.

*

*/

public class DHCPServer implements IOFMessageListener, IOFSwitchListener, IFloodlightModule, IDHCPService {

protected static final Logger log = LoggerFactory.getLogger(DHCPServer.class);

protected IFloodlightProviderService floodlightProviderService;

protected IOFSwitchService switchService;

protected IRestApiService restApiService;

protected ITopologyService topologyService;

protected IStaticEntryPusherService staticEntryPusherService;

private static Map<String, DHCPInstance> dhcpInstanceMap;

private static volatile boolean enableDHCPService = false;

private static volatile boolean enableDHCPDynamicService = false;

private static ScheduledThreadPoolExecutor leasePoliceDispatcher;

private static long DHCP_SERVER_CHECK_EXPIRED_LEASE_PERIOD_SECONDS = 10; // 10 secs as default

@Override

public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {

Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);

OFPort inPort = OFMessageUtils.getInPort((OFPacketIn) msg);

if (!isDHCPEnabled()) return Command.CONTINUE;

if (!DHCPServerUtils.isDHCPPacketIn(eth)) return Command.CONTINUE;

NodePortTuple npt = DHCPServerUtils.getNodePortTuple(sw, inPort);

VlanVid vid = DHCPServerUtils.getVlanVid((OFPacketIn) msg, eth);

if (!getInstance(npt).isPresent() && !getInstance(sw.getId()).isPresent() && !getInstance(vid).isPresent()) {

log.warn("Could not locate DHCP instance for DPID {}, port {} or VLAN {}", new Object[] {sw.getId(), inPort, vid});

return Command.CONTINUE;

}

DHCPInstance instance = null;

if (getInstance(sw.getId()).isPresent()) {

instance = getInstance(sw.getId()).get();

}

else if (getInstance(npt).isPresent()) {

instance = getInstance(npt).get();

}

else {

instance = getInstance(vid).get();

}

synchronized (instance.getDHCPPool()) {

if (!instance.getDHCPPool().isPoolAvailable()) {

log.info("DHCP Pool is full, trying to allocate more space");

return Command.CONTINUE;

}

}

DHCP dhcPayload = DHCPServerUtils.getDHCPayload(eth);

IPv4Address srcAddr = ((IPv4) eth.getPayload()).getSourceAddress();

IPv4Address dstAddr = ((IPv4) eth.getPayload()).getDestinationAddress();

MacAddress srcMac = eth.getSourceMACAddress();

switch (DHCPServerUtils.getOpcodeType(dhcPayload)) {

case REQUEST:

processDhcpRequest(dhcPayload, sw, inPort, instance, srcAddr, dstAddr, srcMac);

return Command.STOP;

default:

break;

}

return Command.CONTINUE;

}

private void processDhcpRequest(DHCP dhcpPayload, IOFSwitch sw, OFPort inPort, DHCPInstance instance,

IPv4Address srcAddr, IPv4Address dstAddr, MacAddress srcMac) {

DHCPMessageHandler handler = new DHCPMessageHandler();

switch (DHCPServerUtils.getMessageType(dhcpPayload)) {

case DISCOVER:

OFPacketOut dhcpOffer = handler.handleDHCPDiscover(sw, inPort, instance, srcAddr, dhcpPayload, enableDHCPDynamicService);

log.info("DHCP DISCOVER message received from switch {} for client interface {}, handled by dhcp instance {} ... ",

new Object[]{sw.getId().toString(), srcMac.toString(), instance.getName()});

sw.write(dhcpOffer);

break;

case REQUEST:

OFPacketOut dhcpReply = handler.handleDHCPRequest(sw, inPort, instance, dstAddr, dhcpPayload);

log.info("DHCP REQUEST message received from switch {} for client interface {}, handled by dhcp instance {} ... ",

new Object[]{sw.getId().toString(), srcMac.toString(), instance.getName()});

sw.write(dhcpReply); // either ACK or NAK

break;

case RELEASE: // clear client IP (e.g. client shut down, etc)

log.debug("DHCP RELEASE message received from switch {}, start handling... ", sw.getId().toString());

handler.handleDHCPRelease(instance, dhcpPayload.getClientHardwareAddress());

break;

case DECLINE: // client found assigned IP invalid

log.debug("DHCP DECLINE message received from switch {}, start handling... ", sw.getId().toString());

handler.handleDHCPDecline(instance, dhcpPayload.getClientHardwareAddress());

break;

case INFORM: // client request some information

log.debug("DHCP INFORM message received from switch {}, start handling... ", sw.getId().toString());

OFPacketOut dhcpAck = handler.handleDHCPInform(sw, inPort, instance, dstAddr, dhcpPayload);

sw.write(dhcpAck);

break;

default:

break;

}

}

@Override

public String getName() {

return "dhcpserver";

}

@Override

public boolean isCallbackOrderingPrereq(OFType type, String name) {

return false;

}

@Override

public boolean isCallbackOrderingPostreq(OFType type, String name) {

return (type.equals(OFType.PACKET_IN) && name.equals("forwarding"));

}

@Override

public Collection<Class<? extends IFloodlightService>> getModuleServices() {

Collection<Class<? extends IFloodlightService>> s =

new HashSet<Class<? extends IFloodlightService>>();

s.add(IDHCPService.class);

return s;

}

@Override

public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {

Map<Class<? extends IFloodlightService>, IFloodlightService> m =

new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();

m.put(IDHCPService.class, this);

return m;

}

@Override

public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {

Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();

l.add(IFloodlightProviderService.class);

l.add(IDHCPService.class);

l.add(IRestApiService.class);

return l;

}

// private DHCPInstance readDHCPConfig(Map<String, String> configOptions, DHCPInstanceBuilder builder) {

// }

@Override

public void init(FloodlightModuleContext context) throws FloodlightModuleException {

this.floodlightProviderService = context.getServiceImpl(IFloodlightProviderService.class);

this.switchService = context.getServiceImpl(IOFSwitchService.class);

this.restApiService = context.getServiceImpl(IRestApiService.class);

this.topologyService = context.getServiceImpl(ITopologyService.class);

this.staticEntryPusherService = context.getServiceImpl(IStaticEntryPusherService.class);

dhcpInstanceMap = new HashMap<>();

// DHCPInstance instance = readDHCPConfig(context.getConfigParams(this), DHCPInstance.createInstance());

// dhcpInstanceMap.put(instance.getName(), instance);

}

@Override

public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {

floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);

switchService.addOFSwitchListener(this);

restApiService.addRestletRoutable(new DHCPServerWebRoutable());

/**

* Thread for DHCP server that periodically check expired DHCP lease

*

* The period of the check for expired lease, in seconds, is specified either in floodlightdefault.properties,

* or through REST API to setup.

*/

leasePoliceDispatcher = new ScheduledThreadPoolExecutor(1);

leasePoliceDispatcher.scheduleAtFixedRate(() -> {

for (DHCPInstance instance : dhcpInstanceMap.values()) {

synchronized (instance.getDHCPPool()) {

instance.getDHCPPool().checkExpiredLeases();

// instance.getDHCPPool().clearExpiredLeases();

}

}

}, 10, DHCP_SERVER_CHECK_EXPIRED_LEASE_PERIOD_SECONDS, TimeUnit.SECONDS);

}

@Override

public void enableDHCP() {

enableDHCPService = true;

}

@Override

public void disableDHCP() {

enableDHCPService = false;

}

@Override

public void enableDHCPDynamic() {

enableDHCPDynamicService = true;

}

@Override

public void disableDHCDynamic() {

enableDHCPDynamicService = false;

}

@Override

public boolean isDHCPDynamicEnabled() {

return enableDHCPDynamicService;

}

@Override

public boolean isDHCPEnabled() {

return enableDHCPService;

}

@Override

public void setCheckExpiredLeasePeriod(long timeSec) {

DHCP_SERVER_CHECK_EXPIRED_LEASE_PERIOD_SECONDS = timeSec;

}

@Override

public Optional<DHCPInstance> getInstance(String name) {

return dhcpInstanceMap.values().stream()

.filter(instance -> instance.getName().contains(name))

.findAny();

}

@Override

public Optional<DHCPInstance> getInstance(IPv4Address ip) {

return dhcpInstanceMap.values().stream()

.filter(dhcpInstance -> dhcpInstance.getDHCPPool().isIPBelongsToPool(ip))

.findAny();

}

@Override

public Optional<DHCPInstance> getInstance(NodePortTuple npt) {

return dhcpInstanceMap.values().stream()

.filter(instance -> instance.getNptMembers().contains(npt))

.findAny();

}

@Override

public Optional<DHCPInstance> getInstance(DatapathId dpid) {

return dhcpInstanceMap.values().stream()

.filter(instance -> instance.getSwitchMembers().contains(dpid))

.findAny();

}

@Override

public Optional<DHCPInstance> getInstance(VlanVid vid) {

return dhcpInstanceMap.values().stream()

.filter(instance -> instance.getVlanMembers().contains(vid))

.findAny();

}

@Override

public Collection<DHCPInstance> getInstances() {

return dhcpInstanceMap.values();

}

@Override

public void addInstance(DHCPInstance instance) {

dhcpInstanceMap.put(instance.getName(), instance);

}

@Override

public boolean deleteInstance(String name) {

if (getInstance(name).isPresent()) {

dhcpInstanceMap.remove(name);

return true;

}

else {

return false;

}

}

@Override

public void deleteAllInstances() {

dhcpInstanceMap.clear();

}

@Override

public DHCPInstance updateInstance(String name, DHCPInstance newInstance) {

DHCPInstance old = dhcpInstanceMap.get(name);

newInstance = old.getBuilder().setSubnetMask(newInstance.getSubnetMask())

.setStartIP(newInstance.getStartIPAddress())

.setEndIP(newInstance.getEndIPAddress())

.setBroadcastIP(newInstance.getBroadcastIP())

.setRouterIP(newInstance.getRouterIP())

.setDomainName(newInstance.getDomainName())

.setLeaseTimeSec(newInstance.getLeaseTimeSec())

.setIPforwarding(newInstance.getIpforwarding())

.setServerMac(newInstance.getServerMac())

.setServerID(newInstance.getServerID())

.build();

return newInstance;

}

@Override

public void switchAdded(DatapathId switchId) { }

@Override

public void switchRemoved(DatapathId switchId) {

dhcpInstanceMap.values().stream()

.forEach(instance -> instance.removeSwitchFromInstance(switchId));

log.info("Handle switchRemoved. Switch {} removed from dhcp instance", switchId.toString());

}

@Override

public void switchActivated(DatapathId switchId) { }

@Override

public void switchPortChanged(DatapathId switchId, OFPortDesc port, PortChangeType type) { }

@Override

public void switchChanged(DatapathId switchId) { }

@Override

public void switchDeactivated(DatapathId switchId) { }

}

У меня есть следующий код

* DHCPServer.java

* DHCPClient.java

* DHCPMessage.java

* DHCPOptions.java

i hav выполнил мою команду promt с помощью javac, у меня нет ошибки, я запускаю код bt, я не знаю, как код работает более конкретно Я не знаю, как запустить его

DHCPServer.java

import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;import java.util.Arrays;

publicclass DHCPServer {

privatestaticfinalint MAX_BUFFER_SIZE = 1024; // 1024 bytes

privateint listenPort = 67;//1337;

public DHCPServer(int servePort) {

listenPort = servePort;

new DHCPServer();

}

public DHCPServer() {

//System.out.println("Opening UDP Socket On Port: " + listenPort);

DatagramSocket socket = null;

try {

socket = new DatagramSocket(listenPort); // ipaddress? throws socket exception

byte[] payload = newbyte[MAX_BUFFER_SIZE];

int length = 6;

DatagramPacket p = new DatagramPacket(payload, length);

//System.out.println("Success! Now listening on port " + listenPort + "...");

System.out.println("Listening on port " + listenPort + "...");

//server is always listening

boolean listening = true;

while (listening) {

socket.receive(p); //throws i/o exception

System.out.println("Connection established from " + p.getAddress());

System.out.println("Data Received: " + Arrays.toString(p.getData()));

}

} catch (SocketException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

/**

* @param args

*/

publicstaticvoid main(String[] args) {

DHCPServer server;

if (args.length >= 1) {

server = new DHCPServer(Integer.parseInt(args[0]));

} else {

server = new DHCPServer();

}

}

}

DHCPClient.java

Скрыть развернуть код копирования

import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.NetworkInterface;import java.net.SocketException;import java.net.UnknownHostException;import java.util.Arrays;

publicclass DHCPClient {

privatestaticfinalint MAX_BUFFER_SIZE = 1024; // 1024 bytes

privateint listenPort = 68;//1338;

privateString serverIP = "127.0.0.1";

privateint serverPort = 67;//1337;

/*

* public DHCPClient(int servePort) { listenPort = servePort; new

* DHCPServer(); }

*/

public DHCPClient() {

System.out.println("Connecting to DHCPServer at " + serverIP + " on port " + serverPort + "...");

DatagramSocket socket = null;

try {

socket = new DatagramSocket(listenPort); // ipaddress? throws socket exception

byte[] payload = newbyte[MAX_BUFFER_SIZE];

int length = 6;

payload[0] = 'h';

payload[1] = '3';

payload[2] = 'l';

payload[3] = 'l';

payload[4] = 'o';

payload[5] = '!';

DatagramPacket p = new DatagramPacket(payload, length, InetAddress.getByName(serverIP), serverPort);

socket.send(p); //throws i/o exception

socket.send(p);

System.out.println("Connection Established Successfully!");

System.out.println("Sending data: " + Arrays.toString(p.getData()));

} catch (SocketException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

/**

* @param args

*/

publicstaticvoid main(String[] args) {

DHCPClient client;

/*

* if (args.length >= 1) { server = new

* DHCPClient(Integer.parseInt(args[0])); } else {

*/

client = new DHCPClient();

//DHCPMessage msgTest = new DHCPMessage();

printMacAddress();

// }

}

publicstaticbyte[] getMacAddress() {

byte[] mac = null;

try {

InetAddress address = InetAddress.getLocalHost();

/*

* Get NetworkInterface for the current host and then read the

* hardware address.

*/

NetworkInterface ni = NetworkInterface.getByInetAddress(address);

mac = ni.getHardwareAddress();

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (SocketException e) {

e.printStackTrace();

}

assert(mac != null);

return mac;

}

publicstaticvoid printMacAddress() {

try {

InetAddress address = InetAddress.getLocalHost();

/*

* Get NetworkInterface for the current host and then read the

* hardware address.

*/

NetworkInterface ni = NetworkInterface.getByInetAddress(address);

byte[] mac = ni.getHardwareAddress();

/*

* Extract each array of mac address and convert it to hexa with the

* . * following format 08-00-27-DC-4A-9E.

*/

for (int i = 0; i < mac.length; i++) {

System.out.format("%02X%s", mac[i], (i < mac.length - 1) ? "-"

: "");

}

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (SocketException e) {

e.printStackTrace();

}

}

}

DHCPMessage.java

Скрыть развернуть код копирования

import java.net.Inet4Address;import java.net.InetAddress;

/**

* This class represents a DHCP application level message packet

*/

/**

* @author Laivz

*

*/publicclass DHCPMessage {

privatestaticfinalint BOOTREQUEST = 1;

privatestaticfinalint BOOTREPLY = 2;

privatestaticfinalint DHCPREQUEST = 1;

privatestaticfinalint DHCPREPLY = 2;

privatestaticfinalint ETHERNET10MB = 1;

//Operation Code:

//Specifies the general type of message

privatebyte op;

//Hardware Type:

//Specifies the type of hardware used for the local network

privatebyte hType;

//Hardware Address Length:

//Specifies how long hardware addresses are in this message.

privatebyte hLen;

//Hops:

privatebyte hops;

//Transaction Identifier: (32-bit)

//Identification field generated by client

//private byte[] xid = new byte[3];

privateint xid;

//Seconds: (16-bit)

//Number of seconds elapsed since a client began an attempt to acquire or renew a lease.

//private byte[] secs = new byte[1];

privateshort secs;

//Flags: (16-bit)

//1bit broadcast flag (0-1)

//15 bit reserverd

//private byte[] flags = new byte[1];

privateshort flags;

//Client IP Address: (32-bit)

privatebyte[] cIAddr;

//private InetAddress cIAddr = new Inet4Address();

//"Your" IP Address: (32-bit)

privatebyte[] yIAddr;

//Server IP Address: (32-bit)

privatebyte[] sIAddr;

//Gateway IP Address: (32-bit)

privatebyte[] gIAddr;

//Client Hardware Address: (128-bit : 16 bytes)

privatebyte[] cHAddr;

//Server Name: (512-bit : 64 bytes)

privatebyte[] sName;

//Boot Filename: (1024-bit : 128 bytes)

privatebyte[] file;

//Options: (variable)

private DHCPOptions options;

public DHCPMessage() {

cIAddr = newbyte[4];

yIAddr = newbyte[4];

sIAddr = newbyte[4];

gIAddr = newbyte[4];

cHAddr = newbyte[16];

sName = newbyte[64];

file = newbyte[128];

options = new DHCPOptions();

this.printMessage();

}

publicbyte[] discoverMsg(byte[] cMacAddress) {

op = DHCPREQUEST;

hType = ETHERNET10MB; // (0x1) 10Mb Ethernet

hLen = 6; // (0x6)

hops = 0; // (0x0)

xid = 556223005; // (0x21274A1D)

secs = 0; // (0x0)

flags = 0; // (0x0)

// DHCP: 0............... = No Broadcast

cIAddr = newbyte[] { 0, 0, 0, 0 }; // 0.0.0.0

yIAddr = newbyte[] { 0, 0, 0, 0 }; // 0.0.0.0

sIAddr = newbyte[] { 0, 0, 0, 0 }; // 0.0.0.0

gIAddr = newbyte[] { 0, 0, 0, 0 }; // 0.0.0.0

cHAddr = cMacAddress; // 08002B2ED85E

sName = newbyte[sName.length]; // <Blank>

file = newbyte[file.length]; // <Blank>

// DHCP: Magic Cookie = [OK]

// DHCP: Option Field (options)

// DHCP: DHCP Message Type = DHCP Discover

// DHCP: Client-identifier = (Type: 1) 08 00 2b 2e d8 5e

// DHCP: Host Name = JUMBO-WS

// DHCP: Parameter Request List = (Length: 7) 01 0f 03 2c 2e 2f 06

// DHCP: End of this option field

returnthis.externalize();

}

/**

* Converts a DHCPMessage object to a byte array.

* @return a byte array with information from DHCPMessage object.

*/

publicbyte[] externalize() {

int staticSize = 236;

byte[] options = this.options.externalize();

int size = staticSize + options.length;

byte[] msg = newbyte[size];

//add each field to the msg array

//single bytes

msg[0] = this.op;

msg[1] = this.hType;

msg[2] = this.hLen;

msg[3] = this.hops;

//add multibytes

for (int i=0; i <4; i++) msg[4+i] = inttobytes(xid)[i];

for (int i=0; i <2; i++) msg[8+i] = shorttobytes(secs)[i];

for (int i=0; i <2; i++) msg[10+i] = shorttobytes(flags)[i];

for (int i=0; i <4; i++) msg[12+i] = cIAddr[i];

for (int i=0; i <4; i++) msg[16+i] = yIAddr[i];

for (int i=0; i <4; i++) msg[20+i] = sIAddr[i];

for (int i=0; i <4; i++) msg[24+i] = gIAddr[i];

for (int i=0; i <16; i++) msg[28+i] = cHAddr[i];

for (int i=0; i <64; i++) msg[44+i] = sName[i];

for (int i=0; i <128; i++) msg[108+i] = file[i];

//add options

for (int i=0; i < options.length; i++) msg[staticSize+i] = options[i];

return msg;

}

publicbyte getOp() {

return op;

}

publicvoid setOp(byte op) {

this.op = op;

}

publicbyte getHType() {

return hType;

}

publicvoid setHType(byte type) {

hType = type;

}

publicbyte getHLen() {

return hLen;

}

publicvoid setHLen(byte len) {

hLen = len;

}

publicbyte getHops() {

return hops;

}

publicvoid setHops(byte hops) {

this.hops = hops;

}

publicint getXid() {

return xid;

}

publicvoid setXid(int xid) {

this.xid = xid;

}

publicshort getSecs() {

return secs;

}

publicvoid setSecs(short secs) {

this.secs = secs;

}

publicshort getFlags() {

return flags;

}

publicvoid setFlags(short flags) {

this.flags = flags;

}

publicbyte[] getCIAddr() {

return cIAddr;

}

publicvoid setCIAddr(byte[] addr) {

cIAddr = addr;

}

publicbyte[] getYIAddr() {

return yIAddr;

}

publicvoid setYIAddr(byte[] addr) {

yIAddr = addr;

}

publicbyte[] getSIAddr() {

return sIAddr;

}

publicvoid setSIAddr(byte[] addr) {

sIAddr = addr;

}

publicbyte[] getGIAddr() {

return gIAddr;

}

publicvoid setGIAddr(byte[] addr) {

gIAddr = addr;

}

publicbyte[] getCHAddr() {

return cHAddr;

}

publicvoid setCHAddr(byte[] addr) {

cHAddr = addr;

}

publicbyte[] getSName() {

return sName;

}

publicvoid setSName(byte[] name) {

sName = name;

}

publicbyte[] getFile() {

return file;

}

publicvoid setFile(byte[] file) {

this.file = file;

}

publicbyte[] getOptions() {

return options.externalize();

}

//no set options yet...

/*public void setOptions(byte[] options) {

this.options = options;

}*/

publicvoid printMessage() {

System.out.println(this.toString());

}

@Override

publicString toString() {

String msg = newString();

msg += "Operation Code: " + this.op + "\n";

msg += "Hardware Type: " + this.hType + "\n";

msg += "Hardware Length: " + this.hLen + "\n";

msg += "Hops: " + this.hops + "\n";

msg += Integer.toString(xid) + "\n";

msg += Short.toString(secs) + "\n";

msg += Short.toString(flags) + "\n";

msg += cIAddr.toString() + "\n";

msg += yIAddr.toString() + "\n";

msg += sIAddr.toString() + "\n";

msg += gIAddr.toString() + "\n";

msg += cHAddr.toString() + "\n";

msg += sName.toString() + "\n";

msg += file.toString() + "\n";

msg += options.toString() + "\n";

//add options

assert(file != null);

assert (options != null);

//msg += options.toString();

//return super.toString();

return msg;

}

privatebyte[] inttobytes(int i){

byte[] dword = newbyte[4];

dword[0] = (byte) ((i >>24) & 0x000000FF);

dword[1] = (byte) ((i >>16) & 0x000000FF);

dword[2] = (byte) ((i >>8) & 0x000000FF);

dword[3] = (byte) (i & 0x00FF);

return dword;

}

privatebyte[] shorttobytes(short i){

byte[] b = newbyte[2];

b[0] = (byte) ((i >>8) & 0x000000FF);

b[1] = (byte) (i & 0x00FF);

return b;

}

}

DHCPOptions.java

Скрыть развернуть код копирования

import java.util.Hashtable;import java.util.LinkedList;

/**

* This class represents a hash table of options for a DHCP message.

* Its purpose is to ease option handling such as add, remove, or change.

* @author Laivz

*

*/publicclass DHCPOptions {

//DHCP Message Types

publicstaticfinalint DHCPDISCOVER = 1;

publicstaticfinalint DHCPOFFER = 2;

publicstaticfinalint DHCPREQUEST = 3;

publicstaticfinalint DHCPDECLINE = 4;

publicstaticfinalint DHCPACK = 5;

publicstaticfinalint DHCPNAK = 6;

publicstaticfinalint DHCPRELEASE = 7;

//DHCP Option Identifiers

//private LinkedList<byte[]> options = new LinkedList<byte[]>();

private Hashtable<Integer,byte[]> options;

public DHCPOptions() {

options = new Hashtable<Integer, byte[]>();

}

publicbyte[] getOption(int optionID) {

return options.get(optionID);

}

publicvoid setOption(int optionID, byte[] option) {

options.put(optionID, option);

}

publicbyte[] getOptionData(int optionID) {

byte[] option = options.get(optionID);

byte[] optionData = newbyte[option.length-2];

for (int i=0; i < optionData.length; i++) optionData[i] = option[2+i];

return optionData;

}

publicvoid setOptionData(int optionID, byte[] optionData) {

byte[] option = newbyte[2+optionData.length];

option[0] = (byte) optionID;

option[1] = (byte) optionData.length;

for (int i=0; i < optionData.length; i++) option[2+i] = optionData[i];

options.put(optionID, option);

}

publicvoid printOption (int optionID) {

String output = newString("");

if (options.get(optionID) != null) {

byte[] option = options.get(optionID);

for (int i=0; i < option.length; i++) {

output += option[i] +

(i == option.length-1 ? "" : ",");

}

} else {

output = "<Empty>";

}

System.out.println(output);

}

publicvoid printOptions () {

for (byte[] option : options.values()) {

printOption(option[0]);

}

}

publicstaticvoid main (String[] args) {

DHCPOptions test = new DHCPOptions();

//test.printOptions();

}

publicbyte[] externalize() {

//get size

int totalBytes = 0;

for (byte[] option : this.options.values()) {

totalBytes += option.length;

}

byte[] options = newbyte[totalBytes];

//copy bytes

int bytes = 0;

for (byte[] option : this.options.values()) {

for (int i=0; i < option.length; i++) {

options[bytes+i] = option[i];

}

bytes += option.length;

}

return options;

}

}

package net.floodlightcontroller.dhcpserver; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.projectfloodlight.openflow.protocol.OFMessage; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFPacketOut; import org.projectfloodlight.openflow.protocol.OFType; import org.projectfloodlight.openflow.protocol.action.OFAction; import org.projectfloodlight.openflow.types.EthType; import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IpProtocol; import org.projectfloodlight.openflow.types.MacAddress; import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.OFVlanVidMatch; import org.projectfloodlight.openflow.types.VlanVid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.core.types.NodePortTuple; import net.floodlightcontroller.dhcpserver.DHCPInstance.DHCPInstanceBuilder; import net.floodlightcontroller.packet.DHCP.DHCPOptionCode; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.packet.UDP; import net.floodlightcontroller.packet.DHCP; import net.floodlightcontroller.packet.DHCPOption; import net.floodlightcontroller.util.OFMessageUtils;

public class DHCPServer implements IOFMessageListener, IFloodlightModule, IDHCPService { protected static final Logger log = LoggerFactory.getLogger(DHCPServer.class); protected static IFloodlightProviderService floodlightProvider; protected static IOFSwitchService switchService; private static Map<String, DHCPInstance> instances; private static volatile boolean enabled = false;

public static byte[] DHCP_MSG_TYPE_DISCOVER = intToBytesSizeOne(1); public static byte[] DHCP_MSG_TYPE_OFFER = intToBytesSizeOne(2);

public static byte[] DHCP_MSG_TYPE_REQUEST = intToBytesSizeOne(3); public static byte[] DHCP_MSG_TYPE_DECLINE = intToBytesSizeOne(4); public static byte[] DHCP_MSG_TYPE_ACK = intToBytesSizeOne(5);

public static byte[] DHCP_MSG_TYPE_NACK = intToBytesSizeOne(6);

public static byte[] DHCP_MSG_TYPE_RELEASE = intToBytesSizeOne(7); public static byte[] DHCP_MSG_TYPE_INFORM = intToBytesSizeOne(8);

public static byte DHCP_REQ_PARAM_OPTION_CODE_SN = intToBytes(1)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_ROUTER = intToBytes(3)[0];

public static byte DHCP_REQ_PARAM_OPTION_CODE_DNS = intToBytes(6)[0];

public static byte DHCP_REQ_PARAM_OPTION_CODE_DN = intToBytes(15)[0];

public static byte DHCP_REQ_PARAM_OPTION_CODE_IP_FORWARDING = intToBytes(19)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_BROADCAST_IP = intToBytes(28)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_NTP_IP = intToBytes(42)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_NET_BIOS_NAME_IP = intToBytes(44)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_NET_BIOS_DDS_IP = intToBytes(45)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_NET_BIOS_NODE_TYPE = intToBytes(46)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_NET_BIOS_SCOPE_ID = intToBytes(47)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_REQUESTED_IP = intToBytes(50)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME = intToBytes(51)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_MSG_TYPE = intToBytes(53)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER = intToBytes(54)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_REQUESTED_PARAMTERS = intToBytes(55)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME = intToBytes(58)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME = intToBytes(59)[0]; public static byte DHCP_REQ_PARAM_OPTION_CODE_END = intToBytes(255)[0]; // Used for composing DHCP REPLY messages public static final MacAddress BROADCAST_MAC = MacAddress.BROADCAST; public static final IPv4Address BROADCAST_IP = IPv4Address.NO_MASK; /* no_mask is all 1's */ public static final IPv4Address UNASSIGNED_IP = IPv4Address.FULL_MASK; /* full_mask is all 0's */ @Override public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); l.add(IFloodlightProviderService.class); return l; } @Override public void init(FloodlightModuleContext context) throws FloodlightModuleException { floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); switchService = context.getServiceImpl(IOFSwitchService.class); instances = new HashMap<String, DHCPInstance>(); } @Override public void startUp(FloodlightModuleContext context) { floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); // Read our config options for the DHCP DHCPServer Map<String, String> configOptions = context.getConfigParams(this); DHCPInstanceBuilder instanceBuilder = DHCPInstance.createBuilder(); try { instanceBuilder.setSubnetMask(IPv4Address.of(configOptions.get("subnet-mask"))) .setStartIp(IPv4Address.of(configOptions.get("lower-ip-range"))) .setStopIp(IPv4Address.of(configOptions.get("upper-ip-range"))) .setBroadcastIp(IPv4Address.of(configOptions.get("broadcast-address"))) .setRouterIp(IPv4Address.of(configOptions.get("router"))) .setDomainName(configOptions.get("domain-name")) .setLeaseTimeSec(Integer.parseInt(configOptions.get("default-lease-time"))) .setIpForwarding(Boolean.parseBoolean(configOptions.get("ip-forwarding"))) .setServer(MacAddress.of(configOptions.get("controller-mac")), IPv4Address.of(configOptions.get("controller-ip"))); DHCP_SERVER_LEASE_POLICE_PATROL_PERIOD_SECONDS = Long.parseLong(configOptions.get("lease-gc-period")); // NetBios and other options can be added to this function here as needed in the future } catch(IllegalArgumentException ex) { log.error("Incorrect DHCP Server configuration options", ex); throw ex; } catch(NullPointerException ex) { log.error("Incorrect DHCP Server configuration options", ex); throw ex; } // Any addresses that need to be set as static/fixed can be permanently added to the pool with a set MAC String staticAddresses = configOptions.get("reserved-static-addresses"); if (staticAddresses != null) { String[] macIpCouples = staticAddresses.split("\\s*;\\s*"); int i; String[] macIpSplit; int ipPos, macPos; for (i = 0; i < macIpCouples.length; i++) { macIpSplit = macIpCouples[i].split("\\s*,\\s*"); // Determine which element is the MAC and which is the IP // i.e. which order have they been typed in in the config file? if (macIpSplit[0].length() > macIpSplit[1].length()) { macPos = 0; ipPos = 1; } else { macPos = 1; ipPos = 0; } instanceBuilder.addReservedStaticAddress(MacAddress.of(macIpSplit[macPos]), IPv4Address.of(macIpSplit[ipPos])); log.info("Configured fixed address of {} for device {}", IPv4Address.of(macIpSplit[ipPos]).toString(), MacAddress.of(macIpSplit[macPos]).toString()); } } /* * Separate the servers in the comma-delimited list, * otherwise the client will get incorrect option information */ String dnses = configOptions.get("domain-name-servers"); if (dnses != null) { List<IPv4Address> dnsIps = new ArrayList<IPv4Address>(); for (String dnsIp : dnses.split("\\s*,\\s*")) { dnsIps.add(IPv4Address.of(dnsIp)); } instanceBuilder.setDnsIps(dnsIps); } String ntps = configOptions.get("ntp-servers"); if (ntps != null) { List<IPv4Address> ntpIps = new ArrayList<IPv4Address>(); for (String ntpIp : ntps.split("\\s*,\\s*")) { ntpIps.add(IPv4Address.of(ntpIp)); } instanceBuilder.setNtpIps(ntpIps); } DHCPInstance instance = instanceBuilder.build(); instances.put(instance.getName(), instance); // Monitor bindings for expired leases and clean them up leasePoliceDispatcher = new ScheduledThreadPoolExecutor(1); leasePolicePatrol = new DHCPLeasePolice(); leasePoliceDispatcher.scheduleAtFixedRate(leasePolicePatrol, 10, DHCP_SERVER_LEASE_POLICE_PATROL_PERIOD_SECONDS, TimeUnit.SECONDS); String enable = configOptions.get("enable"); if (enable != null && !enable.isEmpty() && (enable.toLowerCase().contains("true") || enable.toLowerCase().contains("yes") || enable.toLowerCase().contains("yep") ) ) { enable(); } else { disable(); } } @Override public Collection<Class<? extends IFloodlightService>> getModuleServices() { Collection<Class<? extends IFloodlightService>> s = new HashSet<Class<? extends IFloodlightService>>(); s.add(IDHCPService.class); return s; } @Override public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); m.put(IDHCPService.class, this); return m; } @Override public String getName() { return "dhcpserver"; } @Override public boolean isCallbackOrderingPrereq(OFType type, String name) { return false; } @Override public boolean isCallbackOrderingPostreq(OFType type, String name) { // We will rely on forwarding to forward out any DHCP packets that are not // destined for our DHCP server. This is to allow an environment where // multiple DHCP servers operate cooperatively if (type == OFType.PACKET_IN && name.equals("forwarding")) { return true; } else { return false; } } public static byte[] intToBytes(int integer) { byte[] bytes = new byte[4]; bytes[3] = (byte) (integer >> 24); bytes[2] = (byte) (integer >> 16); bytes[1] = (byte) (integer >> 8); bytes[0] = (byte) (integer); return bytes; } public static byte[] intToBytesSizeOne(int integer) { byte[] bytes = new byte[1]; bytes[0] = (byte) (integer); return bytes; } public void sendDHCPOffer(DHCPInstance inst, IOFSwitch sw, OFPort inPort, MacAddress chaddr, IPv4Address dstIPAddr, IPv4Address yiaddr, IPv4Address giaddr, int xid, ArrayList<Byte> requestOrder) { // Compose DHCP OFFER /** (2) DHCP Offer * -- UDP src port = 67 * -- UDP dst port = 68 * -- IP src addr = DHCP DHCPServer's IP * -- IP dst addr = 255.255.255.255 * -- Opcode = 0x02 * -- XID = transactionX * -- ciaddr = blank * -- yiaddr = offer IP * -- siaddr = DHCP DHCPServer IP * -- giaddr = blank * -- chaddr = Client's MAC * -- Options: * -- Option 53 = DHCP Offer * -- Option 1 = SN Mask IP * -- Option 3 = Router IP * -- Option 51 = Lease time (s) * -- Option 54 = DHCP DHCPServer IP * -- Option 6 = DNS servers **/ OFPacketOut.Builder DHCPOfferPacket = sw.getOFFactory().buildPacketOut(); DHCPOfferPacket.setBufferId(OFBufferId.NO_BUFFER); Ethernet ethDHCPOffer = new Ethernet(); ethDHCPOffer.setSourceMACAddress(inst.getServerMac()); ethDHCPOffer.setDestinationMACAddress(chaddr); ethDHCPOffer.setEtherType(EthType.IPv4); IPv4 ipv4DHCPOffer = new IPv4(); if (dstIPAddr.equals(IPv4Address.NONE)) { ipv4DHCPOffer.setDestinationAddress(BROADCAST_IP); } else { // Client has IP and dhcpc must have crashed ipv4DHCPOffer.setDestinationAddress(dstIPAddr); } ipv4DHCPOffer.setSourceAddress(inst.getServerIp()); ipv4DHCPOffer.setProtocol(IpProtocol.UDP); ipv4DHCPOffer.setTtl((byte) 64); UDP udpDHCPOffer = new UDP(); udpDHCPOffer.setDestinationPort(UDP.DHCP_CLIENT_PORT); udpDHCPOffer.setSourcePort(UDP.DHCP_SERVER_PORT); DHCP dhcpDHCPOffer = new DHCP(); dhcpDHCPOffer.setOpCode(DHCP_OPCODE_REPLY); dhcpDHCPOffer.setHardwareType((byte) 1); dhcpDHCPOffer.setHardwareAddressLength((byte) 6); dhcpDHCPOffer.setHops((byte) 0); dhcpDHCPOffer.setTransactionId(xid); dhcpDHCPOffer.setSeconds((short) 0); dhcpDHCPOffer.setFlags((short) 0); dhcpDHCPOffer.setClientIPAddress(UNASSIGNED_IP); dhcpDHCPOffer.setYourIPAddress(yiaddr); dhcpDHCPOffer.setServerIPAddress(inst.getServerIp()); dhcpDHCPOffer.setGatewayIPAddress(giaddr); dhcpDHCPOffer.setClientHardwareAddress(chaddr); List<DHCPOption> dhcpOfferOptions = new ArrayList<DHCPOption>(); DHCPOption newOption; newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_MSG_TYPE); newOption.setData(DHCP_MSG_TYPE_OFFER); newOption.setLength((byte) 1); dhcpOfferOptions.add(newOption); for (Byte specificRequest : requestOrder) {if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_SN) {newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_SN); newOption.setData(inst.getSubnetMask().getBytes()); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_ROUTER) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_ROUTER); newOption.setData(inst.getRouterIp().getBytes()); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_DN) {newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_DN); newOption.setData(inst.getDomainName().getBytes()); newOption.setLength((byte) inst.getDomainName().getBytes().length); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_DNS) { if (!inst.getDnsIps().isEmpty()) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_DNS); ByteBuffer bb = ByteBuffer.allocate(inst.getDnsIps().size() * 4 /* sizeof(IPv4Address) */); /* exact size */ for (IPv4Address ip : inst.getDnsIps()) { bb.put(ip.getBytes()); } bb.flip(); newOption.setData(bb.array()); //TODO verify this newOption.setLength((byte) bb.array().length); dhcpOfferOptions.add(newOption); } else { log.warn("Client asked for DNS servers, but we didn't have any for instance {}", inst.getName()); } } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_BROADCAST_IP) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_BROADCAST_IP); newOption.setData(inst.getBroadcastIp().getBytes()); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER); newOption.setData(inst.getServerIp().getBytes()); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME); newOption.setData(intToBytes(inst.getLeaseTimeSec())); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_NTP_IP) { if (!inst.getNtpIps().isEmpty()) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_NTP_IP); ByteBuffer bb = ByteBuffer.allocate(inst.getNtpIps().size() * 4); /* exact size */ for (IPv4Address ip : inst.getNtpIps()) { bb.put(ip.getBytes()); } bb.flip(); newOption.setData(bb.array()); //TODO verify this newOption.setLength((byte) bb.array().length); dhcpOfferOptions.add(newOption); } else { log.warn("Client asked for NTP servers, but we didn't have any for instance {}", inst.getName()); } } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME); newOption.setData(intToBytes(inst.getRebindTimeSec())); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME); newOption.setData(intToBytes(inst.getRenewalTimeSec())); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_IP_FORWARDING) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_IP_FORWARDING); newOption.setData(intToBytesSizeOne(inst.getIpForwarding() ? 1 : 0)); newOption.setLength((byte) 1); dhcpOfferOptions.add(newOption); } else { //log.debug("Setting specific request for OFFER failed"); } } newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_END); newOption.setLength((byte) 0); dhcpOfferOptions.add(newOption); dhcpDHCPOffer.setOptions(dhcpOfferOptions); ethDHCPOffer.setPayload(ipv4DHCPOffer.setPayload(udpDHCPOffer.setPayload(dhcpDHCPOffer))); DHCPOfferPacket.setInPort(OFPort.ANY); List<OFAction> actions = new ArrayList<OFAction>(1); actions.add(sw.getOFFactory().actions().output(inPort, 0xffFFffFF)); DHCPOfferPacket.setActions(actions); DHCPOfferPacket.setData(ethDHCPOffer.serialize()); log.debug("Sending DHCP OFFER"); sw.write(DHCPOfferPacket.build()); } public void sendDHCPAck(DHCPInstance inst, IOFSwitch sw, OFPort inPort, MacAddress chaddr, IPv4Address dstIPAddr, IPv4Address yiaddr, IPv4Address giaddr, int xid, ArrayList<Byte> requestOrder) { /** (4) DHCP ACK * -- UDP src port = 67 * -- UDP dst port = 68 * -- IP src addr = DHCP DHCPServer's IP * -- IP dst addr = 255.255.255.255 * -- Opcode = 0x02 * -- XID = transactionX * -- ciaddr = blank * -- yiaddr = offer IP * -- siaddr = DHCP DHCPServer IP * -- giaddr = blank * -- chaddr = Client's MAC * -- Options: * -- Option 53 = DHCP ACK * -- Option 1 = SN Mask IP * -- Option 3 = Router IP * -- Option 51 = Lease time (s) * -- Option 54 = DHCP DHCPServer IP * -- Option 6 = DNS servers **/ OFPacketOut.Builder DHCPACKPacket = sw.getOFFactory().buildPacketOut(); DHCPACKPacket.setBufferId(OFBufferId.NO_BUFFER); Ethernet ethDHCPAck = new Ethernet(); ethDHCPAck.setSourceMACAddress(inst.getServerMac()); ethDHCPAck.setDestinationMACAddress(chaddr); ethDHCPAck.setEtherType(EthType.IPv4); IPv4 ipv4DHCPAck = new IPv4(); if (dstIPAddr.equals(IPv4Address.NONE)) { ipv4DHCPAck.setDestinationAddress(BROADCAST_IP); } else { // Client has IP and dhclient must have crashed ipv4DHCPAck.setDestinationAddress(dstIPAddr); } ipv4DHCPAck.setSourceAddress(inst.getServerIp()); ipv4DHCPAck.setProtocol(IpProtocol.UDP); ipv4DHCPAck.setTtl((byte) 64); UDP udpDHCPAck = new UDP(); udpDHCPAck.setDestinationPort(UDP.DHCP_CLIENT_PORT); udpDHCPAck.setSourcePort(UDP.DHCP_SERVER_PORT); DHCP dhcpDHCPAck = new DHCP(); dhcpDHCPAck.setOpCode(DHCP_OPCODE_REPLY); dhcpDHCPAck.setHardwareType((byte) 1); dhcpDHCPAck.setHardwareAddressLength((byte) 6); dhcpDHCPAck.setHops((byte) 0); dhcpDHCPAck.setTransactionId(xid); dhcpDHCPAck.setSeconds((short) 0); dhcpDHCPAck.setFlags((short) 0); dhcpDHCPAck.setClientIPAddress(UNASSIGNED_IP); dhcpDHCPAck.setYourIPAddress(yiaddr); dhcpDHCPAck.setServerIPAddress(inst.getServerIp()); dhcpDHCPAck.setGatewayIPAddress(giaddr); dhcpDHCPAck.setClientHardwareAddress(chaddr); List<DHCPOption> dhcpAckOptions = new ArrayList<DHCPOption>(); DHCPOption newOption; newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_MSG_TYPE); newOption.setData(DHCP_MSG_TYPE_ACK); newOption.setLength((byte) 1); dhcpAckOptions.add(newOption); for (Byte specificRequest : requestOrder) {if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_SN) {newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_SN); newOption.setData(inst.getSubnetMask().getBytes()); newOption.setLength((byte) 4); dhcpAckOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_ROUTER) {newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_ROUTER); newOption.setData(inst.getRouterIp().getBytes()); newOption.setLength((byte) 4); dhcpAckOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_DN) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_DN); newOption.setData(inst.getDomainName().getBytes()); newOption.setLength((byte) inst.getDomainName().getBytes().length); dhcpAckOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_DNS) { if (!inst.getDnsIps().isEmpty()) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_DNS); ByteBuffer bb = ByteBuffer.allocate(inst.getDnsIps().size() * 4); /* exact size */ for (IPv4Address ip : inst.getDnsIps()) { bb.put(ip.getBytes()); } bb.flip(); newOption.setData(bb.array()); //TODO verify this newOption.setLength((byte) bb.array().length); dhcpAckOptions.add(newOption); } else { log.warn("Client asked for DNS servers, but we didn't have any for instance {}", inst.getName()); } } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_BROADCAST_IP) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_BROADCAST_IP); newOption.setData(inst.getBroadcastIp().getBytes()); newOption.setLength((byte) 4); dhcpAckOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER); newOption.setData(inst.getServerIp().getBytes()); newOption.setLength((byte) 4); dhcpAckOptions.add(newOption);} else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME) {newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME); newOption.setData(intToBytes(inst.getLeaseTimeSec())); newOption.setLength((byte) 4); dhcpAckOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_NTP_IP) { if (!inst.getNtpIps().isEmpty()) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_NTP_IP); ByteBuffer bb = ByteBuffer.allocate(inst.getNtpIps().size() * 4); /* exact size */ for (IPv4Address ip : inst.getNtpIps()) { bb.put(ip.getBytes()); } bb.flip(); newOption.setData(bb.array()); //TODO verify this newOption.setLength((byte) bb.array().length); dhcpAckOptions.add(newOption); } else { log.warn("Client asked for NTP servers, but we didn't have any for instance {}", inst.getName()); } } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME); newOption.setData(intToBytes(inst.getRebindTimeSec())); newOption.setLength((byte) 4); dhcpAckOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME); newOption.setData(intToBytes(inst.getRenewalTimeSec())); newOption.setLength((byte) 4); dhcpAckOptions.add(newOption); } else if (specificRequest.byteValue() == DHCP_REQ_PARAM_OPTION_CODE_IP_FORWARDING) { newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_IP_FORWARDING); newOption.setData(intToBytesSizeOne(inst.getIpForwarding() ? 1 : 0)); newOption.setLength((byte) 1); dhcpAckOptions.add(newOption); }else { log.debug("Setting specific request for ACK failed"); } } newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_END); newOption.setLength((byte) 0); dhcpAckOptions.add(newOption); dhcpDHCPAck.setOptions(dhcpAckOptions); ethDHCPAck.setPayload(ipv4DHCPAck.setPayload(udpDHCPAck.setPayload(dhcpDHCPAck))); DHCPACKPacket.setInPort(OFPort.ANY); List<OFAction> actions = new ArrayList<OFAction>(1); actions.add(sw.getOFFactory().actions().output(inPort, 0xffFFffFF)); DHCPACKPacket.setActions(actions); DHCPACKPacket.setData(ethDHCPAck.serialize()); log.debug("Sending DHCP ACK"); sw.write(DHCPACKPacket.build()); } public void sendDHCPNack(DHCPInstance inst, IOFSwitch sw, OFPort inPort, MacAddress chaddr, IPv4Address giaddr, int xid) { OFPacketOut.Builder DHCPOfferPacket = sw.getOFFactory().buildPacketOut(); DHCPOfferPacket.setBufferId(OFBufferId.NO_BUFFER); Ethernet ethDHCPOffer = new Ethernet(); ethDHCPOffer.setSourceMACAddress(inst.getServerMac()); ethDHCPOffer.setDestinationMACAddress(chaddr); ethDHCPOffer.setEtherType(EthType.IPv4); IPv4 ipv4DHCPOffer = new IPv4(); ipv4DHCPOffer.setDestinationAddress(BROADCAST_IP); ipv4DHCPOffer.setSourceAddress(inst.getServerIp()); ipv4DHCPOffer.setProtocol(IpProtocol.UDP); ipv4DHCPOffer.setTtl((byte) 64); UDP udpDHCPOffer = new UDP(); udpDHCPOffer.setDestinationPort(UDP.DHCP_CLIENT_PORT); udpDHCPOffer.setSourcePort(UDP.DHCP_SERVER_PORT); DHCP dhcpDHCPOffer = new DHCP(); dhcpDHCPOffer.setOpCode(DHCP_OPCODE_REPLY); dhcpDHCPOffer.setHardwareType((byte) 1); dhcpDHCPOffer.setHardwareAddressLength((byte) 6); dhcpDHCPOffer.setHops((byte) 0); dhcpDHCPOffer.setTransactionId(xid); dhcpDHCPOffer.setSeconds((short) 0); dhcpDHCPOffer.setFlags((short) 0); dhcpDHCPOffer.setClientIPAddress(UNASSIGNED_IP); dhcpDHCPOffer.setYourIPAddress(UNASSIGNED_IP); dhcpDHCPOffer.setServerIPAddress(inst.getServerIp()); dhcpDHCPOffer.setGatewayIPAddress(giaddr); dhcpDHCPOffer.setClientHardwareAddress(chaddr); List<DHCPOption> dhcpOfferOptions = new ArrayList<DHCPOption>(); DHCPOption newOption; newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_MSG_TYPE); newOption.setData(DHCP_MSG_TYPE_NACK); newOption.setLength((byte) 1); dhcpOfferOptions.add(newOption); newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER); newOption.setData(inst.getServerIp().getBytes()); newOption.setLength((byte) 4); dhcpOfferOptions.add(newOption); newOption = new DHCPOption(); newOption.setCode(DHCP_REQ_PARAM_OPTION_CODE_END); newOption.setLength((byte) 0); dhcpOfferOptions.add(newOption); dhcpDHCPOffer.setOptions(dhcpOfferOptions); ethDHCPOffer.setPayload(ipv4DHCPOffer.setPayload(udpDHCPOffer.setPayload(dhcpDHCPOffer))); DHCPOfferPacket.setInPort(OFPort.ANY); List<OFAction> actions = new ArrayList<OFAction>(1); actions.add(sw.getOFFactory().actions().output(inPort, 0xffFFffFF)); DHCPOfferPacket.setActions(actions); DHCPOfferPacket.setData(ethDHCPOffer.serialize()); log.info("Sending DHCP NACK"); sw.write(DHCPOfferPacket.build()); } public ArrayList<Byte> getRequestedParameters(DHCP DHCPPayload, boolean isInform) { ArrayList<Byte> requestOrder = new ArrayList<Byte>(); byte[] requests = DHCPPayload.getOption(DHCPOptionCode.OptionCode_RequestedParameters).getData(); boolean requestedLeaseTime = false; boolean requestedRebindTime = false; boolean requestedRenewTime = false; for (byte specificRequest : requests) { if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_SN) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_SN); } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_ROUTER) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_ROUTER); } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_DN) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_DN); } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_DNS) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_DNS); } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME); requestedLeaseTime = true; } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER); } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_BROADCAST_IP) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_BROADCAST_IP); } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_NTP_IP) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_NTP_IP); } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME); requestedRebindTime = true; } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME); requestedRenewTime = true; } else if (specificRequest == DHCP_REQ_PARAM_OPTION_CODE_IP_FORWARDING) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_IP_FORWARDING); log.debug("requested IP FORWARDING"); } else { //log.debug("Requested option 0x" + Byte.toString(specificRequest) + " not available"); } } // We need to add these in regardless if the request list includes them if (!isInform) { if (!requestedLeaseTime) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_LEASE_TIME); log.debug("added option LEASE TIME"); } if (!requestedRenewTime) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_RENEWAL_TIME); log.debug("added option RENEWAL TIME"); } if (!requestedRebindTime) { requestOrder.add(DHCP_REQ_PARAM_OPTION_CODE_REBIND_TIME); log.debug("added option REBIND TIME"); } } return requestOrder; } @Override public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { OFPacketIn pi = (OFPacketIn) msg; OFPort inPort = OFMessageUtils.getInPort(pi); OFVlanVidMatch vlan = OFMessageUtils.getVlan(pi); DHCPInstance instance = getInstance(new NodePortTuple(sw.getId(), inPort)); if (instance == null) { log.debug("Could not locate DHCP instance for DPID {}, port {}. Checking VLAN next", sw.getId(), inPort); instance = getInstance(vlan.getVlanVid()); } if (instance == null) { log.error("Could not locate DHCP instance for DPID {}, port {}, VLAN {}", new Object[] { sw.getId(), inPort, }); return Command.CONTINUE; } if (!instance.getPool().hasAvailableAddresses()) { log.info("DHCP Pool is full! Consider increasing the pool size."); return Command.CONTINUE; } Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); if (eth.getEtherType() == EthType.IPv4) { /* shallow compare is okay for EthType */ log.debug("Got IPv4 Packet"); IPv4 IPv4Payload = (IPv4) eth.getPayload(); IPv4Address IPv4SrcAddr = IPv4Payload.getSourceAddress(); if (IPv4Payload.getProtocol() == IpProtocol.UDP) { /* shallow compare also okay for IpProtocol */ log.debug("Got UDP Packet"); UDP UDPPayload = (UDP) IPv4Payload.getPayload(); if ((UDPPayload.getDestinationPort().equals(UDP.DHCP_SERVER_PORT) /* TransportPort must be deep though */ || UDPPayload.getDestinationPort().equals(UDP.DHCP_CLIENT_PORT)) && (UDPPayload.getSourcePort().equals(UDP.DHCP_SERVER_PORT) || UDPPayload.getSourcePort().equals(UDP.DHCP_CLIENT_PORT))) { log.debug("Got DHCP Packet"); // This is a DHCP packet that we need to process DHCP DHCPPayload = (DHCP) UDPPayload.getPayload(); /* DHCP/IPv4 Header Information */ int xid = 0; IPv4Address yiaddr = IPv4Address.NONE; IPv4Address giaddr = IPv4Address.NONE; MacAddress chaddr = null; IPv4Address desiredIPAddr = null; ArrayList<Byte> requestOrder = new ArrayList<Byte>(); if (DHCPPayload.getOpCode() == DHCP_OPCODE_REQUEST) { /** * (1) DHCP Discover * -- UDP src port = 68 * -- UDP dst port = 67 * -- IP src addr = 0.0.0.0 * -- IP dst addr = 255.255.255.255 * -- Opcode = 0x01 * -- XID = transactionX * -- All addresses blank: * -- ciaddr (client IP) * -- yiaddr (your IP) * -- siaddr (DHCPServer IP) * -- giaddr (GW IP) * -- chaddr = Client's MAC * -- Options: * -- Option 53 = DHCP Discover * -- Option 50 = possible IP request * -- Option 55 = parameter request list * -- (1) SN Mask * -- (3) Router * -- (15) Domain Name * -- (6) DNS **/ if (Arrays.equals(DHCPPayload.getOption(DHCP.DHCPOptionCode.OptionCode_MessageType).getData(), DHCP_MSG_TYPE_DISCOVER)) { log.debug("DHCP DISCOVER Received"); xid = DHCPPayload.getTransactionId(); yiaddr = DHCPPayload.getYourIPAddress(); // Will have GW IP if a relay agent was used giaddr = DHCPPayload.getGatewayIPAddress(); chaddr = DHCPPayload.getClientHardwareAddress(); List<DHCPOption> options = DHCPPayload.getOptions(); for (DHCPOption option : options) { if (option.getCode() == DHCP_REQ_PARAM_OPTION_CODE_REQUESTED_IP) { desiredIPAddr = IPv4Address.of(option.getData()); log.debug("Got requested IP"); } else if (option.getCode() == DHCP_REQ_PARAM_OPTION_CODE_REQUESTED_PARAMTERS) { log.debug("Got requested param list"); requestOrder = getRequestedParameters(DHCPPayload, false); } } // Process DISCOVER message and prepare an OFFER with minimum-hold lease // A HOLD lease should be a small amount of time sufficient for the client to respond // with a REQUEST, at which point the ACK will set the least time to the DEFAULT synchronized (instance.getPool()) { if (!instance.getPool().hasAvailableAddresses()) { log.info("DHCP Pool is full! Consider increasing the pool size."); log.info("Device with MAC " + chaddr.toString() + " was not granted an IP lease"); return Command.CONTINUE; } DHCPBinding lease = instance.getPool().getSpecificAvailableLease(desiredIPAddr, chaddr); if (lease != null) { log.debug("Checking new lease with specific IP"); instance.getPool().setDHCPbinding(lease, chaddr, instance.getHoldTimeSec()); yiaddr = lease.getIPv4Address(); log.debug("Got new lease for " + yiaddr.toString()); } else { log.debug("Checking new lease for any IP"); lease = instance.getPool().getAnyAvailableLease(chaddr); instance.getPool().setDHCPbinding(lease, chaddr, instance.getHoldTimeSec()); yiaddr = lease.getIPv4Address(); log.debug("Got new lease for " + yiaddr.toString()); } } sendDHCPOffer(instance, sw, inPort, chaddr, IPv4SrcAddr, yiaddr, giaddr, xid, requestOrder); } // END IF DISCOVER /** (3) DHCP Request * -- UDP src port = 68 * -- UDP dst port = 67 * -- IP src addr = 0.0.0.0 * -- IP dst addr = 255.255.255.255 * -- Opcode = 0x01 * -- XID = transactionX * -- ciaddr = blank * -- yiaddr = blank * -- siaddr = DHCP DHCPServer IP * -- giaddr = GW IP * -- chaddr = Client's MAC * -- Options: * -- Option 53 = DHCP Request * -- Option 50 = IP requested (from offer) * -- Option 54 = DHCP DHCPServer IP **/ else if (Arrays.equals(DHCPPayload.getOption(DHCP.DHCPOptionCode.OptionCode_MessageType).getData(), DHCP_MSG_TYPE_REQUEST)) { log.debug(": DHCP REQUEST received"); IPv4SrcAddr = IPv4Payload.getSourceAddress(); xid = DHCPPayload.getTransactionId(); yiaddr = DHCPPayload.getYourIPAddress(); giaddr = DHCPPayload.getGatewayIPAddress(); chaddr = DHCPPayload.getClientHardwareAddress(); List<DHCPOption> options = DHCPPayload.getOptions(); for (DHCPOption option : options) { if (option.getCode() == DHCP_REQ_PARAM_OPTION_CODE_REQUESTED_IP) { desiredIPAddr = IPv4Address.of(option.getData()); if (!desiredIPAddr.equals(instance.getPool().getDHCPbindingFromMAC(chaddr).getIPv4Address())) { // This client wants a different IP than what we have on file, so cancel its HOLD lease now (if we have one) instance.getPool().cancelLeaseOfMAC(chaddr); return Command.CONTINUE; } } else if (option.getCode() == DHCP_REQ_PARAM_OPTION_CODE_DHCP_SERVER) { if (!IPv4Address.of(option.getData()).equals(instance.getServerIp())) { // We're not the DHCPServer the client wants to use, so cancel its HOLD lease now and ignore the client instance.getPool().cancelLeaseOfMAC(chaddr); return Command.CONTINUE; } } else if (option.getCode() == DHCP_REQ_PARAM_OPTION_CODE_REQUESTED_PARAMTERS) { requestOrder = getRequestedParameters(DHCPPayload, false); } } // Process REQUEST message and prepare an ACK with default lease time // This extends the hold lease time to that of a normal lease boolean sendACK = true; synchronized (instance.getPool()) { if (!instance.getPool().hasAvailableAddresses()) { log.info("DHCP Pool is full! Consider increasing the pool size."); log.info("Device with MAC " + chaddr.toString() + " was not granted an IP lease"); return Command.CONTINUE; } DHCPBinding lease; // Get any binding, in use now or not if (desiredIPAddr != null) { lease = instance.getPool().getDHCPbindingFromIPv4(desiredIPAddr); } else { lease = instance.getPool().getAnyAvailableLease(chaddr); } // This IP is not in our allocation range if (lease == null) { log.info("The IP " + desiredIPAddr.toString() + " is not in the range " + instance.getPool().getStartIp().toString() + "+"); log.info("Device with MAC " + chaddr.toString() + " was not granted an IP lease"); sendACK = false; // Determine if the IP in the binding we just retrieved is okay to allocate to the MAC requesting it } else if (!lease.getMACAddress().equals(chaddr) && lease.isActiveLease()) { log.debug("Tried to REQUEST an IP that is currently assigned to another MAC"); log.debug("Device with MAC " + chaddr.toString() + " was not granted an IP lease"); sendACK = false; // Check if we want to renew the MAC's current lease } else if (lease.getMACAddress().equals(chaddr) && lease.isActiveLease()) { log.debug("Renewing lease for MAC " + chaddr.toString()); instance.getPool().renewLease(lease.getIPv4Address(), instance.getLeaseTimeSec()); yiaddr = lease.getIPv4Address(); log.debug("Finalized renewed lease for " + yiaddr.toString()); // Check if we want to create a new lease for the MAC } else if (!lease.isActiveLease()){ log.debug("Assigning new lease for MAC " + chaddr.toString()); instance.getPool().setDHCPbinding(lease, chaddr, instance.getLeaseTimeSec()); yiaddr = lease.getIPv4Address(); log.debug("Finalized new lease for " + yiaddr.toString()); } else { log.debug("Don't know how we got here"); return Command.CONTINUE; } } if (sendACK) { sendDHCPAck(instance, sw, inPort, chaddr, IPv4SrcAddr, yiaddr, giaddr, xid, requestOrder); } else { sendDHCPNack(instance, sw, inPort, chaddr, giaddr, xid); } } // END IF REQUEST else if (Arrays.equals(DHCPPayload.getOption(DHCP.DHCPOptionCode.OptionCode_MessageType).getData(), DHCP_MSG_TYPE_RELEASE)) { if (!DHCPPayload.getServerIPAddress().equals(instance.getServerIp())) { log.info("DHCP RELEASE message not for our DHCP server"); // Send the packet out the port it would normally go out via the Forwarding module // Execution jumps to return Command.CONTINUE at end of receive() } else { log.debug("Got DHCP RELEASE. Cancelling remaining time on DHCP lease"); synchronized(instance.getPool()) { if (instance.getPool().cancelLeaseOfMAC(DHCPPayload.getClientHardwareAddress())) { log.info("Cancelled DHCP lease of " + DHCPPayload.getClientHardwareAddress().toString()); log.info("IP " + instance.getPool().getDHCPbindingFromMAC(DHCPPayload.getClientHardwareAddress()).getIPv4Address().toString() + " is now available in the DHCP address pool"); } else { log.debug("Lease of " + DHCPPayload.getClientHardwareAddress().toString() + " was already inactive"); } } } } // END IF RELEASE else if (Arrays.equals(DHCPPayload.getOption(DHCP.DHCPOptionCode.OptionCode_MessageType).getData(), DHCP_MSG_TYPE_DECLINE)) { log.debug("Got DHCP DECLINE. Cancelling HOLD time on DHCP lease"); synchronized(instance.getPool()) { if (instance.getPool().cancelLeaseOfMAC(DHCPPayload.getClientHardwareAddress())) { log.info("Cancelled DHCP lease of " + DHCPPayload.getClientHardwareAddress().toString()); log.info("IP " + instance.getPool().getDHCPbindingFromMAC(DHCPPayload.getClientHardwareAddress()).getIPv4Address().toString() + " is now available in the DHCP address pool"); } else { log.info("HOLD Lease of " + DHCPPayload.getClientHardwareAddress().toString() + " has already expired"); } } } // END IF DECLINE else if (Arrays.equals(DHCPPayload.getOption(DHCP.DHCPOptionCode.OptionCode_MessageType).getData(), DHCP_MSG_TYPE_INFORM)) { log.debug("Got DHCP INFORM. Retreiving requested parameters from message"); IPv4SrcAddr = IPv4Payload.getSourceAddress(); xid = DHCPPayload.getTransactionId(); yiaddr = DHCPPayload.getYourIPAddress(); giaddr = DHCPPayload.getGatewayIPAddress(); chaddr = DHCPPayload.getClientHardwareAddress(); // Get the requests from the INFORM message. True for inform -- we don't want to include lease information requestOrder = getRequestedParameters(DHCPPayload, true); // Process INFORM message and send an ACK with requested information sendDHCPAck(instance, sw, inPort, chaddr, IPv4SrcAddr, yiaddr, giaddr, xid, requestOrder); } // END IF INFORM } // END IF DHCP OPCODE REQUEST else if (DHCPPayload.getOpCode() == DHCP_OPCODE_REPLY) { // Do nothing right now. The DHCP DHCPServer isn't supposed to receive replies but ISSUE them instead log.debug("Got an OFFER/ACK (REPLY)...this shouldn't happen unless there's another DHCP Server somewhere"); } else { log.debug("Got DHCP packet, but not a known DHCP packet opcode"); } } // END IF DHCP packet } // END IF UDP packet } // END IF IPv4 packet return Command.CONTINUE; } // END of receive(pkt) /** * DHCPLeasePolice is a simple class that is instantiated and invoked * as a runnable thread. The objective is to clean up the expired DHCP * leases on a set time interval. Most DHCP leases are hours in length, * so the granularity of our check can be on the order of minutes (IMHO). * The period of the check for expired leases, in seconds, is specified * in the configuration file: * * floodlight/src/main/resources/floodlightdefault.properties * * as option: * * net.floodlightcontroller.dhcpserver.DHCPServer.lease-gc-period = <seconds> * * where gc stands for "garbage collection". * * @author Ryan Izard, rizard@g.clemson.edu * */ class DHCPLeasePolice implements Runnable { @Override public void run() { log.info("Cleaning any expired DHCP leases..."); ArrayList<DHCPBinding> newAvailableBindings; for (DHCPInstance instance : instances.values()) { synchronized(instance.getPool()) { // Loop through lease pool and check all leases to see if they are expired // If a lease is expired, then clean it up and make the binding available newAvailableBindings = instance.getPool().cleanExpiredLeases(); } for (DHCPBinding binding : newAvailableBindings) { log.info("MAC " + binding.getMACAddress().toString() + " has expired"); log.info("Lease now available for IP " + binding.getIPv4Address().toString()); } } } } // END DHCPLeasePolice Class @Override public synchronized void enable() { log.warn("DHCP server module enabled"); enabled = true; } @Override public synchronized void disable() { log.warn("DHCP server module disabled"); enabled = false; } @Override public boolean isEnabled() { return enabled; } @Override public synchronized boolean addInstance(DHCPInstance instance) { if (instances.containsKey(instance.getName())) { log.error("DHCP instance {} already present. Not adding", instance.getName()); return false; } else { instances.put(instance.getName(), instance); return true; } } @Override public DHCPInstance getInstance(String name) { return instances.get(name); } @Override public DHCPInstance getInstance(NodePortTuple member) { for (DHCPInstance instance : instances.values()) { if (instance.getMemberPorts().contains(member)) { return instance; } } return null; } @Override public DHCPInstance getInstance(VlanVid member) { for (DHCPInstance instance : instances.values()) { if (instance.getMemberVlans().contains(member)) { return instance; } } return null; } @Override public Collection<DHCPInstance> getInstances() { return Collections.unmodifiableCollection(instances.values()); } @Override public synchronized boolean deleteInstance(String name) { if (instances.containsKey(name)) { log.error("DHCP instance {} not present. Cannot delete", name); return false; } else { instances.remove(name); return true; } } } // END DHCPServer Class


Подобные документы

  • Изучение функционирования DHCP сервера, базовая конфигурация первой ветки модели ЛВС, выполнение конфигурации DHCP второй ветки ЛВС c применением удаленного сервера базы данных. Распределение настроек сети, на все компьютеры, использование протокола DHCP.

    лабораторная работа [5,5 M], добавлен 08.05.2023

  • Принцип работы DHCP. Проблема автоматизации распределения IP-адресов. Реализация DHCP в Windows. Адреса для динамической конфигурации. Процесс функционирования служб. Механизм авторизации DHCP-серверов. Типы сообщений, направления, основные параметры.

    презентация [223,0 K], добавлен 10.09.2013

  • Протокол динамического распределения адресов DHCP (Dynamic Host Configuration Protocol). Конфигурационные параметры, взаимодействие клиента и сервера при выделении сетевого адреса. Internet/intranet - технологический базис новых методов управления.

    контрольная работа [825,5 K], добавлен 09.06.2010

  • Общее понятие о DHCP (протоколе динамического конфигурирования адресов). Порядок настройки сервера и доставки почты. Описание конфигурации в специальном файле. Особенности процесса отправки и приема сообщений. Режимы работы программного интерфейса.

    презентация [138,5 K], добавлен 25.10.2013

  • Основные функции отдела камеральных проверок налоговой инспекции. Автоматизация процесса назначения IP-адресов узлам сети с использованием протокола DHCP. Проблемы и примеры работы протокола DHCP. Модель клиент-сервер, механизм функционирования.

    отчет по практике [91,2 K], добавлен 22.03.2012

  • NIC (Network Interface Card) или сетевые адаптеры. Создание локальной сети и профиля. Выбор оборудования и операционной системы. Обжим проводов. Установка Windows 2003 Server, Traffic Inspector, DNS-сервера, DHCP-сервера. Применение маршрутизаторов.

    курсовая работа [8,8 M], добавлен 17.03.2014

  • Семейство ОС Windows 2000. Windows 2000 Server. Windows 2000 Advanced Server. Windows 2000 Datacenter Server. ОС Windows Server 2003. Организация сети на основе Windows 2000. Службы каталогов, DHCP, DNS, WINS. Конфигурирование сервера.

    курсовая работа [307,1 K], добавлен 06.10.2006

  • Создание виртуальной машины для гостевой операционной системы Microsoft Windows Server 2003. Первоначальная настройка установленной операционной системы. Создание DHCP-сервера с диапазоном рабочих адресов. Настройка доменного имени для IP-адреса сервера.

    лабораторная работа [3,2 M], добавлен 20.12.2012

  • Методы проектирования LAN для обеспечения обмена данными, доступа к общим ресурсам, принтерам и Internet. Автоматическая адресация в IP-сетях при помощи протокола DHCP. Алгоритмы маршрутизации, базирующиеся на информации о топологии и состоянии сети.

    дипломная работа [2,7 M], добавлен 01.07.2014

  • Разработка проекта корпоративной ЛВС. Реализация схемы IP-адресации с помощью сервисов DHCP и технологии NAT. Настройка сетевого оборудования (коммутаторов, маршрутизаторов, DNS, HTTP-серверов), динамической маршрутизации при помощи протоколов RIP и OSPF.

    курсовая работа [990,5 K], добавлен 15.01.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.