Задача: динамически формировать конфигурационный файл для dhcp-сервера isc-dhcpd. При этом, если в настройках учетной записи абонента стоит галка «один на порту», то не проверять его мак-адрес. В этом случае учитываются только порт подключения и мак-адрес свича. Как это будет выглядеть в сформированном конфиге:
class "host10.0.0.7" {match if suffix(option agent.circuit-id,1)=a and suffix(option agent.remote-id,6)=00:11:22:33:44:55;} subnet 10.0.0.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 10.0.0.255; host host10.0.0.6 { hardware ethernet 00:11:00:11:00:22; fixed-address 10.0.0.6; } pool { range 10.0.0.7; allow members of "host10.0.0.7"; } }
Здесь мы видим, что абонент, подключенный к порту 10 («a» в 16-ричной системе счисления) свича с мак-адресом 00:11:22:33:44:55 получит ip 10.0.0.7. Абонент с мак-адресом 00:11:00:11:00:22 получит ip 10.0.0.6. У первого абонента в настройках стоит галка «один на порту».
Создаем файл /usr/local/nodeny/kernel/make_config_dhcp.cfg:
run => 0, period => 60, template => { 'dhcp_ok.tmpl' => { # куда будет записан сформированный конфиг file => '/usr/local/etc/dhcpd.conf', # системная команда, которая будет выполнена перед записью конфига, можно '' cmd_before => '', # системная команда, которая будет выполнена после записи конфига, можно '' cmd_after => '/usr/local/etc/rc.d/isc-dhcpd forcestart >/dev/null', # удалять пустые строки pretty => 1, }, }, subs => { pretty_mac => sub { my $mac = shift; $mac =~ s/(..)/$1:/g; chop $mac; return $mac; }, hex => sub { return sprintf('%x', $_[0]); } }
Создаем /usr/local/nodeny/kernel/make_config/dhcp_ok.tmpl:
allow unknown-clients; option domain-name-servers 1.1.1.1, 8.8.8.8; default-lease-time 28800; min-lease-time 10000; max-lease-time 128800; authoritative; ddns-update-style interim; log-facility local7; {% for user in users %} {% if user.ips.0.ipa && user.ips.0.type eq 'static' && user.connection.0 && user.connection.0.oneconnect %} {% one_line %} class "host{{user.ips.0.ipa}}" { match if suffix(option agent.circuit-id,1)={{user.connection.0.device_port|hex}} and suffix(option agent.remote-id,6)={{user.connection.0.device_mac|pretty_mac}}; } {% one_line_end %} {% endif %} {% endfor %} subnet 10.0.0.0 netmask 255.255.255.0 { option subnet-mask 255.255.255.0; option broadcast-address 10.0.0.255; interface em1; option routers 10.0.0.1; {% for user in users %} {% if user.ips.0.ipa && user.ips.0.type eq 'static' && user.connection.0 %} {% if user.connection.0.oneconnect %} pool { range {{user.ips.0.ipa}}; allow members of "host{{user.ips.0.ipa}}"; } {% else %} host host{{user.ips.0.ipa}} { hardware ethernet {{user.connection.0.mac|pretty_mac}}; fixed-address {{user.ips.0.ipa}}; } {% endif %} {% endif %} {% endfor %} }
Запустим с выводом результата на экран:
perl /usr/local/nodeny/nokernel.pl -v -m=make_config -g=make_config_dhcp
Если конфиг сформирован правильно, добавим запуск make_config в автозагрузку:
echo '/usr/bin/perl /usr/local/nodeny/nokernel.pl -m=make_config -g=make_config_dhcp -d &' >> /etc/rc.local
Небольшие комментарии по шаблону: