1#   Copyright 2016 - The Android Open Source Project
2#
3#   Licensed under the Apache License, Version 2.0 (the "License");
4#   you may not use this file except in compliance with the License.
5#   You may obtain a copy of the License at
6#
7#       http://www.apache.org/licenses/LICENSE-2.0
8#
9#   Unless required by applicable law or agreed to in writing, software
10#   distributed under the License is distributed on an "AS IS" BASIS,
11#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12#   See the License for the specific language governing permissions and
13#   limitations under the License.
14
15import collections
16import copy
17import ipaddress
18
19
20class Subnet(object):
21    """Configs for a subnet  on the dhcp server.
22
23    Attributes:
24        network: ipaddress.IPv4Network, the network that this subnet is in.
25        start: ipaddress.IPv4Address, the start ip address.
26        end: ipaddress.IPv4Address, the end ip address.
27        router: The router to give to all hosts in this subnet.
28        lease: The lease time of all hosts in this subnet.
29    """
30
31    def __init__(self,
32                 subnet,
33                 start=None,
34                 end=None,
35                 router=None,
36                 lease_time=None):
37        """
38        Args:
39            subnet_address: ipaddress.IPv4Network, The network that this
40                            subnet is.
41            start: ipaddress.IPv4Address, The start of the address range to
42                   give hosts in this subnet. If not given then the first ip in
43                   the network is used.
44            end: ipaddress.IPv4Address, The end of the address range to give
45                 hosts. If not given then the last ip in the network is used.
46            router: ipaddress.IPv4Address, The router hosts should use in this
47                    subnet. If not given the first ip in the network is used.
48            lease_time: int, The amount of lease time in seconds
49                        hosts in this subnet have.
50        """
51        self.network = subnet
52
53        if start:
54            self.start = start
55        else:
56            self.start = self.network[2]
57
58        if not self.start in self.network:
59            raise ValueError('The start range is not in the subnet.')
60        if self.start.is_reserved:
61            raise ValueError('The start of the range cannot be reserved.')
62
63        if end:
64            self.end = end
65        else:
66            self.end = self.network[-2]
67
68        if not self.end in self.network:
69            raise ValueError('The end range is not in the subnet.')
70        if self.end.is_reserved:
71            raise ValueError('The end of the range cannot be reserved.')
72        if self.end < self.start:
73            raise ValueError(
74                'The end must be an address larger than the start.')
75
76        if router:
77            if router >= self.start and router <= self.end:
78                raise ValueError('Router must not be in pool range.')
79            if not router in self.network:
80                raise ValueError('Router must be in the given subnet.')
81
82            self.router = router
83        else:
84            # TODO: Use some more clever logic so that we don't have to search
85            # every host potentially.
86            self.router = None
87            for host in self.network.hosts():
88                if host < self.start or host > self.end:
89                    self.router = host
90                    break
91
92            if not self.router:
93                raise ValueError('No useable host found.')
94
95        self.lease_time = lease_time
96
97
98class StaticMapping(object):
99    """Represents a static dhcp host.
100
101    Attributes:
102        identifier: How id of the host (usually the mac addres
103                    e.g. 00:11:22:33:44:55).
104        address: ipaddress.IPv4Address, The ipv4 address to give the host.
105        lease_time: How long to give a lease to this host.
106    """
107
108    def __init__(self, identifier, address, lease_time=None):
109        self.identifier = identifier
110        self.ipv4_address = address
111        self.lease_time = lease_time
112
113
114class DhcpConfig(object):
115    """The configs for a dhcp server.
116
117    Attributes:
118        subnets: A list of all subnets for the dhcp server to create.
119        static_mappings: A list of static host addresses.
120        default_lease_time: The default time for a lease.
121        max_lease_time: The max time to allow a lease.
122    """
123
124    def __init__(self,
125                 subnets=None,
126                 static_mappings=None,
127                 default_lease_time=600,
128                 max_lease_time=7200):
129        self.subnets = copy.deepcopy(subnets) if subnets else []
130        self.static_mappings = (copy.deepcopy(static_mappings)
131                                if static_mappings else [])
132        self.default_lease_time = default_lease_time
133        self.max_lease_time = max_lease_time
134