DHCP MYSQL
Конфиг для DHCP средсвами MYSQL
Есть желание уйти от всяких скриптов (php, bash, perl) для получения конфига из MySQL для dhcpd а так же с помошью представлений отказаться от привязки к конкретным таблицам.
Заодно проверить какое из решений будет работать быстрее.
Это только черновик пока и я еще не использую это решение в продакшене
TODO
- Проверить что бы использовалась только таблица mtraf_status
Создание представдения
Для того что бы не быть привязаным к структуре базы (которую программист биллинга вообще-то может менять по своему усмотрению) все данные для dhcp буду получать из view.
Стараюсь хранить данные в виде их "физических сущностей" - а именно IP - как INT UNSIGNED. В некоторых случаях приходиться брать данные "как есть" и преобразовывать.
DROP view mtraf_status; CREATE VIEW mtraf_status AS SELECT domain AS domain, IF( 0n_a<0 OR ( 0n_a=0 AND debt=0 ) ,0,1) AS status, ip AS ip, mac AS mac, IF( 0n_a<0 OR ( 0n_a=0 AND debt=0), inet_ntoa(inet_aton(ip)+6553600),ip) AS ip_dhcp, lower(substr(replace(concat(':', mac), ':0', ':') from 2)) AS mac_dhcp FROM mtraf;
Условие в IF - условие когда абонент "должен" - ему нужно дать другой IP (у меня вместо, например, 10.0.136.10 он получит 10,100,136,10) и соответвенно, пускать только на биллинг (если короко, то файрволл не пускает абонентов никуда кроме отдельного ДНСа (или отдельного view) который на все запросы отвечает адресом странички "дай денег, дорогой абонент" и собственно биллинга) Всем кто будет напоминать про dhcp snooping, opt 82 и прочее - это все делается для остатоков неуправляемых сегментов.
Дополнительные данные о сети
В биллинге (в моем случае) нет никакой информации о топологии сети). Нужно добавить данные о сетях, релеях, гейтвеях. Отмечу, что в сети есть как минимум 2 релея (т.к. сети 10.0... и 10.100... - алиасы ) и запрос прийти может через любой из них. В общем случае релеев может быть сколько угодно - по числу алиасов на интерфейсе.
DROP TABLE network_relay; CREATE TABLE network_relay ( network int(64) UNSIGNED, relay int(64) UNSIGNED ); INSERT into network_relay values(INET_ATON('10.0.135.0'), INET_ATON('10.0.135.1')); INSERT into network_relay values(INET_ATON('10.0.135.0'), INET_ATON('10.0.135.254')); INSERT into network_relay values(INET_ATON('10.0.135.0'), INET_ATON('10.100.135.1')); INSERT into network_relay values(INET_ATON('10.0.135.0'), INET_ATON('10.100.135.254')); INSERT into network_relay values(INET_ATON('10.0.136.0'), INET_ATON('10.0.136.1')); INSERT into network_relay values(INET_ATON('10.0.136.0'), INET_ATON('10.0.136.254')); INSERT into network_relay values(INET_ATON('10.0.136.0'), INET_ATON('10.100.136.1')); INSERT into network_relay values(INET_ATON('10.0.136.0'), INET_ATON('10.100.136.254')); INSERT into network_relay values(INET_ATON('10.0.137.0'), INET_ATON('10.0.137.1')); INSERT into network_relay values(INET_ATON('10.0.137.0'), INET_ATON('10.0.137.254')); INSERT into network_relay values(INET_ATON('10.0.137.0'), INET_ATON('10.100.137.1')); INSERT into network_relay values(INET_ATON('10.0.137.0'), INET_ATON('10.100.137.254'));
DROP TABLE network_mask; CREATE TABLE network_mask ( network int UNSIGNED NOT NULL UNIQUE, mask int UNSIGNED, is_dhcp int DEFAULT 1 ); INSERT into network_mask(network,mask) values(INET_ATON('10.0.135.0'), INET_ATON('255.255.255.0')); INSERT into network_mask(network,mask) values(INET_ATON('10.0.136.0'), INET_ATON('255.255.255.0')); INSERT into network_mask(network,mask) values(INET_ATON('10.0.137.0'), INET_ATON('255.255.255.0'));
DROP TABLE network_gateway; CREATE TABLE network_gateway ( network int UNSIGNED, gateway int UNSIGNED ); INSERT into network_gateway values(INET_ATON('10.0.135.0'), INET_ATON('10.0.135.254')); INSERT into network_gateway values(INET_ATON('10.0.136.0'), INET_ATON('10.0.136.254')); INSERT into network_gateway values(INET_ATON('10.0.137.0'), INET_ATON('10.0.137.254')); INSERT into network_gateway values(INET_ATON('10.100.135.0'), INET_ATON('10.100.135.254')); INSERT into network_gateway values(INET_ATON('10.100.136.0'), INET_ATON('10.100.136.254')); INSERT into network_gateway values(INET_ATON('10.100.137.0'), INET_ATON('10.100.137.254'));
Процедуры и функции
Решил максимально разбить задачу на отдельные атомарные функции, MySQL к это теперь позволяет
Вычисление броадкаста
Тривиальная задача зная ip и маску. Для простоты вынес в отдельную ф-ю. DROP FUNCTION GetBroadcast; delimiter // CREATE FUNCTION GetBroadcast(n1 int UNSIGNED, m1 INT UNSIGNED) RETURNS INT UNSIGNED BEGIN
DECLARE b1 INT UNSIGNED; SELECT n1+POWER(2,32-BIT_COUNT(m1))-1 INTO b1; RETURN b1;
END // delimiter ;
Получение маски для IP
Зная IP получаем маску сети (которая в общем случае может отличаться от "255.255.255.0". Возвращаю первое вхождение.
DROP FUNCTION GetMaskForIP; delimiter // CREATE FUNCTION GetMaskForIP(ip1 int(64) UNSIGNED) RETURNS INT UNSIGNED BEGIN DECLARE mask1 INT UNSIGNED; SELECT mask from network_mask WHERE ip1&mask=network LIMIT 1 INTO mask1; RETURN mask1; END // delimiter ;
Пример:
mysql> SELECT INET_NTOA(GetMaskForIP(INET_ATON('10.0.136.12'))); +---------------------------------------------------+ | INET_NTOA(GetMaskForIP(INET_ATON('10.0.136.12'))) | +---------------------------------------------------+ | 255.255.255.0 | +---------------------------------------------------+ 1 row in set (0.01 sec)
Аналогично для "неплатильщиков"
DROP FUNCTION GetMaskForNoPayIP; delimiter // CREATE FUNCTION GetMaskForNoPayIP(ip1 int(64) UNSIGNED) RETURNS INT UNSIGNED BEGIN DECLARE mask1 INT UNSIGNED; SELECT mask from network_mask WHERE (ip1-6553600)&mask=network limit 1 INTO mask1; RETURN mask1; END // delimiter ;
Получение списка relay для сети
В сети запрос может прийти от одного или нескольких возможных relay-агентов. Для каждой сети - определен список этих relay. Задача - сгенерировать часть конфига вида "запрос пришел через релей1 ИЛИ запрос пришел через релей2 ИЛИ ..."
DROP FUNCTION GetRelayForNet; delimiter // CREATE FUNCTION GetRelayForNet(n1 int UNSIGNED) RETURNS MEDIUMTEXT BEGIN -- done is "end of cycle" variable DECLARE done INT DEFAULT 0; DECLARE current_relay MEDIUMTEXT default ""; DECLARE dhcp_relay MEDIUMTEXT; DECLARE dhcp_relay_res MEDIUMTEXT default ""; -- set done=1 when cusror ends -- cursor for relay DECLARE cursor_relay CURSOR FOR SELECT relay from network_relay WHERE network=n1 LIMIT 1,18446744073709551615; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; OPEN cursor_relay; SELECT INET_NTOA(relay) INTO dhcp_relay FROM network_relay WHERE network=n1 LIMIT 1; SELECT CONCAT("( ( binary-to-ascii(10, 8, \".\", packet(24, 4))=\"", dhcp_relay, "\" ) ") INTO dhcp_relay_res; FETCH cursor_relay INTO current_relay; WHILE done = 0 DO SELECT INET_NTOA(relay) INTO dhcp_relay FROM network_relay WHERE relay = current_relay LIMIT 1; SELECT CONCAT(dhcp_relay_res, " or (binary-to-ascii(10, 8, \".\", packet(24, 4))=\"", dhcp_relay,"\")") INTO dhcp_relay_res; FETCH cursor_relay INTO current_relay; END WHILE; CLOSE cursor_relay; RETURN CONCAT(dhcp_relay_res, ")"); END // delimiter ;
Пример:
SELECT GetRelayForNet(INET_ATON('10.0.136.0')); +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | GetRelayForNet(INET_ATON('10.0.136.0')) | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ( ( binary-to-ascii(10, 8, ".", packet(24, 4))="10.0.136.1" ) or (binary-to-ascii(10, 8, ".", packet(24, 4))="10.0.136.254") or (binary-to-ascii(10, 8, ".", packet(24, 4))="10.100.136.1") or (binary-to-ascii(10, 8, ".", packet(24, 4))="10.100.136.254")) | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
class для IP
Для простоты разделелил генерацию класса на несколько частей
Эта функция возващает заготовку класса (match mac-address) для определенного IP.
DROP FUNCTION GetClassForIP; delimiter // CREATE FUNCTION GetClassForIP(ip1 int UNSIGNED) RETURNS char(255) BEGIN DECLARE mac_dhcp1 char(255) DEFAULT ""; DECLARE ip_d char(255) DEFAULT ""; SELECT ip_dhcp INTO ip_d FROM mtraf_status WHERE ip=INET_NTOA(ip1); SELECT mac_dhcp INTO mac_dhcp1 FROM mtraf_status WHERE mtraf_status.ip=ip_d LIMIT 1; RETURN CONCAT("class \"",ip_d,"__",mac_dhcp1,"\" { match if ( ( binary-to-ascii(16, 8, \":\", substring(hardware,1, 6)) = \"",mac_dhcp1,"\") and"); END // delimiter ;
Пример
mysql> SELECT GetClassForIP(INET_ATON('10.0.136.11')); +------------------------------------------------------------------------------------------------------------------------------------+ | GetClassForIP(INET_ATON('10.0.136.11')) | +------------------------------------------------------------------------------------------------------------------------------------+ | class "10.0.136.11__0:13:d4:5:d9:f4" { match if( ( binary-to-ascii(16, 8, ":", substring(hardware,1, 6)) = "0:13:d4:5:d9:f4 and | +------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.10 sec)
Генерация полноценного класса
Собираем полноценный класс из частей.
DROP FUNCTION GetFullClassForIP; delimiter // CREATE FUNCTION GetFullClassForIP(ip1 int UNSIGNED) RETURNS TEXT BEGIN RETURN CONCAT( GetClassForIP(ip1), " " , GetRelayForNet(GetNetForIP(ip1)) ,"}\n" ) ; END // delimiter ;
Пример (читать так: Классу соответвует запрос с маком $mac прошедьший через $relay[1] или $relay[2] или ... или relay[N] ). В такой конфигурации мак должен быть уникален в пределах сегмента а не в пределах всей сети:
mysql> SELECT GetFullClassForIP(INET_ATON('10.0.136.11')); +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | GetFullClassForIP(INET_ATON('10.0.136.11')) | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | class "10.0.136.11__0:13:d4:5:d9:f4" { match if( ( binary-to-ascii(16, 8, ":", substring(hardware,1, 6)) = "0:13:d4:5:d9:f4 and ( ( binary-to-ascii(10, 8, ".", packet(24, 4))="10.0.136.1" ) or (binary-to-ascii(10, 8, ".", packet(24, 4))="10.0.136.254") or (binary-to-ascii(10, 8, ".", packet(24, 4))="10.100.136.1") or (binary-to-ascii(10, 8, ".", packet(24, 4))="10.100.136.254"))} | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.08 sec)
Определить какой сети принадлежит IP
DROP FUNCTION GetNetForIP; delimiter // CREATE FUNCTION GetNetForIP(ip1 int UNSIGNED) RETURNS int UNSIGNED BEGIN DECLARE net1 INT UNSIGNED; SELECT network INTO net1 FROM network_mask WHERE ip1&mask=network LIMIT 1; RETURN net1; END // delimiter ;
Пример:
mysql> SELECT INET_NTOA(GetNetForIP(INET_ATON('10.0.136.11'))); +--------------------------------------------------+ | INET_NTOA(GetNetForIP(INET_ATON('10.0.136.11'))) | +--------------------------------------------------+ | 10.0.136.0 | +--------------------------------------------------+ 1 row in set (0.00 sec)
создание пула для IP
DROP FUNCTION GetPoolForIP; delimiter // CREATE FUNCTION GetPoolForIP(ip1 int UNSIGNED) RETURNS MEDIUMTEXT BEGIN DECLARE mac_dhcp1 VARCHAR(255); SELECT mac_dhcp INTO mac_dhcp1 FROM mtraf_status WHERE INET_ATON(mtraf_status.ip)=ip1 LIMIT 1; RETURN CONCAT( "pool { range ", INET_NTOA(ip1), "; allow members of \"", INET_NTOA(ip1), "__", mac_dhcp1, "\"; default-lease-time 36000; max-lease-time 72000; } " ); END // delimiter ;
создание пула для ip неплатильщика
DROP FUNCTION GetPoolForNoPayIP; delimiter // CREATE FUNCTION GetPoolForNoPayIP(ip1 int UNSIGNED) RETURNS MEDIUMTEXT BEGIN DECLARE ip_dhcp1 VARCHAR(32) DEFAULT ""; DECLARE mac_dhcp1 VARCHAR(255) DEFAULT ""; SELECT INET_NTOA(ip1) INTO ip_dhcp1; SELECT mac_dhcp INTO mac_dhcp1 FROM mtraf_status WHERE INET_ATON(mtraf_status.ip)=ip1-6553600 LIMIT 1; RETURN CONCAT( "pool { range ", ip_dhcp1, "; allow members of \"", ip_dhcp1, "__", mac_dhcp1, "\"; default-lease-time 36000; max-lease-time 72000; } " ); END // delimiter ; SELECT GetPoolForNoPayIP(INET_ATON('10.100.136.84'));
Пример:
mysql> SELECT GetPoolForNoPayIP(INET_ATON('10.100.136.84')); +---------------------------------------------------------------------------------------------------------------------------------+ | GetPoolForNoPayIP(INET_ATON('10.100.136.84')) | +---------------------------------------------------------------------------------------------------------------------------------+ | pool { range 10.100.136.84; allow members of 10.100.136.84__0:1d:92:58:27:cf default-lease-time 36000; max-lease-time 72000; } | +---------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.04 sec)
Полные пулы для тех кто платит и тех кто нет (из одного сегмента)
Получить пулы для тех кто платит
DROP FUNCTION GetAllPoolsForNet; delimiter // CREATE FUNCTION GetAllPoolsForNet(n1 int UNSIGNED) RETURNS MEDIUMTEXT BEGIN DECLARE done INT DEFAULT 0; DECLARE mask1 int UNSIGNED; DECLARE current_ip int UNSIGNED DEFAULT 0; DECLARE pools MEDIUMTEXT DEFAULT " "; DECLARE cursor_ip CURSOR FOR SELECT INET_ATOn(ip_dhcp) from mtraf_status WHERE INET_ATON(mtraf_status.ip_dhcp)&mask1=n1; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; SELECT mask from network_mask WHERE network=n1 INTO mask1; OPEN cursor_ip; FETCH cursor_ip INTO current_ip; WHILE done = 0 DO SELECT CONCAT(GetPoolForIP(current_ip)," \n",pools) INTO pools; FETCH cursor_ip INTO current_ip; END WHILE; CLOSE cursor_ip; RETURN pools; END // delimiter ;
Пример (часть поскипано):
mysql> SELECT GetAllPoolsForNet(INET_ATON('10.0.136.0')); ... pool { range 10.0.136.154; allow members of 10.0.136.154__0:e:2e:98:32:c default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.153; allow members of 10.0.136.153__0:15:f2:5:44:29 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.152; allow members of 10.0.136.152__0:e0:1c:3c:33:cd default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.151; allow members of 10.0.136.151__0:e0:1c:3b:d6:39 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.150; allow members of 10.0.136.150__0:19:d1:e6:1e:2c default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.149; allow members of 10.0.136.149__0:18:f3:fb:fe:b6 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.174; allow members of 10.0.136.174__0:26:2d:5f:97:c1 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.148; allow members of 10.0.136.148__0:26:9e:75:50:d2 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.147; allow members of 10.0.136.147__0:a0:d1:ca:47:b default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.145; allow members of 10.0.136.145__0:e0:4c:3:d7:55 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.146; allow members of 10.0.136.146__0:1f:c6:4f:ed:7a default-lease-time 36000; max-lease-time 72000; } ... 1 row in set (13.79 sec)
И тех кто не платит
DROP FUNCTION GetAllPoolsForNoPayNet; delimiter // CREATE FUNCTION GetAllPoolsForNoPayNet(n1 int UNSIGNED) RETURNS MEDIUMTEXT BEGIN DECLARE done INT DEFAULT 0; DECLARE mask1 int UNSIGNED; DECLARE current_ip int UNSIGNED DEFAULT 0; DECLARE pools MEDIUMTEXT DEFAULT " "; DECLARE cursor_ip CURSOR FOR SELECT INET_ATON(ip_dhcp) from mtraf_status WHERE (INET_ATON(mtraf_status.ip_dhcp))&mask1=(n1+6553600); DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; SELECT mask from network_mask WHERE network=n1 INTO mask1; OPEN cursor_ip; FETCH cursor_ip INTO current_ip; WHILE done = 0 DO SELECT CONCAT(GetPoolForNoPayIP(current_ip)," \n",pools) INTO pools; FETCH cursor_ip INTO current_ip; END WHILE; CLOSE cursor_ip; RETURN pools; END // delimiter ;
Конфиг SUBNET
Для того что бы выдавать статические маршруты (и не говорите мне что при правильном дизайне сети это не нужно=) ) нужно gateway разбивать на октеты и писать в виде 192, 168, 0, 1 что вносит приятное разнообразие программирование. Ну, и еще - рассчитвать btoadcast зная netmask и network (спасибо дяде Кораблеву за наше счастливое детство лекции )
Строка с маршрутами получилась довольно длинная.
DROP FUNCTION GetSubnet; delimiter // CREATE FUNCTION GetSubnet(n1 int UNSIGNED) RETURNS TEXT BEGIN -- broacast DECLARE b1 INT UNSIGNED; DECLARE m1 INT UNSIGNED; DECLARE g1 INT UNSIGNED; DECLARE oct_1 INT UNSIGNED; DECLARE oct_2 INT UNSIGNED; DECLARE oct_3 INT UNSIGNED; DECLARE oct_4 INT UNSIGNED; DECLARE gateway_dhcp VARCHAR(255); DECLARE prefix TEXT default ""; DECLARE pools TEXT default ""; SELECT GetMaskForIP(n1) INTO m1; SELECT GetBroadcast(n1,m1) INTO b1; SELECT GetGateway(n1) INTO g1; SELECT (g1 & INET_ATON('255.0.0.0')) >> 24 INTO oct_1; SELECT (g1 & INET_ATON('0.255.0.0')) >> 16 INTO oct_2; SELECT (g1 & INET_ATON('0.0.255.0')) >> 8 INTO oct_3; SELECT (g1 & INET_ATON('0.0.0.255')) >> 0 INTO oct_4; SELECT CONCAT(oct_1,",",oct_2,",",oct_3,",",oct_4) INTO gateway_dhcp; SELECT CONCAT("subnet ",INET_NTOA(n1)," netmask ",INET_NTOA(m1)," { \n option subnet-mask ",INET_NTOA(m1),";\n option broadcast-address ",INET_NTOA(b1),";\n option routers ",INET_NTOA(g1),";\n \n ddns-update-style none;\n option domain-name \"airbites.kh.ua\";\n option domain-name-servers 193.33.48.33, 193.33.49.160, 195.69.244.7, 195.69.244.2, 193.33.48.1, 193.33.49.1;\n option ms-classless-static-routes 4, 224, ",gateway_dhcp,", 8, 10, ",gateway_dhcp,", 12, 172,16, ",gateway_dhcp,", 16, 192,168, ",gateway_dhcp,", 17, 95,69,128, ",gateway_dhcp,", 32, 193, 33, 48, 1, ",gateway_dhcp,", 32, 193, 33, 48, 33, ",gateway_dhcp,", 32, 193, 33, 49, 1, ",gateway_dhcp,", 32, 193, 33, 49, 160, ",gateway_dhcp,", 17, 188, 230, 0, ",gateway_dhcp,";\n option rfc3442-classless-static-routes 4, 224, ",gateway_dhcp,", 8, 10, gateway_dhcp, 12, 172,16, ",gateway_dhcp,", 16, 192,168, ",gateway_dhcp,", 17, 95,69,128, ",gateway_dhcp,", 32, 193, 33, 48, 1, ",gateway_dhcp,", 32, 193, 33, 48, 33, ",gateway_dhcp,", 32, 193, 33, 49, 1, ",gateway_dhcp,", 32, 193, 33, 49, 160, ",gateway_dhcp,", 17, 188, 230, 0, ",gateway_dhcp,";") INTO prefix; SELECT GetAllPoolsForNet(n1) INTO pools; RETURN CONCAT(prefix,"\n\n",pools,"\n\n }"); END // delimiter ;
Пример:
subnet 10.0.136.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 10.0.136.255; option routers 10.0.136.254; ddns-update-style none; option domain-name "airbites.kh.ua"; option domain-name-servers 193.33.48.33, 193.33.49.160, 195.69.244.7, 195.69.244.2, 193.33.48.1, 193.33.49.1; option ms-classless-static-routes 4, 224, 10,0,136,254, 8, 10, 10,0,136,254, 12, 172,16, 10,0,136,254, 16, 192,168, 10,0,136,254, 17, 95,69,128, 10,0,136,254, 32, 193, 33, 48, 1, 10,0,136,254, 32, 193, 33, 48, 33, 10,0,136,254, 32, 193, 33, 49, 1, 10,0,136,254, 32, 193, 33, 49, 160, 10,0,136,254, 17, 188, 230, 0, 10,0,136,254; option rfc3442-classless-static-routes 4, 224, 10,0,136,254, 8, 10, gateway_dhcp, 12, 172,16, 10,0,136,254, 16, 192,168, 10,0,136,254, 17, 95,69,128, 10,0,136,254, 32, 193, 33, 48, 1, 10,0,136,254, 32, 193, 33, 48, 33, 10,0,136,254, 32, 193, 33, 49, 1, 10,0,136,254, 32, 193, 33, 49, 160, 10,0,136,254, 17, 188, 230, 0, 10,0,136,254; pool { range 10.0.136.154; allow members of 10.0.136.154__0:e:2e:98:32:c default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.153; allow members of 10.0.136.153__0:15:f2:5:44:29 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.152; allow members of 10.0.136.152__0:e0:1c:3c:33:cd default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.151; allow members of 10.0.136.151__0:e0:1c:3b:d6:39 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.150; allow members of 10.0.136.150__0:19:d1:e6:1e:2c default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.149; allow members of 10.0.136.149__0:18:f3:fb:fe:b6 default-lease-time 36000; max-lease-time 72000; } pool { range 10.0.136.174; allow members of 10.0.136.174__0:26:2d:5f:97:c1 default-lease-time 36000; max-lease-time 72000; } ...поскипано ... 1 row in set (14.09 sec)