Page MenuHomeVyOS Platform

No OneTemporary

Size
14 KB
Referenced Files
None
Subscribers
None
diff --git a/data/templates/dhcp-server/dhcpd.conf.tmpl b/data/templates/dhcp-server/dhcpd.conf.tmpl
index 3e0fd8d1d..d172018bf 100644
--- a/data/templates/dhcp-server/dhcpd.conf.tmpl
+++ b/data/templates/dhcp-server/dhcpd.conf.tmpl
@@ -1,192 +1,192 @@
### Autogenerated by dhcp_server.py ###
# For options please consult the following website:
# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html
#
# log-facility local7;
{% if hostfile_update %}
on release {
set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
set ClientMac = binary-to-ascii(16, 8, ":",substring(hardware, 1, 6));
set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", ClientName, ClientIp, ClientMac, ClientDomain);
}
on expiry {
set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
set ClientMac = binary-to-ascii(16, 8, ":",substring(hardware, 1, 6));
set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", ClientName, ClientIp, ClientMac, ClientDomain);
}
{% endif %}
{% if host_decl_name %}
use-host-decl-names on;
{% endif %}
ddns-update-style {{ 'interim' if ddns_enable else 'none' }};
{% if static_route %}
option rfc3442-static-route code 121 = array of integer 8;
option windows-static-route code 249 = array of integer 8;
{% endif %}
{% if wpad %}
option wpad-url code 252 = text;
{% endif %}
{% if global_parameters %}
# The following {{ global_parameters | length }} line(s) were added as global-parameters in the CLI and have not been validated
{% for param in global_parameters %}
{{ param }}
{% endfor %}
{% endif %}
# Failover configuration
{% for network in shared_network %}
{% if not network.disabled %}
{% for subnet in network.subnet %}
{% if subnet.failover_name %}
failover peer "{{ subnet.failover_name }}" {
{% if subnet.failover_status == 'primary' %}
primary;
mclt 1800;
split 128;
{% elif subnet.failover_status == 'secondary' %}
secondary;
{% endif %}
address {{ subnet.failover_local_addr }};
port 520;
peer address {{ subnet.failover_peer_addr }};
peer port 520;
max-response-delay 30;
max-unacked-updates 10;
load balance max seconds 3;
}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
# Shared network configration(s)
{% for network in shared_network if not network.disabled %}
shared-network {{ network.name }} {
{% if network.authoritative %}
authoritative;
{% endif %}
{% if network.network_parameters %}
# The following {{ network.network_parameters | length }} line(s) were added as shared-network-parameters in the CLI and have not been validated
{% for param in network.network_parameters %}
{{ param }}
{% endfor %}
{% endif %}
{% for subnet in network.subnet %}
subnet {{ subnet.address }} netmask {{ subnet.netmask }} {
{% if subnet.dns_server %}
option domain-name-servers {{ subnet.dns_server | join(', ') }};
{% endif %}
{% if subnet.domain_search %}
option domain-search {{ subnet.domain_search | join(', ') }};
{% endif %}
{% if subnet.ntp_server %}
option ntp-servers {{ subnet.ntp_server | join(', ') }};
{% endif %}
{% if subnet.pop_server %}
option pop-server {{ subnet.pop_server | join(', ') }};
{% endif %}
{% if subnet.smtp_server %}
option smtp-server {{ subnet.smtp_server | join(', ') }};
{% endif %}
{% if subnet.time_server %}
option time-servers {{ subnet.time_server | join(', ') }};
{% endif %}
{% if subnet.wins_server %}
option netbios-name-servers {{ subnet.wins_server | join(', ') }};
{% endif %}
{% if subnet.static_route %}
option rfc3442-static-route {{ subnet.static_route }}{% if subnet.rfc3442_default_router %}, {{ subnet.rfc3442_default_router }}{% endif %};
option windows-static-route {{ subnet.static_route }};
{% endif %}
{% if subnet.ip_forwarding %}
option ip-forwarding true;
{% endif %}
{% if subnet.default_router %}
option routers {{ subnet.default_router }};
{% endif %}
{% if subnet.server_identifier %}
option dhcp-server-identifier {{ subnet.server_identifier }};
{% endif %}
{% if subnet.domain_name %}
option domain-name "{{ subnet.domain_name }}";
{% endif %}
{% if subnet.subnet_parameters %}
# The following {{ subnet.subnet_parameters | length }} line(s) were added as subnet-parameters in the CLI and have not been validated
{% for param in subnet.subnet_parameters %}
{{ param }}
{% endfor %}
{% endif %}
{% if subnet.tftp_server %}
option tftp-server-name "{{ subnet.tftp_server }}";
{% endif %}
{% if subnet.bootfile_name %}
option bootfile-name "{{ subnet.bootfile_name }}";
filename "{{ subnet.bootfile_name }}";
{% endif %}
{% if subnet.bootfile_server %}
next-server {{ subnet.bootfile_server }};
{% endif %}
{% if subnet.time_offset %}
option time-offset {{ subnet.time_offset }};
{% endif %}
{% if subnet.wpad_url %}
option wpad-url "{{ subnet.wpad_url }}";
{% endif %}
{% if subnet.client_prefix_length %}
option subnet-mask {{ subnet.client_prefix_length }};
{% endif %}
{% if subnet.lease %}
default-lease-time {{ subnet.lease }};
max-lease-time {{ subnet.lease }};
{% endif %}
{% for host in subnet.static_mapping if not host.disabled %}
- host {% if host_decl_name %} {{ host.name }} {% else %} {{ network.name }}_{{ host.name }} {% endif %} {
+ host {{ host.name if host_decl_name else network.name + '_' + host.name }} {
{% if host.ip_address %}
fixed-address {{ host.ip_address }};
{% endif %}
hardware ethernet {{ host.mac_address }};
{% if host.static_parameters %}
# The following {{ host.static_parameters | length }} line(s) were added as static-mapping-parameters in the CLI and have not been validated
{% for param in host.static_parameters %}
{{ param }}
{% endfor %}
{% endif %}
}
{% endfor %}
{% if subnet.failover_name %}
pool {
failover peer "{{ subnet.failover_name }}";
deny dynamic bootp clients;
{% for range in subnet.range %}
range {{ range.start }} {{ range.stop }};
{% endfor %}
}
{% else %}
{% for range in subnet.range %}
range {{ range.start }} {{ range.stop }};
{% endfor %}
{% endif %}
}
{% endfor %}
on commit {
set shared-networkname = "{{ network.name }}";
{% if hostfile_update %}
set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
set ClientIp = binary-to-ascii(10, 8, ".", leased-address);
set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
{% endif %}
}
}
{% endfor %}
diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py
index 03537472a..8d6917cf1 100755
--- a/smoketest/scripts/cli/test_service_dhcp-server.py
+++ b/smoketest/scripts/cli/test_service_dhcp-server.py
@@ -1,95 +1,148 @@
#!/usr/bin/env python3
#
# Copyright (C) 2019-2020 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
import os
import unittest
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
from vyos.util import cmd
from vyos.util import process_named_running
from vyos.util import read_file
from vyos.template import inc_ip
from vyos.template import address_from_cidr
from vyos.template import netmask_from_cidr
PROCESS_NAME = 'dhcpd'
DHCPD_CONF = '/run/dhcp-server/dhcpd.conf'
base_path = ['service', 'dhcp-server']
subnet = '192.0.2.0/25'
router = inc_ip(subnet, 1)
class TestServiceDHCPServer(unittest.TestCase):
def setUp(self):
self.session = ConfigSession(os.getpid())
cidr_mask = subnet.split('/')[-1]
self.session.set(['interfaces', 'dummy', 'dum8765', 'address', f'{router}/{cidr_mask}'])
def tearDown(self):
self.session.delete(['interfaces', 'dummy', 'dum8765'])
self.session.delete(base_path)
self.session.commit()
del self.session
- def test_single_pool(self):
+ def test_single_pool_range(self):
shared_net_name = 'SMOKE-1'
dns_1 = inc_ip(subnet, 2)
dns_2 = inc_ip(subnet, 3)
domain_name = 'vyos.net'
range_0_start = inc_ip(subnet, 10)
range_0_stop = inc_ip(subnet, 20)
range_1_start = inc_ip(subnet, 40)
range_1_stop = inc_ip(subnet, 50)
pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
# we use the first subnet IP address as default gateway
self.session.set(pool + ['default-router', router])
self.session.set(pool + ['dns-server', dns_1])
self.session.set(pool + ['dns-server', dns_2])
self.session.set(pool + ['domain-name', domain_name])
# check validate() - No DHCP address range or active static-mapping set
with self.assertRaises(ConfigSessionError):
self.session.commit()
self.session.set(pool + ['range', '0', 'start', range_0_start])
self.session.set(pool + ['range', '0', 'stop', range_0_stop])
self.session.set(pool + ['range', '1', 'start', range_1_start])
self.session.set(pool + ['range', '1', 'stop', range_1_stop])
# commit changes
self.session.commit()
config = read_file(DHCPD_CONF)
network = address_from_cidr(subnet)
netmask = netmask_from_cidr(subnet)
self.assertIn(f'ddns-update-style none;', config)
self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
self.assertIn(f'option domain-name-servers {dns_1}, {dns_2};', config)
self.assertIn(f'option routers {router};', config)
self.assertIn(f'option domain-name "{domain_name}";', config)
self.assertIn(f'default-lease-time 86400;', config)
self.assertIn(f'max-lease-time 86400;', config)
self.assertIn(f'range {range_0_start} {range_0_stop};', config)
self.assertIn(f'range {range_1_start} {range_1_stop};', config)
self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
+ def test_single_pool_static_mapping(self):
+ shared_net_name = 'SMOKE-2'
+
+ dns_1 = inc_ip(subnet, 2)
+ dns_2 = inc_ip(subnet, 3)
+ domain_name = 'vyos.net'
+
+ pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
+ # we use the first subnet IP address as default gateway
+ self.session.set(pool + ['default-router', router])
+ self.session.set(pool + ['dns-server', dns_1])
+ self.session.set(pool + ['dns-server', dns_2])
+ self.session.set(pool + ['domain-name', domain_name])
+
+ # check validate() - No DHCP address range or active static-mapping set
+ with self.assertRaises(ConfigSessionError):
+ self.session.commit()
+
+ client_base = 10
+ for client in ['client1', 'client2', 'client3']:
+ mac = '00:50:00:00:00:{}'.format(client_base)
+ self.session.set(pool + ['static-mapping', client, 'mac-address', mac])
+ self.session.set(pool + ['static-mapping', client, 'ip-address', inc_ip(subnet, client_base)])
+ client_base += 1
+
+ # commit changes
+ self.session.commit()
+
+ config = read_file(DHCPD_CONF)
+ network = address_from_cidr(subnet)
+ netmask = netmask_from_cidr(subnet)
+ self.assertIn(f'ddns-update-style none;', config)
+ self.assertIn(f'subnet {network} netmask {netmask}' + r' {', config)
+ self.assertIn(f'option domain-name-servers {dns_1}, {dns_2};', config)
+ self.assertIn(f'option routers {router};', config)
+ self.assertIn(f'option domain-name "{domain_name}";', config)
+ self.assertIn(f'default-lease-time 86400;', config)
+ self.assertIn(f'max-lease-time 86400;', config)
+
+ client_base = 10
+ for client in ['client1', 'client2', 'client3']:
+ mac = '00:50:00:00:00:{}'.format(client_base)
+ ip = inc_ip(subnet, client_base)
+ self.assertIn(f'host {shared_net_name}_{client}' + ' {', config)
+ self.assertIn(f'fixed-address {ip};', config)
+ self.assertIn(f'hardware ethernet {mac};', config)
+ client_base += 1
+
+ self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+
+ # Check for running process
+ self.assertTrue(process_named_running(PROCESS_NAME))
+
if __name__ == '__main__':
unittest.main()

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 6, 6:25 AM (3 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4646150
Default Alt Text
(14 KB)

Event Timeline