1*9c5db199SXin Li# Lint as: python2, python3 2*9c5db199SXin Li# Copyright 2015 The Chromium OS Authors. All rights reserved. 3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 4*9c5db199SXin Li# found in the LICENSE file. 5*9c5db199SXin Li 6*9c5db199SXin Li""" 7*9c5db199SXin LiEncapsulate functionality of the dhcpd Daemon. Support writing out a 8*9c5db199SXin Liconfiguration file as well as starting and stopping the service. 9*9c5db199SXin Li""" 10*9c5db199SXin Li 11*9c5db199SXin Liimport os 12*9c5db199SXin Liimport signal 13*9c5db199SXin Li 14*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 15*9c5db199SXin Lifrom autotest_lib.client.common_lib import utils 16*9c5db199SXin Li 17*9c5db199SXin Li# Filenames used for execution. 18*9c5db199SXin LiDHCPV6_SERVER_EXECUTABLE = '/usr/local/sbin/dhcpd' 19*9c5db199SXin LiDHCPV6_SERVER_CONFIG_FILE = '/tmp/dhcpv6_test.conf' 20*9c5db199SXin LiDHCPV6_SERVER_PID_FILE = '/tmp/dhcpv6_test.pid' 21*9c5db199SXin Li 22*9c5db199SXin LiDHCPV6_SERVER_ADDRESS = '2001:db8:0:1::1' 23*9c5db199SXin LiDHCPV6_SERVER_SUBNET_PREFIX = '2001:db8:0:1::' 24*9c5db199SXin LiDHCPV6_SERVER_SUBNET_PREFIX_LENGTH = 64 25*9c5db199SXin LiDHCPV6_ADDRESS_RANGE_LOW = 0x100 26*9c5db199SXin LiDHCPV6_ADDRESS_RANGE_HIGH = 0x1ff 27*9c5db199SXin LiDHCPV6_PREFIX_DELEGATION_INDEX_LOW = 0x1 28*9c5db199SXin LiDHCPV6_PREFIX_DELEGATION_INDEX_HIGH = 0xf 29*9c5db199SXin LiDHCPV6_PREFIX_DELEGATION_RANGE_FORMAT = '2001:db8:0:%x00::' 30*9c5db199SXin LiDHCPV6_PREFIX_DELEGATION_RANGE_LOW = (DHCPV6_PREFIX_DELEGATION_RANGE_FORMAT % 31*9c5db199SXin Li (DHCPV6_PREFIX_DELEGATION_INDEX_LOW)) 32*9c5db199SXin LiDHCPV6_PREFIX_DELEGATION_RANGE_HIGH = (DHCPV6_PREFIX_DELEGATION_RANGE_FORMAT % 33*9c5db199SXin Li (DHCPV6_PREFIX_DELEGATION_INDEX_HIGH)) 34*9c5db199SXin LiDHCPV6_PREFIX_DELEGATION_PREFIX_LENGTH = 56 35*9c5db199SXin LiDHCPV6_DEFAULT_LEASE_TIME = 600 36*9c5db199SXin LiDHCPV6_MAX_LEASE_TIME = 7200 37*9c5db199SXin LiDHCPV6_NAME_SERVERS = 'fec0:0:0:1::1' 38*9c5db199SXin LiDHCPV6_DOMAIN_SEARCH = 'domain.example' 39*9c5db199SXin Li 40*9c5db199SXin LiCONFIG_DEFAULT_LEASE_TIME = 'default_lease_time' 41*9c5db199SXin LiCONFIG_MAX_LEASE_TIME = 'max_lease_time' 42*9c5db199SXin LiCONFIG_SUBNET = 'subnet' 43*9c5db199SXin LiCONFIG_RANGE = 'range' 44*9c5db199SXin LiCONFIG_NAME_SERVERS = 'name_servers' 45*9c5db199SXin LiCONFIG_DOMAIN_SEARCH = 'domain_search' 46*9c5db199SXin LiCONFIG_PREFIX_RANGE = 'prefix_range' 47*9c5db199SXin Li 48*9c5db199SXin Liclass Dhcpv6TestServer(object): 49*9c5db199SXin Li """ 50*9c5db199SXin Li This is an embodiment of the DHCPv6 server (dhcpd) process. It converts an 51*9c5db199SXin Li config dict into parameters for the dhcpd configuration file and 52*9c5db199SXin Li manages startup and cleanup of the process. 53*9c5db199SXin Li """ 54*9c5db199SXin Li 55*9c5db199SXin Li def __init__(self, interface = None): 56*9c5db199SXin Li if not os.path.exists(DHCPV6_SERVER_EXECUTABLE): 57*9c5db199SXin Li raise error.TestNAError('Could not find executable %s; ' 58*9c5db199SXin Li 'this is likely an old version of ' 59*9c5db199SXin Li 'ChromiumOS' % 60*9c5db199SXin Li DHCPV6_SERVER_EXECUTABLE) 61*9c5db199SXin Li self._interface = interface 62*9c5db199SXin Li # "2001:db8:0:1::/64" 63*9c5db199SXin Li subnet = '%s/%d' % (DHCPV6_SERVER_SUBNET_PREFIX, 64*9c5db199SXin Li DHCPV6_SERVER_SUBNET_PREFIX_LENGTH) 65*9c5db199SXin Li # "2001:db8:0:1::100 2001:db8:1::1ff" 66*9c5db199SXin Li range = '%s%x %s%x' % (DHCPV6_SERVER_SUBNET_PREFIX, 67*9c5db199SXin Li DHCPV6_ADDRESS_RANGE_LOW, 68*9c5db199SXin Li DHCPV6_SERVER_SUBNET_PREFIX, 69*9c5db199SXin Li DHCPV6_ADDRESS_RANGE_HIGH) 70*9c5db199SXin Li # "2001:db8:0:100:: 2001:db8:1:f00:: /56" 71*9c5db199SXin Li prefix_range = '%s %s /%d' % (DHCPV6_PREFIX_DELEGATION_RANGE_LOW, 72*9c5db199SXin Li DHCPV6_PREFIX_DELEGATION_RANGE_HIGH, 73*9c5db199SXin Li DHCPV6_PREFIX_DELEGATION_PREFIX_LENGTH) 74*9c5db199SXin Li self._config = { 75*9c5db199SXin Li CONFIG_DEFAULT_LEASE_TIME: DHCPV6_DEFAULT_LEASE_TIME, 76*9c5db199SXin Li CONFIG_MAX_LEASE_TIME: DHCPV6_MAX_LEASE_TIME, 77*9c5db199SXin Li CONFIG_SUBNET: subnet, 78*9c5db199SXin Li CONFIG_RANGE: range, 79*9c5db199SXin Li CONFIG_NAME_SERVERS: DHCPV6_NAME_SERVERS, 80*9c5db199SXin Li CONFIG_DOMAIN_SEARCH: DHCPV6_DOMAIN_SEARCH, 81*9c5db199SXin Li CONFIG_PREFIX_RANGE: prefix_range 82*9c5db199SXin Li } 83*9c5db199SXin Li 84*9c5db199SXin Li 85*9c5db199SXin Li def _write_config_file(self): 86*9c5db199SXin Li """ 87*9c5db199SXin Li Write out a configuration file for DHCPv6 server to use. 88*9c5db199SXin Li """ 89*9c5db199SXin Li config = '\n'.join([ 90*9c5db199SXin Li 'default-lease-time %(default_lease_time)d;', 91*9c5db199SXin Li 'max-lease-time %(max_lease_time)d;', 92*9c5db199SXin Li 'subnet6 %(subnet)s {', 93*9c5db199SXin Li ' range6 %(range)s;', 94*9c5db199SXin Li ' option dhcp6.name-servers %(name_servers)s;', 95*9c5db199SXin Li ' option dhcp6.domain-search \"%(domain_search)s\";', 96*9c5db199SXin Li ' prefix6 %(prefix_range)s;', 97*9c5db199SXin Li '}' 98*9c5db199SXin Li '']) % self._config 99*9c5db199SXin Li with open(DHCPV6_SERVER_CONFIG_FILE, 'w') as f: 100*9c5db199SXin Li f.write(config) 101*9c5db199SXin Li 102*9c5db199SXin Li 103*9c5db199SXin Li def _cleanup(self): 104*9c5db199SXin Li """ 105*9c5db199SXin Li Cleanup temporary files. If PID file exists, also kill the 106*9c5db199SXin Li associated process. 107*9c5db199SXin Li """ 108*9c5db199SXin Li if os.path.exists(DHCPV6_SERVER_PID_FILE): 109*9c5db199SXin Li with open(DHCPV6_SERVER_PID_FILE) as rf: 110*9c5db199SXin Li pid = int(rf.read()) 111*9c5db199SXin Li os.remove(DHCPV6_SERVER_PID_FILE) 112*9c5db199SXin Li try: 113*9c5db199SXin Li os.kill(pid, signal.SIGTERM) 114*9c5db199SXin Li except OSError: 115*9c5db199SXin Li pass 116*9c5db199SXin Li if os.path.exists(DHCPV6_SERVER_CONFIG_FILE): 117*9c5db199SXin Li os.remove(DHCPV6_SERVER_CONFIG_FILE) 118*9c5db199SXin Li 119*9c5db199SXin Li 120*9c5db199SXin Li def start(self): 121*9c5db199SXin Li """ 122*9c5db199SXin Li Start the DHCPv6 server. The server will daemonize itself and 123*9c5db199SXin Li run in the background. 124*9c5db199SXin Li """ 125*9c5db199SXin Li self._cleanup() 126*9c5db199SXin Li self._write_config_file() 127*9c5db199SXin Li utils.system('%s -6 -pf %s -cf %s %s' % 128*9c5db199SXin Li (DHCPV6_SERVER_EXECUTABLE, 129*9c5db199SXin Li DHCPV6_SERVER_PID_FILE, 130*9c5db199SXin Li DHCPV6_SERVER_CONFIG_FILE, 131*9c5db199SXin Li self._interface)) 132*9c5db199SXin Li 133*9c5db199SXin Li 134*9c5db199SXin Li def stop(self): 135*9c5db199SXin Li """ 136*9c5db199SXin Li Halt the DHCPv6 server. 137*9c5db199SXin Li """ 138*9c5db199SXin Li self._cleanup() 139