Основное

» Linux Docker 0.9 - краткое практическое руководство
Установка, настройка, запуск, основные моменты работы.

» Изучаем CGroups
Практический подход к изучению подсистемы ядра Linux

» db2dhcp - DHCP сервер на SQL СУБД
Сборка из исходников, настройка БД, запуск.

Последние записи

» Отличия синтаксиса C++ & Java и некоторые особенности Java
В рамках "заметок на полях" - краткий, очень поверхностный и слабо структурированный набор различий в...

» Восстановление старых разработок
Старые проекты по которым планируется восстановить работы

» Linux Docker 0.9 - краткое практическое руководство
Установка, настройка, запуск, основные моменты работы.

db2dhcp - DHCP сервер на SQL СУБД

19 мая 2011

Предисловие

Ещё во времена работы в интернет провайдинге мною была осознанна необходимость DHCP сервера работающего с SQL без всяких дополнительных скриптовых обвязок. На моё удивление такого сервера не было. Родилась идея его написать, в результате чего появился проект патча к ISC DHCP. То что получилось - работало (и работает по сей день), но честно говоря реализация была на столько запутанна и сложно поддерживаема (в силу ужасного стиля кода написанного ISC), что не нравилась мне самому. Потому было решено написать свою реализацию сервера с чистого листа.

Содержание

Возможности сервера

  • Работа с Ethernet сетями, IP протокол версии 4.
  • Поддерживаемые СУБД: PostgreSQL, MySQL.
  • Поддерживаемые ОС: сборка и базовое тестирование проведены в Linux, FreeBSD, Windows XP. Но ничего не должно помешать сборке в других ОС после минимальных доработок ОС зависимых функций.

Планируемые доработки:

  • Поддержка IP протокола версии 6.
  • Доведение внутренней логики работы сервера до полного соответствия RFC.
  • Расширение списка поддерживаемых СУБД.
  • Расширение списка поддерживаемых ОС.
  • Поддержка возможности регистрации в DNS.
  • Поддержка защиты SQL сервера от перегрузки ограничением по числу запросов от отдельных DHCP клиентов и от всего сервера в целом.
  • Возможность использования резервного сервера БД в случае отказа основного.

ВНИМАНИЕ

Исходные коды сервера доступные на данный момент являются альфа-версией, потому: от сервера можно ожидать любого не корректного поведения (падений, утечек памяти, самоблокировки); есть ряд недоработок как в логике работы самого сервера (например нет ограничения по числу запросов в секунду к БД), так и в реализации DHCP (пока нет полного соответствия RFC).

Применение без доработки в реально эксплуатируемых системах на данный момент не рекомендовано! В то же время автор надеется что все желающие помочь развитию проекта постараются произвести тесты в меру своих возможностей и сообщат об обнаруженных проблемах.

Сборка сервера

Требования для сборки

  • pthreads - поддержка POSIX threads, обязательно.
  • pcap - библиотека разработчика, обязательна.
  • pq - библиотека разработчика для PostgreSQL. Обязательна в случае использования PostgreSQL.
  • mysqlclient - библиотека разработчика для MySQL. Обязательна в случае использования MySQL.

Соответственно для работы уже скомпилированной версии нужны обычные версии этих библиотек (без файлов для разработчиков).

Сборка

Сборка производится абсолютно стандартно, единственное условие - обязательно не забудьте указать поддержку какой из СУБД необходимо активировать. В противном случае сервер соберётся но не будет поддерживать ни одной СУБД.

$ wget http://www.netpatch.ru/downloads/db2dhcp/db2dhcp-<VERSION>.tar.bz2
$ tar xf db2dhcp-<VERSION>.tar.bz2
$ cd db2dhcp-<VERSION>
$ ./configure --enable-mysql --enable-postgresql
$ make

Для сборки в FreeBSD командную строку configure нужно добавить:

LDFLAGS="-L/usr/local/lib -L/usr/local/lib/mysql" CFLAGS="-I/usr/local/include"

На данный момент последней доступной версией является 0.1.a.10.

Настройка сервера

Настройка осуществляется через командную строку и конфигурационный файл.

