-
Notifications
You must be signed in to change notification settings - Fork 1
/
pm_dhcpd.lua
201 lines (169 loc) · 5.6 KB
/
pm_dhcpd.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/usr/bin/env lua
-- -*-lua-*-
--
-- $Id: pm_dhcpd.lua $
--
-- Author: Markus Stenberg <markus [email protected]>
--
-- Copyright (c) 2012 cisco Systems, Inc.
--
-- Created: Thu Nov 8 06:54:56 2012 mstenber
-- Last modified: Mon Sep 30 17:16:25 2013 mstenber
-- Edit time: 14 min
--
require 'pm_handler'
module(..., package.seeall)
local _null=string.char(0)
DHCPD_SCRIPT='/usr/share/hnet/dhcpd_handler.sh'
local _parent = pm_handler.pm_handler_with_pa_dns
pm_dhcpd = _parent:new_subclass{class='pm_dhcpd'}
function pm_dhcpd:run()
local fpath = self.config.dhcpd_conf_filename
local owned4 = self:write_dhcpd_conf(fpath)
local s = string.format('%s 4 %s %s', DHCPD_SCRIPT, tostring(owned4), fpath)
self.shell(s)
-- if we're doing v4 only, don't do anything about v6
if self.config.use_fakedhcpv6d
then
return
end
local fpath = self.config.dhcpd6_conf_filename
local owned6 = self:write_dhcpd6_conf(fpath)
local s = string.format('%s 6 %s %s', DHCPD_SCRIPT, tostring(owned6), fpath)
self.shell(s)
end
function pm_dhcpd:write_dhcpd_conf(fpath)
local owned = 0
self:d('entered write_dhcpd_conf')
local fpath = fpath
local t = mst.array:new{}
local dns = self.ospf_v4_dns or {}
self:dump_address_list_option(t, dns, 'domain-name-servers')
local search = self.ospf_v4_dns_search or {}
self:dump_search_list_option(t, search, 'domain-search')
if #dns == 0
then
t:insert([[
# we don't have good information yet, keep asking!
max-lease-time 30;
]])
end
-- for each locally assigned prefix, if we're the owner (=publisher
-- of asp), run DHCPv4 otherwise not..
handled = mst.set:new{}
for i, lap in ipairs(self.lap)
do
local dep = lap.depracate
local own = lap.owner and not lap.external
-- this is used to prevent more than one subnet per interface
-- (sigh, ISC DHCP limitation #N)
local already_done = handled[lap.ifname]
if not dep and own and not already_done and lap.address
then
local p = ipv6s.ipv6_prefix:new{ascii=lap.prefix}
if p:is_ipv4()
then
handled:insert(lap.ifname)
local myip = mst.string_split(lap.address, '/')[1]
owned = owned + 1
local b = p:get_binary()
local snb = b .. _null
local sn = ipv6s.binary_address_to_address(snb)
local stb = b .. string.char(pa.IPV4_PA_LAST_ROUTER + 1)
local enb = b .. string.char(254)
local st = ipv6s.binary_address_to_address(stb)
local en = ipv6s.binary_address_to_address(enb)
t:insert('subnet ' .. sn .. ' netmask 255.255.255.0 {')
t:insert(' range ' .. st .. ' ' .. en .. ';')
t:insert(' option routers ' .. myip .. ';')
t:insert('}')
end
end
end
self:write_to_file(fpath, t, '# ')
return owned
end
function pm_dhcpd:write_dhcpd6_conf(fpath)
local owned = 0
self:d('entered write_dhcpd6_conf')
local t = mst.array:new{}
t:insert([[
# dhcpd6.conf
# automatically generated by pm_core.lua
]])
local dns = self.ospf_dns or {}
self:dump_address_list_option(t, dns, 'dhcp6.name-servers')
local search = self.ospf_dns_search or {}
self:dump_search_list_option(t, search, 'dhcp6.domain-search')
-- for each locally assigned prefix, if we're the owner (=publisher
-- of asp), run DHCPv6, otherwise not..
handled = mst.set:new{}
for i, lap in ipairs(self.lap)
do
self:a(not lap[elsa_pa.PREFIX_CLASS_KEY],
'prefix classes not supported in ISC DHCPv6d yet')
local dep = lap.depracate
local own = lap.owner and not lap.external
-- this is used to prevent more than one subnet per interface
-- (sigh, ISC DHCP limitation #N)
local already_done = handled[lap.ifname]
if not dep and own and not already_done
then
local p = ipv6s.ipv6_prefix:new{ascii=lap.prefix}
if not p:is_ipv4()
then
handled:insert(lap.ifname)
owned = owned + 1
local b = p:get_binary()
local stb = b .. string.rep(_null, 7) .. string.char(42)
local enb = b .. string.rep(_null, 7) .. string.char(123)
local st = ipv6s.binary_address_to_address(stb)
local en = ipv6s.binary_address_to_address(enb)
t:insert('subnet6 ' .. lap.prefix .. ' {')
t:insert(' range6 ' .. st .. ' ' .. en .. ';')
t:insert('}')
end
end
end
self:write_to_file(fpath, t, '# ')
return owned
end
function pm_dhcpd:dump_address_list_option(t, l, option_name)
if #l == 0
then
return
end
l = mst.array_filter(l, function (v)
return #mst.string_strip(v) > 0
end)
local s = table.concat(l,",")
-- if we have multiple ones from e.g. shell, separator may be
-- space too
s = string.gsub(s, ' ', ',')
t:insert('option ' .. option_name .. ' ' .. s .. ';')
end
function pm_dhcpd:dump_search_list_option(t, l, option_name)
if #l == 0
then
return
end
local r = mst.array:new{}
for i, v0 in ipairs(l)
do
for i, v in ipairs(mst.string_split(v0, ' '))
do
v = mst.string_strip(v)
if #v > 0
then
r:insert(mst.repr(v))
end
end
end
-- may also skip if results were just whitespaces or something
if #r == 0
then
return
end
local s = table.concat(r, ",")
t:insert('option ' .. option_name .. ' ' .. s .. ';')
end