summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/dhcp-client/daemon-options.tmpl1
-rw-r--r--data/templates/dhcp-client/ipv4.tmpl2
-rw-r--r--data/templates/dhcp-client/ipv6.tmpl2
-rw-r--r--python/vyos/ifconfig/dhcp.py130
-rw-r--r--src/systemd/dhclient6@.service18
-rw-r--r--src/systemd/dhclient@.service19
6 files changed, 77 insertions, 95 deletions
diff --git a/data/templates/dhcp-client/daemon-options.tmpl b/data/templates/dhcp-client/daemon-options.tmpl
new file mode 100644
index 000000000..b5a10c3b8
--- /dev/null
+++ b/data/templates/dhcp-client/daemon-options.tmpl
@@ -0,0 +1 @@
+DHCLIENT_OPTS="-nw -cf {{ conf_file }} -pf {{ pid_file }} -lf {{ lease_file }} {{ '-S' if dhcpv6_prm_only }} {{ '-T' if dhcpv6_temporary }} {{ ifname }}"
diff --git a/data/templates/dhcp-client/ipv4.tmpl b/data/templates/dhcp-client/ipv4.tmpl
index 43f273077..ab772b5f6 100644
--- a/data/templates/dhcp-client/ipv4.tmpl
+++ b/data/templates/dhcp-client/ipv4.tmpl
@@ -1,4 +1,4 @@
-# generated by ifconfig.py
+# generated by dhcp.py
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
timeout 60;
retry 300;
diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl
index 83db40c5f..be0235add 100644
--- a/data/templates/dhcp-client/ipv6.tmpl
+++ b/data/templates/dhcp-client/ipv6.tmpl
@@ -1,4 +1,4 @@
-# generated by ifconfig.py
+# generated by dhcp.py
interface "{{ ifname }}" {
request routers, domain-name-servers, domain-name;
}
diff --git a/python/vyos/ifconfig/dhcp.py b/python/vyos/ifconfig/dhcp.py
index 3122147a3..d3e75c292 100644
--- a/python/vyos/ifconfig/dhcp.py
+++ b/python/vyos/ifconfig/dhcp.py
@@ -20,27 +20,19 @@ from vyos.ifconfig.control import Control
from vyos.template import render
-class _DHCP (Control):
- client_base = r'/var/lib/dhcp/dhclient_'
-
- def __init__(self, ifname, version, **kargs):
- super().__init__(**kargs)
- self.version = version
- self.file = {
- 'ifname': ifname,
- 'conf': self.client_base + ifname + '.' + version + 'conf',
- 'pid': self.client_base + ifname + '.' + version + 'pid',
- 'lease': self.client_base + ifname + '.' + version + 'leases',
- }
-
-class _DHCPv4 (_DHCP):
+class _DHCPv4 (Control):
def __init__(self, ifname):
- super().__init__(ifname, '')
+ super().__init__()
+ config_base = r'/run/dhclient'
self.options = FixedDict(**{
'ifname': ifname,
'hostname': '',
'client_id': '',
- 'vendor_class_id': ''
+ 'vendor_class_id': '',
+ 'conf_file': config_base + f'/{ifname}.conf',
+ 'options_file': config_base + f'/{ifname}.options',
+ 'pid_file': config_base + f'/{ifname}.pid',
+ 'lease_file': config_base + f'/{ifname}.leases',
})
# replace dhcpv4/v6 with systemd.networkd?
@@ -55,25 +47,16 @@ class _DHCPv4 (_DHCP):
>>> j = Interface('eth0')
>>> j.dhcp.v4.set()
"""
-
if not self.options['hostname']:
# read configured system hostname.
# maybe change to vyos hostd client ???
with open('/etc/hostname', 'r') as f:
self.options['hostname'] = f.read().rstrip('\n')
- render(self.file['conf'], 'dhcp-client/ipv4.tmpl' ,self.options)
+ render(self.options['options_file'], 'dhcp-client/daemon-options.tmpl', self.options)
+ render(self.options['conf_file'], 'dhcp-client/ipv4.tmpl', self.options)
- cmd = 'start-stop-daemon'
- cmd += ' --start'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile {pid}'
- cmd += ' --exec /sbin/dhclient'
- cmd += ' --'
- # now pass arguments to dhclient binary
- cmd += ' -4 -nw -cf {conf} -pf {pid} -lf {lease} {ifname}'
- return self._cmd(cmd.format(**self.file))
+ return self._cmd('systemctl restart dhclient@{ifname}.service'.format(**self.options))
def delete(self):
"""
@@ -86,44 +69,30 @@ class _DHCPv4 (_DHCP):
>>> j = Interface('eth0')
>>> j.dhcp.v4.delete()
"""
- if not os.path.isfile(self.file['pid']):
+ if not os.path.isfile(self.options['pid_file']):
self._debug_msg('No DHCP client PID found')
return None
- # with open(self.file['pid'], 'r') as f:
- # pid = int(f.read())
-
- # stop dhclient, we need to call dhclient and tell it should release the
- # aquired IP address. tcpdump tells me:
- # 172.16.35.103.68 > 172.16.35.254.67: [bad udp cksum 0xa0cb -> 0xb943!] BOOTP/DHCP, Request from 00:50:56:9d:11:df, length 300, xid 0x620e6946, Flags [none] (0x0000)
- # Client-IP 172.16.35.103
- # Client-Ethernet-Address 00:50:56:9d:11:df
- # Vendor-rfc1048 Extensions
- # Magic Cookie 0x63825363
- # DHCP-Message Option 53, length 1: Release
- # Server-ID Option 54, length 4: 172.16.35.254
- # Hostname Option 12, length 10: "vyos"
- #
- cmd = '/sbin/dhclient -cf {conf} -pf {pid} -lf {lease} -r {ifname}'
- self._cmd(cmd.format(**self.file))
+ self._cmd('systemctl stop dhclient@{ifname}.service'.format(**self.options))
# cleanup old config files
- for name in ('conf', 'pid', 'lease'):
- if os.path.isfile(self.file[name]):
- os.remove(self.file[name])
+ for name in ('conf_file', 'options_file', 'pid_file', 'lease_file'):
+ if os.path.isfile(self.options[name]):
+ os.remove(self.options[name])
-
-class _DHCPv6 (_DHCP):
+class _DHCPv6 (Control):
def __init__(self, ifname):
- super().__init__(ifname, 'v6')
+ super().__init__()
+ config_base = r'/run/dhclient6'
self.options = FixedDict(**{
'ifname': ifname,
+ 'conf_file': config_base + f'/{ifname}.conf',
+ 'options_file': config_base + f'/{ifname}.options',
+ 'pid_file': config_base + f'/{ifname}.pid',
+ 'lease_file': config_base + f'/{ifname}.leases',
'dhcpv6_prm_only': False,
'dhcpv6_temporary': False,
})
- self.file.update({
- 'accept_ra': f'/proc/sys/net/ipv6/conf/{ifname}/accept_ra',
- })
def set(self):
"""
@@ -134,7 +103,7 @@ class _DHCPv6 (_DHCP):
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
- >>> j.set_dhcpv6()
+ >>> j.dhcp.v6.set()
"""
# better save then sorry .. should be checked in interface script
@@ -143,29 +112,13 @@ class _DHCPv6 (_DHCP):
raise Exception(
'DHCPv6 temporary and parameters-only options are mutually exclusive!')
- render(self.file['conf'], 'dhcp-client/ipv6.tmpl', self.options)
+ render(self.options['options_file'], 'dhcp-client/daemon-options.tmpl', self.options)
+ render(self.options['conf_file'], 'dhcp-client/ipv6.tmpl', self.options)
# no longer accept router announcements on this interface
- self._write_sysfs(self.file['accept_ra'], 0)
-
- # assemble command-line to start DHCPv6 client (dhclient)
- cmd = 'start-stop-daemon'
- cmd += ' --start'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile {pid}'
- cmd += ' --exec /sbin/dhclient'
- cmd += ' --'
- # now pass arguments to dhclient binary
- cmd += ' -6 -nw -cf {conf} -pf {pid} -lf {lease}'
- # add optional arguments
- if self.options['dhcpv6_prm_only']:
- cmd += ' -S'
- if self.options['dhcpv6_temporary']:
- cmd += ' -T'
- cmd += ' {ifname}'
-
- return self._cmd(cmd.format(**self.file))
+ self._write_sysfs('/proc/sys/net/ipv6/conf/{ifname}/accept_ra'.format(**self.options), 0)
+
+ return self._cmd('systemctl restart dhclient6@{ifname}.service'.format(**self.options))
def delete(self):
"""
@@ -176,33 +129,24 @@ class _DHCPv6 (_DHCP):
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
- >>> j.del_dhcpv6()
+ >>> j.dhcp.v6.delete()
"""
- if not os.path.isfile(self.file['pid']):
+ if not os.path.isfile(self.options['pid_file']):
self._debug_msg('No DHCPv6 client PID found')
return None
- # with open(self.file['pid'], 'r') as f:
- # pid = int(f.read())
-
- # stop dhclient
- cmd = 'start-stop-daemon'
- cmd += ' --stop'
- cmd += ' --oknodo'
- cmd += ' --quiet'
- cmd += ' --pidfile {pid}'
- self._cmd(cmd.format(**self.file))
+ self._cmd('systemctl stop dhclient6@{ifname}.service'.format(**self.options))
# accept router announcements on this interface
- self._write_sysfs(self.file['accept_ra'], 1)
+ self._write_sysfs('/proc/sys/net/ipv6/conf/{ifname}/accept_ra'.format(**self.options), 1)
# cleanup old config files
- for name in ('conf', 'pid', 'lease'):
- if os.path.isfile(self.file[name]):
- os.remove(self.file[name])
+ for name in ('conf_file', 'options_file', 'pid_file', 'lease_file'):
+ if os.path.isfile(self.options[name]):
+ os.remove(self.options[name])
-class DHCP (object):
+class DHCP(object):
def __init__(self, ifname):
self.v4 = _DHCPv4(ifname)
self.v6 = _DHCPv6(ifname)
diff --git a/src/systemd/dhclient6@.service b/src/systemd/dhclient6@.service
new file mode 100644
index 000000000..d871e7354
--- /dev/null
+++ b/src/systemd/dhclient6@.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=DHCPv6 client on %i
+Documentation=man:dhclient(8)
+RequiresMountsFor=/run
+ConditionPathExists=/run/dhclient6/%i.conf
+ConditionPathExists=/run/dhclient6/%i.options
+After=vyos-router.service
+
+[Service]
+WorkingDirectory=/run/dhclient6
+Type=exec
+EnvironmentFile=-/run/dhclient6/%i.options
+PIDFile=/run/dhclient6/%i.pid
+ExecStart=/sbin/dhclient -6 $DHCLIENT_OPTS
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/src/systemd/dhclient@.service b/src/systemd/dhclient@.service
new file mode 100644
index 000000000..1040ce2b2
--- /dev/null
+++ b/src/systemd/dhclient@.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=DHCP client on %i
+Documentation=man:dhclient(8)
+RequiresMountsFor=/run
+ConditionPathExists=/run/dhclient/%i.conf
+ConditionPathExists=/run/dhclient/%i.options
+After=vyos-router.service
+
+[Service]
+WorkingDirectory=/run/dhclient
+Type=exec
+EnvironmentFile=-/run/dhclient/%i.options
+PIDFile=/run/dhclient/%i.pid
+ExecStart=/sbin/dhclient -4 $DHCLIENT_OPTS
+ExecStop=/sbin/dhclient -4 $DHCLIENT_OPTS -r
+Restart=always
+
+[Install]
+WantedBy=multi-user.target