Параметры командной строки

  • -L - показывает список интерфейсов на которых возможна обработка DHCP запросов.
  • -D - отключает режим демонизмации.
  • -d - включает отладочный вывод в лог.
  • -q - "тихий" режим запуска.
  • -s - включает вывод сообщений в stdout, имеет смысл применять в случае использования ключа -D
  • -c <config-filename> - задаёт имя конфигурационного файла.
  • -o - выводит таблицу смещений полей в заголовке DHCP.
  • <interface-name1> [... <interface-nameN>] - задаёт список интерфейсов на которых сервер будет принимать DHCP запросы от клиентов.

Формат конфигурационного файла

Конфигурационный файл состоит из набора параметров имеющих общий формат:

Имя-параметра = значение

Допустимые параметры конфигурационного файла

  • User - имя пользователя от которого будет выполняться сервер. По умолчанию - текущий пользователь. Работа от имени суперпользователя строжайше не рекомендована! Не поддерживается на win32 платформе.
  • LogFile - имя лог-файла. Пользователь заданный директивой User должен иметь право записи в целевой каталог.
  • DBType - тип СУБД. Возможные значения: PostgreSQL, MySQL.
  • DBServerAddress - IP адрес сервера БД.
  • DBServerPort - порт сервера БД. По умолчанию соответствует порту выбранной СУБД.
  • DBUserName - имя пользователя БД.
  • DBUserPassword - пароль БД.
  • DBName - имя БД.
  • DBClientsCount - число потоков работающих с БД. По умолчанию: 4.
  • QueryDiscover - SQL запрос выполняющийся при получении DHCPDISCOVER. Обязательно должен быть определён.
  • QueryRequest - SQL запрос выполняющийся при получении DHCPREQUEST. Если не указан, то выполняется QueryDiscover.
  • QueryRequestRej - запрос выполняемый в случае если клиент не выбрал данный сервер. Не реализовано.
  • QueryInform - - SQL запрос выполняющийся при получении DHCPINFORM. Не реализовано.
  • QueryRelease - SQL запрос выполняющийся при получении DHCPRELEASE. Если не указан, то ничего не выполняется.
  • MaxQpsHost - максимальное число DHCP запросов в секунду от одного клиента. Не реализовано.
  • MaxQpsTotal - суммарное максимальное число DHCP запросов.Не реализовано.
  • DHCPServerPort - прослушиваемый порт для обработки DHCP запросов. По умолчанию: 67.
  • DHCPClientPort - клиентский DHCP порт на который будут уходить ответы. По умолчанию: 68.
  • DHCPCacheTTL - время хранения DHCP ответа во внутреннем кэше db2dhcp, в секундах. Если кэш включен, то в случае получения запроса DHCPREQUEST db2dhcp сперва проверит наличие ответа в кэше, если ответ обнаружен то DHCP клиент получит информацию из кэша db2dhcp - SQL запрос в БД выполняться не будет. Данная опция позволяет очень существенно снижать загркузку на сервер БД если используется небольшое (в пределах нескольких часов) значение времени аренды. По умолчанию кэш не используется (значение 0).
  • Var - параметр создающий переменную значение которой определяется по различным характеристикам DHCP запроса клиента. Подробности смотрите ниже.

Настройка запросов к БД

Основная суть настройки сервера заключается в правильном конфигурировании запросов выполняемых к БД. Для этого нужно знать и соблюдать следующее:

  • В запросах кроме обычных SQL выражений можно (и нужно) использовать встроенные переменные сервера и переменные объявленные пользователем. Пользовательские переменные могут содержать в себе простые условные конструкции. Переменные в запросах используются как $ИМЯ-ПЕРЕМЕННОЙ$.
  • Сам по себе запрос может выглядеть абсолютно как угодно и использовать любые допустимые SQL и выбранной версией СУБД конструкции (например - JOIN, UNION).
  • В получаемом из БД результате число и тип (смысловое значение) полей должны строго соответствовать требуемуму сервером формату: код, тип, значение. Это значит что любой запрос для получения данных должен начинаться как
    SELECT code-field-name, type-field-name, value-field-name FROM ...

Встроенные переменные сервера

Встроенные переменные делятся на два типа - переменные относящиеся к системе хоста и переменные относящиеся к интерфейсу (сетевому устройству) на котором был получен DHCP запрос.

Переменная относящаяся к системе пока только одна:

  • SRV-HOSTNAME - имя хоста на котором запущен сервер.

