db2dhcp — DHCP сервер на SQL СУБД (В работе)
Содержание [Скрыть]
db2dhcp — DHCP сервер на SQL СУБД
На основной работе возникла необходимость поднять DHCP сервер, с возможностью выдачи IP адреса абоненту по следующим критериям: известный MAC адрес свича, известный порт на свиче с которого пришел запрос, причем данные чтоб хранились в БД MySQL. Вполне подошел проект http://www.netpatch.ru/devel/db2dhcp/. Одно НО, в нем не был реализован функционал ведения «истории авторизаций» в БД, да и проект в целом оказался заброшенным, а выйти на автора не удалось. Собственно поэтому и возник форк данного проекта.
Текущие изменения:
- реализована возможность ведения истории авторизаций пользователя
- можно указать IP адрес, который нужно «слушать» (по умолчанию «садился» на 0.0.0.0)
- доработана возможность сборки проекта под FreeBSD 8.4, 9.2, 10
GIT репозитарий проекта здесь: https://github.com/donpadlo/dhcp2db
Возможности сервера
- Работа с Ethernet сетями, IP протокол версии 4.
- Поддерживаемые СУБД: PostgreSQL, MySQL.
- Поддерживаемые ОС: сборка и базовое тестирование проведены в Linux, FreeBSD, Windows XP. Но ничего не должно помешать сборке в других ОС после минимальных доработок ОС зависимых функций.
ВНИМАНИЕ
Исходные коды сервера доступные на данный момент являются альфа-версией, потому: от сервера можно ожидать любого не корректного поведения (падений, утечек памяти, самоблокировки); есть ряд недоработок как в логике работы самого сервера (например нет ограничения по числу запросов в секунду к БД), так и в реализации DHCP (пока нет полного соответствия RFC).
Применение без доработки в реально эксплуатируемых системах на данный момент не рекомендовано! В то же время надеемся что все желающие помочь развитию проекта постараются произвести тесты и присоединятся к совершенствованию кода в силу своих возможностей.
Сборка сервера
Требования для сборки
- pthreads — поддержка POSIX threads, обязательно.
- pcap — библиотека разработчика, обязательна.
- pq — библиотека разработчика для PostgreSQL. Обязательна в случае использования PostgreSQL.
- mysqlclient — библиотека разработчика для MySQL. Обязательна в случае использования MySQL.
Соответственно для работы уже скомпилированной версии нужны обычные версии этих библиотек (без файлов для разработчиков).
Сборка
Сборка производится абсолютно стандартно, единственное условие — обязательно не забудьте указать поддержку какой из СУБД необходимо активировать. В противном случае сервер соберётся но не будет поддерживать ни одной СУБД.
Для сборки в FreeBSD командную строку configure нужно добавить:
LDFLAGS="-L/usr/local/lib -L/usr/local/lib/mysql" CFLAGS="-I/usr/local/include"
Настройка сервера
Настройка осуществляется через командную строку и конфигурационный файл.
Параметры командной строки
-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 запроса клиента. Подробности смотрите ниже.
- IPtoBind — на каком IP слушаем DHCP запросы. Обычно 0.0.0.0
- QueryHistory — запрос для записи в БД сохранения истории авторизации
Настройка запросов к БД
Основная суть настройки сервера заключается в правильном конфигурировании запросов выполняемых к БД. Для этого нужно знать и соблюдать следующее:
- В запросах кроме обычных 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). Форматы обоих типов переменных:
- h-переменные — поле
смещение
указывает смещение относительно начала заголовка DHCP пакета; поледлина
указывает сколько байт необходимо скопировать из пакета в значение переменной. Пример объявления переменной для получения Ethernet адреса клиента:
Var = CLI-ETHER-ADDR h:28:6
По смещению в 28 байт от начала DHCP заголовка начинается поле аппаратного адреса. Ethernet адрес имеет длину 6 байт. Смещения полей заголовка вы можете узнать запустив db2dhcp с ключём-o
. - o-переменные — поле код-опции содержит код интересующей нас DHCP опции указанной клиентом в поле опций DHCP пакета. Если в строке больше ничего не указано — берётся всё значение опции. Если указаны смещение и длина, то смещение считается от начала данной опции; смысл поля
длина
такой же как и для h-переменных. Вместо указания смещения и длины можно указать условную конструкцию вычисляющую нужное смещение и длину. Если опция с указанным кодом не найдена в DHCP пакете — значением переменной будет пустая строка.
Формат условной конструкции:
В скобках, в левой части от знака равенства указывается смещение от нулевого байта опции, начиная с которого выполняется сравнение. Значение — hex-строка произвольной длины (в разумных пределах — не длиннее ожидаемого значения опции) начинающаяяся с префикса 0x.
В результате будет выполнено сравнение значения опции начиная с указанного смещения с шестнадцатиричным значением заданным строкой-значением на длину равную длине строки-значения. Если значение опции совпадает со строкой-значением, то результатом условной конструкции будут смещение и длина указанные сразу после скобок. Если не совпадает — результатом будет смещение и длина указанные после вертикальной черты |. В случае не совпадения вместо непосредственного результата (смещение:длина) можно указать следующую условную конструкцию с другим условием.
Механизм условных конструкций реализован в основном для возможности обработки DHCP опции 82 — ожидается что при использовании устройств разных производителей (а значит имеющих разный формат этой опции) можно будет делать правильный разбор опции в самом сервере, без необходимости отсылки в БД «сырых» данных.
Коды и типы значений в БД
Как было сказано выше — данные выборки полученной из БД для правильной интерпретации сервером db2dhcp должны содержать правильный код и тип. Условимся что запрос на получение данных имеет вид:
Исходя из этого разберём по отдельности значения каждого поля результирующей выборки:
- code — всегда дожен быть первым полем результирующей выборки данных. Может быть числом в диапазоне 0 — 255, либо 1000 и выше.
Если код имеет значение 0 — 255, то данные в поле value интерпретируются как значение DHCP опции с таким кодом и добавляется в поле опций DHCP ответа. Возможные значения смотрите здесь.
Если код имеет значение в диапазоне 1001 — 1015 (включительно), то данные поля value интерпретируются как значения соответствующего поля из заголовка DHCP пакета. Возможные значения смотрите в таблице кодов полей DHCP заголовка.
Если код имеет значение выше 2000, то данные интерпретируются как служебные, не передающиеся в результирующий DHCP ответ и использующиеся самим сервером. Возможные значения смотрите в таблице служебных кодов. - type — всегда должно быть вторым полем результирующей выборки данных. Указывает тип данных содержащихся в поле value. Указание типа необходимо что бы db2dhcp мог правильно преобразовать данные перед записью их в результирующий DHCP ответ. Возможные значения поля смотрите в таблице кодов типов значений.
- 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 клиенты находятся в трёх физически разделённых сетях:
- Непосредственно в сегменте прослушиваемом DHCP сервером. IP адрес прослушиваемного интерфейса 10.7.7.1, сеть 10.7.7.0/24. Для определения правильной конфигурации клиента используется его Ethernet адрес.
- В удалённом сегменте сети 10.10.10.0/24. Обслуживается DHCP агентом пересылки (конкретно — ISC dhcrelay. Адрес агента 10.10.10.10. Для определения правильной конфигурации клиента используется его Ethernet адрес и IP адрес агента пересылки.
- В удалённом сегменте сети 10.70.70.0/24. Обслуживается DHCP агентом пересылки на свитче D-Link 3526. Адрес агегнта 10.7.7.100. Для определения правильной конфигурации DHCP клиентам используется IP адрес агента пересылки и опция 82.
Для обслуживания подобной сети используется три таблицы:
- dhcp_clients_by_ether — содержит конфигурационную информацию (IP адрес) для DHCP клиентов из первой и второй подсети. Имеется поле ether для идентификации клиента.
- dhcp_clients_by\ _relay — содержит информацию для DHCP клиентов из третьей подсети. Имеются поля relayid и relayport для идентификации клиентов.
- 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:
DELIMITER $$
CREATE PROCEDURE insert2history
(IN mac_sw_in
VARCHAR(20), IN port_in
VARCHAR(20), IN mac_client_in
VARCHAR(20))
DETERMINISTIC
BEGIN
DECLARE iip varchar(20);
DECLARE vgid int(11);
DECLARE vblocked int(11);
DECLARE ip_cur CURSOR FOR SELECT value,vg_id,blocked FROM dhcp_clients_by_relay WHERE mac_sw_in=relay_id AND port_in=relay_port;
OPEN ip_cur;
FETCH ip_cur INTO iip,vgid,vblocked;
CLOSE ip_cur;
IF vgid>0 THEN
INSERT into dhcp_hist(dt,mac_sw,port,mac_client,assigned_ip,vg_id,blocked) values (now(),mac_sw_in,port_in,mac_client_in,iip,vgid,vblocked);
ELSE SELECT «ok»;
END IF;
END$$
DELIMITER ;
CREATE TABLE IF NOT EXISTS dhcp_clients_by_relay
(
id
int(11) NOT NULL,
code
smallint(6) NOT NULL,
type
smallint(6) NOT NULL,
relay_id
varchar(200) COLLATE utf8_bin NOT NULL,
relay_port
varchar(200) COLLATE utf8_bin NOT NULL,
vg_id
int(11) NOT NULL,
segment_id
int(11) NOT NULL,
value
varchar(200) COLLATE utf8_bin DEFAULT NULL,
blocked
int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS dhcp_subnets
(
id
int(11) NOT NULL,
code
int(11) NOT NULL,
type
int(11) NOT NULL,
segment_id
int(11) NOT NULL,
subnet
varchar(100) COLLATE utf8_bin DEFAULT NULL,
value
varchar(200) COLLATE utf8_bin NOT NULL,
record_id
varchar(200) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS dhcp_hist
( id
int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, dt
datetime NOT NULL, mac_sw
varchar(20) COLLATE utf8_bin NOT NULL, port
varchar(20) COLLATE utf8_bin NOT NULL, mac_client
varchar(20) COLLATE utf8_bin NOT NULL, assigned_ip
varchar(20) COLLATE utf8_bin NOT NULL, vg_id
int(11) NOT NULL ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
ALTER TABLE dhcp_clients_by_relay
ADD PRIMARY KEY (id
), ADD UNIQUE KEY vg_id
(vg_id
);
ALTER TABLE dhcp_subnets
ADD PRIMARY KEY (id
), ADD UNIQUE KEY record_id
(record_id
);
ALTER TABLE dhcp_clients_by_relay
MODIFY id
int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2;
ALTER TABLE dhcp_hist
MODIFY id
int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4;
ALTER TABLE dhcp_subnets
MODIFY id
int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE dhcp_hist
ADD blocked
INT NOT NULL AFTER vg_id
;
ALTER TABLE dhcp_clients_by_relay
ADD blocked
INT NOT NULL AFTER value
;
ALTER TABLE dhcp_clients_by_relay
ADD userlogin
VARCHAR(20) NOT NULL AFTER blocked
;
ВНИМАНИЕ! Это тестовый пример для демонстрации возможностей сервера. В таблицах не создано ни одного индекса, а значит на больших наборах данных работа с такими таблицами будет затруднена. В реальности ваши таблицы могут быть совсем иными, потому построение индексов оставлено на ваше усмотрение.
Добавление данных в БД
Добавим минимально необходимые данные для клиентов из указанных выше подсетей:
— Конфигурируем 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=root
LogFile=/var/log/db2dhcp.log
DBType=MySQL
DBServerAddress=localhost
DBServerPort=3306
DBUserName=erfwerfwer
DBUserPassword=erferf
DBName=dhcp2db
DBClientsCount=1
DHCPCacheTTL=0
Var = CLI-GIADDR h:24:4
Var = CLI-ETHER-ADDR h:28:6 # Ethernet address
Var = OPT82-PORT o:82:(7=0x00)9:1|7:1
Var = OPT82-REMOTE-ID o:82:9:6
IPtoBind=172.17.117.2
#QueryDiscover=SELECT code, type, value FROM dhcp_subnets where (subnet = ‘$DEV-NETWORK-INT$’ and CONV(‘$CLI-GIADDR$’, 16, 10) = 0) or subnet = CONV(‘$CLI-GIADDR$’, 16, 10) UNION SELECT code, type, value FROM dhcp_clients_by_relay WHERE relay_id = ‘$OPT82-REMOTE-ID$’ AND relay_port = ‘$OPT82-PORT$’ ORDER BY CODE
QueryDiscover=SELECT code, type, value FROM dhcp_subnets where segment_id in (SELECT segment_id FROM dhcp_clients_by_relay WHERE relay_id = ‘$OPT82-REMOTE-ID$’ AND relay_port = ‘$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
QueryHistory=CALL insert2history(‘$OPT82-REMOTE-ID$’,’$OPT82-PORT$’,’$CLI-ETHER-ADDR$’);
Определены 4 пользовательских переменные: CLI-GIADDR — IP адрес агента пересылки; CLI-ETHER-ADDR — аппаратный адрес DHCP клиента; OPT82-PORT — порт свитча на котором был получен запрос; OPT82-REMOTE-ID — идентификатор свитча получившего запрос (фактически — его MAC адрес).
В запросе QueryDiscover первый блок (до первого UNION) получает общую конфигурационную информацию для подсети клиента, второй блок пытается получить IP адрес клиента из таблицы с привязкой MAC->IP, третий блок — пытается получить IP адрес клиента из таблицы с привязкой к порту коммутатора. Если вы всё сделали правильно, то в результате обработки запроса от клиента внесённого в БД итоговый набор данных будет выглядеть например так:
Конфигурирование сервера закончено.
Запуск сервера
Проверим работоспособность сервера добавив при запуске ключи -Ds
— это позволит читать лог сервера непосредственно из консоли и остановить сервер по Ctrl+C. (в лог ниже добавлены коментарии и удалены временные отметки и PID процесса)
Отладка
Если сервер ведёт себя не так как ожидалось: не выдаёт адреса, выдаёт адреса не правильно и т.д. — скорее всего вы неправильно настроили запрос в базу, либо переменные участвующие в этом запросе (а может это просто бага в сервере ). Что бы разобраться в чём дело — запустите сервер с опцией
-d
и смотрите в логи. Вывод достаточно подробен что бы можно было решить многие потенциальные проблемы. В частности в отладочном выводе вы можете увидеть исполняемые в БД запросы и попробовав выполнить их самостоятельно разобраться правильный-ли результат получается.
Кроме того рекомендую использовать tcpdump
запущенный на интерфейсе прослушиваемом сервером с аргументами -nvvvs0 port 67
.