Переменные относящиеся к интерфейсу получившему DHCP запрос:

  • DEV-NAME - имя интерфейса.
  • DEV-ETHERADDR - Ethernet адрес интерфейса: шестнадцатиричные цифры в верхнем регистре, октеты разделены двоеточием.
  • DEV-IPADDR - строкое представление IP адреса интерфейса.
  • DEV-NETWORK - строковое представление IP адреса сети интерфейса.
  • DEV-NETMASK - строковое представление сетевой маски интерфейса.
  • DEV-NETMASK-CIDR - строковое представление сетевой маски интерфейса в формате CIDR (длина маски одним числом).
  • DEV-IPADDR-INT - числовое представление IP адреса интерфейса. Например 192.168.1.1 = 3232235777. Сделано т.к. поиск в SQL БД по числу может оказаться значительно быстрее поиска по строке.
  • DEV-NETWORK-INT - числовое представление IP адреса сети интерфейса.
  • DEV-NETMASK-INT - числовое представление сетевой маски интерфейса.
  • DEV-SRVPORT - номер порта сервера.
  • DEV-CLIPORT - номер порта клиента отправившего DHCP запрос.

Пользовательские переменные

Пользовательские переменные имеют возможность достаточно гибкой настройки при объявлении, благодаря чему в выполняемом SQL запросе можно использовать практически любую информацию из DHCP запроса клиента. Значения переменных передаются в запрос в виде hex-строк в верхнем регистре без какой-либо дополнительной конвертации и разделителей октетов.

Пользовательские переменные могут быть двух типов - содержащие данные из DHCP заголовка (описание переменной начинается с h) и содержащие данные из поля "опции" заголовка (описание начинается с o). Форматы обоих типов переменных:

Var = ИМЯ-ПЕРЕМЕННОЙ    h:<смещение>:<длина>
Var = ИМЯ-ПЕРЕМЕННОЙ   o:<код-опции>[:<смещение[:длина]>|<условная-конструкция>]
  1. h-переменные - поле смещение указывает смещение относительно начала заголовка DHCP пакета; поле длина указывает сколько байт необходимо скопировать из пакета в значение переменной. Пример объявления переменной для получения Ethernet адреса клиента:
    Var = CLI-ETHER-ADDR h:28:6
    По смещению в 28 байт от начала DHCP заголовка начинается поле аппаратного адреса. Ethernet адрес имеет длину 6 байт. Смещения полей заголовка вы можете узнать запустив db2dhcp с ключём -o.
  2. o-переменные - поле код-опции содержит код интересующей нас DHCP опции указанной клиентом в поле опций DHCP пакета. Если в строке больше ничего не указано - берётся всё значение опции. Если указаны смещение и длина, то смещение считается от начала данной опции; смысл поля длина такой же как и для h-переменных. Вместо указания смещения и длины можно указать условную конструкцию вычисляющую нужное смещение и длину. Если опция с указанным кодом не найдена в DHCP пакете - значением переменной будет пустая строка.

Формат условной конструкции:

(<смещение> = <значение>) <смещение[:код]_если_условие_верно> | \
      <смещение[:код]_если_условие_не_верно|вложенная_условная_конструкция> 

В скобках, в левой части от знака равенства указывается смещение от нулевого байта опции, начиная с которого выполняется сравнение. Значение - hex-строка произвольной длины (в разумных пределах - не длиннее ожидаемого значения опции) начинающаяяся с префикса 0x.

В результате будет выполнено сравнение значения опции начиная с указанного смещения с шестнадцатиричным значением заданным строкой-значением на длину равную длине строки-значения. Если значение опции совпадает со строкой-значением, то результатом условной конструкции будут смещение и длина указанные сразу после скобок. Если не совпадает - результатом будет смещение и длина указанные после вертикальной черты |. В случае не совпадения вместо непосредственного результата (смещение:длина) можно указать следующую условную конструкцию с другим условием.

Механизм условных конструкций реализован в основном для возможности обработки DHCP опции 82 - ожидается что при использовании устройств разных производителей (а значит имеющих разный формат этой опции) можно будет делать правильный разбор опции в самом сервере, без необходимости отсылки в БД "сырых" данных.

Коды и типы значений в БД

Как было сказано выше - данные выборки полученной из БД для правильной интерпретации сервером db2dhcp должны содержать правильный код и тип. Условимся что запрос на получение данных имеет вид:

SELECT code, type, value FROM ...

Исходя из этого разберём по отдельности значения каждого поля результирующей выборки:

  1. code - всегда дожен быть первым полем результирующей выборки данных. Может быть числом в диапазоне 0 - 255, либо 1000 и выше.
    Если код имеет значение 0 - 255, то данные в поле value интерпретируются как значение DHCP опции с таким кодом и добавляется в поле опций DHCP ответа. Возможные значения смотрите здесь.
    Если код имеет значение в диапазоне 1001 - 1015 (включительно), то данные поля value интерпретируются как значения соответствующего поля из заголовка DHCP пакета. Возможные значения смотрите в таблице кодов полей DHCP заголовка.
    Если код имеет значение выше 2000, то данные интерпретируются как служебные, не передающиеся в результирующий DHCP ответ и использующиеся самим сервером. Возможные значения смотрите в таблице служебных кодов.
  2. type - всегда должно быть вторым полем результирующей выборки данных. Указывает тип данных содержащихся в поле value. Указание типа необходимо что бы db2dhcp мог правильно преобразовать данные перед записью их в результирующий DHCP ответ. Возможные значения поля смотрите в таблице кодов типов значений.
  3. value - собственно данные которые будут непосредственно записаны в DHCP ответ клиенту. Вид и формат этих данных зависит от типа указанного в поле type.

Коды полей DHCP заголовка

Код Поле
1001 Код оператора сообщения (BOOTREQUEST/BOOTREPLY). Если это поле не задано в итоговой выборке – сервер сам его установит в правильное значение. Обычно явно указывать его не имеет смысла
1002 Тип аппаратного адреса. На данный момент допустим только Ethernet. Так же не имеет смысла устанавливать в базе – в случае отсутствия сервер сам устанавливает правильное значение
1003 Длина аппаратного адреса, по умолчанию – 6 (Ethernet)
1004 Поле hops (шаги)
1005 XID DHCP транзацкии
1006 Не должно присутствовать в данных выборки, сервером не устанавливается
1007 Флаги
1008 IP адрес клиента отправившего запрос. Не должно присутствовать в данных выборки
1009 IP адрес клиента предлагаемый DHCP сервером. Должно присутствовать в ответе сервера (данных выборки соответственно), только если это не ответ на DHCPINFORM
1010 Адрес следующего сервера загрузки. Если не указано в данных выборки, то db2dhcp проставляет в это поле IP адрес интерфейса на котором был получен DHCP запрос
1011 IP адрес агента пересылки (DHCP relay). Должно быть заполнено в случае использования агента. Если отсутствует в данных выборки – сервер сам заполняет его основываясь на запросе DHCP клиента. Обычно указывать его в базе не имеет смысла
1012 Аппаратный адрес клиента. Заполняется сервером самостоятельно
1013 Имя DHCP сервера
1014 Имя файла загрузки (при использовании сетевой загрузки хоста)
1015 Поле DHCP опций. Обычно не должно указываться в итоговом наборе данных т.к. опции задаются по отдельности

Служебные коды db2dhcp

Код Поле
2001 Запрет кэширования DHCPACK созданного из данного набора данных. Используется в случае если разрешено кэширование но для некоторых клиентов (например не имеющих привязки MAC→IP) это кэширование нужно отключить

Типы данных db2dhcp

Тип Код Пояснение
UINT1 1 Однобайтовое число
UINT4 2 Четырёхбайтовое число
HEX 3 Строка “сырых” hex-данных без разделителей. При интерпретации db2dhcp конвертирует строку в соответствующей ей набор двоичных данных без какой-либо дополнительной обработки. Удобно применять например для передачи маршрутной информации (опции 121 и 249)
STRING 4 Строковые данные. Записываются в ответ вообще без какой-либо дополнительной конвертации. Например имя хоста или сервера
IPADDRS 5 Список IP адресов. Может содержать один или более IP адресов разделённых запятой
BINARY 6 Двоичные данные. Копируются в ответ без какого-либо преобразования, разумеется для правильной обработки их клиентом – должны быть внесены в базу уже в подходящем двоичном представлении

Примеры настройки db2dhcp и БД

В качестве примера используем тестовую сеть: db2dhcp запущен на хосте 10.7.7.1; DHCP клиенты находятся в трёх физически разделённых сетях:

  1. Непосредственно в сегменте прослушиваемом DHCP сервером. IP адрес прослушиваемного интерфейса 10.7.7.1, сеть 10.7.7.0/24. Для определения правильной конфигурации клиента используется его Ethernet адрес.
  2. В удалённом сегменте сети 10.10.10.0/24. Обслуживается DHCP агентом пересылки (конкретно - ISC dhcrelay. Адрес агента 10.10.10.10. Для определения правильной конфигурации клиента используется его Ethernet адрес и IP адрес агента пересылки.
  3. В удалённом сегменте сети 10.70.70.0/24. Обслуживается DHCP агентом пересылки на свитче D-Link 3526. Адрес агегнта 10.7.7.100. Для определения правильной конфигурации DHCP клиентам используется IP адрес агента пересылки и опция 82.

Для обслуживания подобной сети используется три таблицы:

  1. dhcp_clients_by_ether - содержит конфигурационную информацию (IP адрес) для DHCP клиентов из первой и второй подсети. Имеется поле ether для идентификации клиента.
  2. dhcp_clients_by\ _relay - содержит информацию для DHCP клиентов из третьей подсети. Имеются поля relayid и relayport для идентификации клиентов.
  3. dhcp_subnets - содержит конфигурационную информацию общую для клиентов сети. Имеется поле subnet по которому выбирается конфигурация для конкретной сети. В случае с клиентами первой сети исользуется IP адрес интерфейса на котором был получен запрос; у клиентов второй и третьей сети используется IP адрес агента пересылки.

Создание БД

Подразумевается что пользователь dhcp уже создан. Команды выполняются от привелигерованного пользователя.

Для PostgreSQL:

CREATE DATABASE dhcp; 
ALTER DATABASE dhcp OWNER TO dhcp;
\c dhcp;
CREATE TABLE dhcp_clients_by_ether (
    code smallint,
    type smallint,
    ether character varying(12) DEFAULT NULL::character varying,
    value character varying(32) DEFAULT NULL::character varying
);
ALTER TABLE dhcp_clients_by_ether OWNER TO dhcp;

CREATE TABLE dhcp_clients_by_relay (
    code smallint,
    type smallint,
    relay_id character varying(32),
    relay_port character varying(2),
    value character varying(32)
);
ALTER TABLE dhcp_clients_by_relay OWNER TO dhcp;

CREATE TABLE dhcp_subnets (
    code smallint,
    type smallint,
    subnet bigint,
    value text
);
ALTER TABLE dhcp_subnets OWNER TO dhcp;

Для MySQL:

CREATE DATABASE dhcp;

CREATE TABLE dhcp_clients_by_ether (     
    code smallint,     type smallint,     
    ether character varying(12),     
    value character varying(32) );
    
CREATE TABLE dhcp_clients_by_relay (
    code smallint,
    type smallint,
    relay_id character varying(32),
    relay_port character varying(2),
    value character varying(32)
);

CREATE TABLE dhcp_subnets (
    code smallint,
    type smallint,
    subnet bigint,
    value text
);

GRANT ALL on dhcp.* TO dhcp;

ВНИМАНИЕ! Это тестовый пример для демонстрации возможностей сервера. В таблицах не создано ни одного индекса, а значит на больших наборах данных работа с такими таблицами будет затруднена. В реальности ваши таблицы могут быть совсем иными, потому построение индексов оставлено на ваше усмотрение.

Добавление данных в БД

Добавим минимально необходимые данные для клиентов из указанных выше подсетей:

-- Конфигурируем IP адреса для каждого клиента в отдельности.

-- IP адрес для клиента подключенного непосредственно к сети db2dhcp
INSERT INTO dhcp_clients_by_ether VALUES (1009, 5, '0003FF2C5290', '10.7.7.70');
-- IP адрес клиента обслуживаемого ISC dhcrelay 
INSERT INTO dhcp_clients_by_ether VALUES (1009, 5, '0003FF155290', '10.10.10.11');
-- IP адрес клиента обслуживаемого агентом пересылки в свитче. Привязка к идентификатору
-- свитча (001E5899156F) и порту (05) в который подключен клиент.
INSERT INTO dhcp_clients_by_relay VALUES (1009, 5, '001E5899156F', '05', '10.70.70.70');
-- Ещё один IP адрес для той же подсети и того же свитча. Другой порт (07).
INSERT INTO dhcp_clients_by_relay VALUES (1009, 5, '001E5899156F', '07', '10.70.70.71');

-- Настройка общих параметров подсетей.

-- Маска подсети. Одинакова для всех.
INSERT INTO dhcp_subnets VALUES (1, 5, 168232704, '255.255.255.0'), 
    (1, 5, 168430090, '255.255.255.0'), (1, 5, 168232804, '255.255.255.0');
-- IP адрес шлюза для каждой подсети.
INSERT INTO dhcp_subnets VALUES (3, 5, 168232704, '10.7.7.1'), 
    (3, 5, 168430090, '10.10.10.10'), (3, 5, 168232804, '10.70.70.1');
-- DNS сервера, одинаковы для всех. В примере использован DNS сервер Google.
INSERT INTO dhcp_subnets VALUES (6, 5, 168232704, '8.8.8.8'), 
    (6, 5, 168430090, '8.8.8.8'), (6, 5, 168232804, '8.8.8.8');
-- Имя домена, одинаково для всех
INSERT INTO dhcp_subnets VALUES (15, 4, 168232704, 'test.local'), 
    (15, 4, 168430090, 'test.local'), (15, 4, 168232804, 'test.local');
-- Время аренды IP адреса.
INSERT INTO dhcp_subnets VALUES (51, 2, 168232704, '7200'), 
    (51, 2, 168430090, '7200'), (51, 2, 168232804, '7200'); 

Создание конфигурационного файла

Минимально необходимый набор данных внесён в БД. Теперь можно записать конфигурационный файл:

User = 'nobody'
DBType = PostgreSQL
#DBType = MySQL
DBName = dhcp
DBClientsCount = 2
DBServerAddress = 127.0.0.1
DBUserName = 'dhcp'
DBUserPassword = 'dhcp'
LogFile = db2dhcp.log
DHCPCacheTTL = 3600

Var = CLI-GIADDR        h:24:4
Var = CLI-ETHER-ADDR    h:28:6  # Ethernet address
Var = OPT82-PORT        o:82:7:1
Var = OPT82-REMOTE-ID    o:82:12

QueryDiscover = SELECT code, type, value FROM dhcp_subnets \
                WHERE \
                    \ # Раскоментируйте следующую строку в случае использования PostgreSQL
                     (subnet = '$DEV-NETWORK-INT$' and x'$CLI-GIADDR$'::bigint = 0) \
                    \ # Раскоментируйте следующую строку в случае использования MySQL
                    \ # (subnet = '$DEV-NETWORK-INT$' and CONV('$CLI-GIADDR$', 16, 10) = 0) \
                OR \
                    \ # Раскоментируйте следующую строку в случае использования PostgreSQL
                    subnet = x'$CLI-GIADDR$'::bigint \
                    \ # Раскоментируйте следующую строку в случае использования MySQL
                    \ # subnet = CONV('$CLI-GIADDR$', 16, 10) \
                \
                UNION \
                \
                SELECT code, type, value FROM dhcp_clients_by_ether \
                WHERE \
                    ether = '$CLI-ETHER-ADDR$' \
                AND \
                    '$OPT82-REMOTE-ID$' = '' \
                AND \
                    '$OPT82-PORT$' = '' \
                \
                UNION \
                \
                SELECT code, type, value FROM dhcp_clients_by_relay \
                \
                WHERE \
                    relay_id = '$OPT82-REMOTE-ID$' \
                AND \
                    relay_port = '$OPT82-PORT$' \
                ORDER BY CODE

#QueryRequest = ''
#QueryRelease = ''

Определены 4 пользовательских переменные: CLI-GIADDR - IP адрес агента пересылки; CLI-ETHER-ADDR - аппаратный адрес DHCP клиента; OPT82-PORT - порт свитча на котором был получен запрос; OPT82-REMOTE-ID - идентификатор свитча получившего запрос (фактически - его MAC адрес).

В запросе QueryDiscover первый блок (до первого UNION) получает общую конфигурационную информацию для подсети клиента, второй блок пытается получить IP адрес клиента из таблицы с привязкой MAC->IP, третий блок - пытается получить IP адрес клиента из таблицы с привязкой к порту коммутатора. Если вы всё сделали правильно, то в результате обработки запроса от клиента внесённого в БД итоговый набор данных будет выглядеть например так:

 code | type |     value
------+------+---------------
    1 |    5 | 255.255.255.0
    3 |    5 | 10.7.7.1
    6 |    5 | 8.8.8.8
   15 |    4 | test.local
   51 |    5 | 7200
 1009 |    5 | 10.7.7.70
 

Конфигурирование сервера закончено.

Запуск сервера

Проверим работоспособность сервера добавив при запуске ключи -Ds - это позволит читать лог сервера непосредственно из консоли и остановить сервер по Ctrl+C. (в лог ниже добавлены коментарии и удалены временные отметки и PID процесса)

$ sudo ./src/db2dhcp -Dsc db2dhcp.conf eth1
INFO: Program db2dhcp (DataBase to DHCP server) started.
Starting request handler threads (using DBM PostgreSQL) ...
Connected to PostgreSQL server.
Connected to PostgreSQL server.
All (2) request handlers started.
Starting DHCP listener thread on interface 'eth1', ether '00:02:44:75:77:E4'...
DHCP listener thread started. Waiting clients.
# С этого момента сервер готов обрабатывать DHCP запросы
# Первый запрос от клиента из собственной подсети db2dhcp. 
# В скобках указывается фактический код опции DHCP сообщения.
Got DHCPDISCOVER (1) message from client 00:03:FF:2C:52:90 on eth1/10.7.7.1
# Ответ DHCP клиенту. Через слеш указан IP адрес выданный клиенту.
Sending DHCPOFFER (2) to 00:03:FF:2C:52:90/10.7.7.70 via 10.7.7.1
Got DHCPREQUEST (3) message from client 00:03:FF:2C:52:90 on eth1/10.7.7.1
# Т.к. включено кэширование - при получении DHCPREQUEST сервер сперва проверяет
# наличие ответа в своём кэше. По скольку ответ найден - отвечает из кэша (запрос в БД не делается).
Found response for client 00:03:FF:2C:52:90 on 10.7.7.1 in DHCP cache.
Sending DHCPACK (5) to 00:03:FF:2C:52:90/10.7.7.70 via 10.7.7.1
Got DHCPINFORM (8) message from client 00:03:FF:2C:52:90 on eth1/10.7.7.1
# Обработка DHCPINFORM пока не реализована, потому запрос клиента игнорируется.
Ignore this message.
# Запрос от клиента подключенного к свитчу поддерживаюему опцию 82. 
# В скобках в конце строки указывается IP адрес агента пересылки.
Got DHCPDISCOVER (1) message from client 00:22:15:49:34:08 on eth1/10.7.7.1 (relay 10.7.7.100)
Sending DHCPOFFER (2) to 00:22:15:49:34:08/10.70.70.71 via 10.7.7.1 (relay 10.7.7.100)
Got DHCPREQUEST (3) message from client 00:22:15:49:34:08 on eth1/10.7.7.1 (relay 10.7.7.100)
Found response for client 00:1E:58:99:15:6F from relay 10.7.7.100 in DHCP cache.
Sending DHCPACK (5) to 00:22:15:49:34:08/10.70.70.71 via 10.7.7.1 (relay 10.7.7.100)
# Запрос от клиента чья подсеть обслуживается ISC dhcrelay.
Got DHCPDISCOVER (1) message from client 00:03:FF:15:52:90 on eth1/10.7.7.1 (relay 10.10.10.10)
Sending DHCPOFFER (2) to 00:03:FF:15:52:90/10.10.10.11 via 10.7.7.1 (relay 10.10.10.10)
Got DHCPREQUEST (3) message from client 00:03:FF:15:52:90 on eth1/10.7.7.1 (relay 10.10.10.10)
Found response for client 00:03:FF:14:52:90 from relay 10.10.10.10 in DHCP cache.
Sending DHCPACK (5) to 00:03:FF:15:52:90/10.10.10.11 via 10.7.7.1 (relay 10.10.10.10)

Отладка

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

Кроме того рекомендую использовать tcpdump запущенный на интерфейсе прослушиваемом сервером с аргументами -nvvvs0 port 67. Если всё же самостоятельно разобраться не получается и вы уверены что проблема в сервере (либо недостаточности документации на него) - просьба сообщить об этом мне приложив отладочный лог сервера и дампы пакетов с интерфейса.

Полезные ссылки


comments powered by Disqus