Project

General

Profile

Download (50.3 KB) Statistics
| Branch: | Tag: | Revision:
1 99caa67c Seth Mos
<?php
2
/*
3 c5d81585 Renato Botelho
 * services_dhcpv6.php
4 df6cb8fe Stephen Beaver
 *
5 c5d81585 Renato Botelho
 * part of pfSense (https://www.pfsense.org)
6 38809d47 Renato Botelho do Couto
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8 402c98a2 Reid Linnemann
 * Copyright (c) 2014-2023 Rubicon Communications, LLC (Netgate)
9 c5d81585 Renato Botelho
 * Copyright (c) 2010 Seth Mos <seth.mos@dds.nl>
10
 * All rights reserved.
11 191cb31d Stephen Beaver
 *
12 c5d81585 Renato Botelho
 * originally based on m0n0wall (http://m0n0.ch/wall)
13
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
14
 * All rights reserved.
15 df6cb8fe Stephen Beaver
 *
16 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
17
 * you may not use this file except in compliance with the License.
18
 * You may obtain a copy of the License at
19 df6cb8fe Stephen Beaver
 *
20 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
21 df6cb8fe Stephen Beaver
 *
22 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
23
 * distributed under the License is distributed on an "AS IS" BASIS,
24
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
 * See the License for the specific language governing permissions and
26
 * limitations under the License.
27 df6cb8fe Stephen Beaver
 */
28 99caa67c Seth Mos
29
##|+PRIV
30
##|*IDENT=page-services-dhcpv6server
31 48157a04 Phil Davis
##|*NAME=Services: DHCPv6 Server
32
##|*DESCR=Allow access to the 'Services: DHCPv6 Server' page.
33 99caa67c Seth Mos
##|*MATCH=services_dhcpv6.php*
34
##|-PRIV
35
36 9bd56e9d Christian McDonald
require_once('guiconfig.inc');
37
require_once('filter.inc');
38 99caa67c Seth Mos
39 8f36f87a jim-p
function dhcpv6_apply_changes($dhcpdv6_enable_changed) {
40 a433a061 Marcos Mendoza
	global $g;
41 8f36f87a jim-p
	$retval = 0;
42
	$retvaldhcp = 0;
43
	$retvaldns = 0;
44 9bd56e9d Christian McDonald
	if (dhcp_is_backend('isc')) {
45
		/* Stop DHCPv6 so we can cleanup leases */
46
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
47
	}
48 8f36f87a jim-p
	// dhcp_clean_leases();
49
	/* dnsmasq_configure calls dhcpd_configure */
50
	/* no need to restart dhcpd twice */
51 0d121100 jim-p
	if (config_path_enabled('dnsmasq') &&
52
	    config_path_enabled('dnsmasq', 'regdhcpstatic')) {
53 44c42356 Phil Davis
		$retvaldns |= services_dnsmasq_configure();
54 8f36f87a jim-p
		if ($retvaldns == 0) {
55
			clear_subsystem_dirty('hosts');
56 9bd56e9d Christian McDonald
			clear_subsystem_dirty('dhcpd6');
57 8f36f87a jim-p
		}
58 0d121100 jim-p
	} elseif (config_path_enabled('unbound') &&
59
		  config_path_enabled('unbound', 'regdhcpstatic')) {
60 44c42356 Phil Davis
		$retvaldns |= services_unbound_configure();
61 8f36f87a jim-p
		if ($retvaldns == 0) {
62
			clear_subsystem_dirty('unbound');
63 9bd56e9d Christian McDonald
			clear_subsystem_dirty('dhcpd6');
64 8f36f87a jim-p
		}
65
	} else {
66 44c42356 Phil Davis
		$retvaldhcp |= services_dhcpd_configure();
67 8f36f87a jim-p
		if ($retvaldhcp == 0) {
68 9bd56e9d Christian McDonald
			clear_subsystem_dirty('dhcpd6');
69 8f36f87a jim-p
		}
70
	}
71 c3fb0119 doktornotor
	/* BIND package - Bug #3710 */
72
	if (!function_exists('is_package_installed')) {
73
		require_once('pkg-utils.inc');
74
	}
75 0d121100 jim-p
	if (is_package_installed('pfSense-pkg-bind') &&
76
	    config_path_enabled('installedpackages/bind/config/0', 'enable_bind')) {
77 c3fb0119 doktornotor
		$reloadbind = false;
78 0d121100 jim-p
		$bindzone = config_get_path('installedpackages/bindzone/config', []);
79
80 c3fb0119 doktornotor
		for ($x = 0; $x < sizeof($bindzone); $x++) {
81 6cc58ae8 doktornotor
			$zone = $bindzone[$x];
82 c3fb0119 doktornotor
			if ($zone['regdhcpstatic'] == 'on') {
83
				$reloadbind = true;
84
				break;
85
			}
86
		}
87
		if ($reloadbind === true) {
88
			if (file_exists("/usr/local/pkg/bind.inc")) {
89
				require_once("/usr/local/pkg/bind.inc");
90
				bind_sync();
91
			}
92
		}
93
	}
94 8f36f87a jim-p
	if ($dhcpdv6_enable_changed) {
95 44c42356 Phil Davis
		$retvalfc |= filter_configure();
96 8f36f87a jim-p
	}
97
	if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) {
98
		$retval = 1;
99
	}
100 44c42356 Phil Davis
	return $retval;
101 8f36f87a jim-p
}
102
103 2568e151 Christian McDonald
if (!g_get('services_dhcp_server_enable')) {
104 6f3d2063 Renato Botelho
	header("Location: /");
105 99caa67c Seth Mos
	exit;
106
}
107
108 c946d721 Steve Beaver
$if = $_REQUEST['if'];
109 99caa67c Seth Mos
$iflist = get_configured_interface_with_descr();
110 16d9ad13 smos
$iflist = array_merge($iflist, get_configured_pppoe_server_interfaces());
111 99caa67c Seth Mos
112
/* set the starting interface */
113
if (!$if || !isset($iflist[$if])) {
114
	foreach ($iflist as $ifent => $ifname) {
115 0d121100 jim-p
		$ifaddr = config_get_path("interfaces/{$ifent}/ipaddrv6");
116
117
		if (!config_path_enabled("dhcpdv6/{$ifent}") &&
118
		    !(($ifaddr == 'track6') ||
119
		    (is_ipaddrv6($ifaddr) &&
120
		    !is_linklocal($ifaddr)))) {
121 99caa67c Seth Mos
			continue;
122 8f8682f7 Phil Davis
		}
123 99caa67c Seth Mos
		$if = $ifent;
124
		break;
125
	}
126
}
127
128 9bd56e9d Christian McDonald
$act = $_REQUEST['act'];
129
130
$a_pools = [];
131
132 0d121100 jim-p
if (!empty(config_get_path("dhcpdv6/{$if}"))) {
133 9bd56e9d Christian McDonald
	$pool = $_REQUEST['pool'];
134
	if (is_numeric($_POST['pool'])) {
135
		$pool = $_POST['pool'];
136 99caa67c Seth Mos
	}
137 9bd56e9d Christian McDonald
138
	if (is_numeric($pool) && empty($if)) {
139
		header('Location: services_dhcpv6.php');
140
		exit;
141 829322b3 Christian McDonald
	}
142 9bd56e9d Christian McDonald
143
	init_config_arr(['dhcpdv6', $if, 'pool']);
144
	$a_pools = &$config['dhcpdv6'][$if]['pool'];
145
146
	if (is_numeric($pool) && $a_pools[$pool]) {
147
		$dhcpdconf = &$a_pools[$pool];
148
	} elseif ($act === 'newpool') {
149
		$dhcpdconf = [];
150
	} else {
151
		$dhcpdconf = &$config['dhcpdv6'][$if];
152 8f8682f7 Phil Davis
	}
153 9bd56e9d Christian McDonald
154
	init_config_arr(['dhcpdv6', $if, 'staticmap']);
155 99caa67c Seth Mos
	$a_maps = &$config['dhcpdv6'][$if]['staticmap'];
156
}
157
158 9bd56e9d Christian McDonald
if (is_array($dhcpdconf)) {
159
	if (!is_numeric($pool) && !($act === 'newpool')) {
160
		$pconfig['enable'] = isset($dhcpdconf['enable']);
161
	} else {
162
		$pconfig['descr'] = $dhcpdconf['descr'];
163
	}
164
165
	/* DHCPv6 */
166
	if (is_array($dhcpdconf['range'])) {
167
		$pconfig['range_from'] = $dhcpdconf['range']['from'];
168
		$pconfig['range_to'] = $dhcpdconf['range']['to'];
169
	}
170
171
	if (is_array($dhcpdconf['prefixrange'])) {
172
		$pconfig['prefixrange_from'] = $dhcpdconf['prefixrange']['from'];
173
		$pconfig['prefixrange_to'] = $dhcpdconf['prefixrange']['to'];
174
		$pconfig['prefixrange_length'] = $dhcpdconf['prefixrange']['prefixlength'];
175
	}
176
177
	$pconfig['deftime'] = $dhcpdconf['defaultleasetime'];
178
	$pconfig['maxtime'] = $dhcpdconf['maxleasetime'];
179
	$pconfig['domain'] = $dhcpdconf['domain'];
180
	$pconfig['domainsearchlist'] = $dhcpdconf['domainsearchlist'];
181
	list($pconfig['dns1'], $pconfig['dns2'], $pconfig['dns3'], $pconfig['dns4']) = $dhcpdconf['dnsserver'];
182
	$pconfig['dhcp6c-dns'] = ($dhcpdconf['dhcp6c-dns'] !== 'disabled' ? 'enabled' : 'disabled');
183
	if (isset($dhcpdconf['denyunknown'])) {
184
		$pconfig['denyunknown'] = empty($dhcpdconf['denyunknown']) ? "enabled" : $dhcpdconf['denyunknown'];
185
	} else {
186
		$pconfig['denyunknown'] = "disabled";
187
	}
188
	$pconfig['ddnsdomain'] = $dhcpdconf['ddnsdomain'];
189
	$pconfig['ddnsdomainprimary'] = $dhcpdconf['ddnsdomainprimary'];
190
	$pconfig['ddnsdomainprimaryport'] = $dhcpdconf['ddnsdomainprimaryport'];
191
	$pconfig['ddnsdomainsecondary'] = $dhcpdconf['ddnsdomainsecondary'];
192
	$pconfig['ddnsdomainsecondaryport'] = $dhcpdconf['ddnsdomainsecondaryport'];
193
	$pconfig['ddnsdomainkeyname'] = $dhcpdconf['ddnsdomainkeyname'];
194
	$pconfig['ddnsdomainkeyalgorithm'] = $dhcpdconf['ddnsdomainkeyalgorithm'];
195
	$pconfig['ddnsdomainkey'] = $dhcpdconf['ddnsdomainkey'];
196
	$pconfig['ddnsupdate'] = isset($dhcpdconf['ddnsupdate']);
197
	$pconfig['ddnsforcehostname'] = isset($dhcpdconf['ddnsforcehostname']);
198
	$pconfig['ddnsclientupdates'] = $dhcpdconf['ddnsclientupdates'];
199
	list($pconfig['ntp1'], $pconfig['ntp2'], $pconfig['ntp3'], $pconfig['ntp4']) = $dhcpdconf['ntpserver'];
200
	$pconfig['tftp'] = $dhcpdconf['tftp'];
201
	$pconfig['ldap'] = $dhcpdconf['ldap'];
202
	$pconfig['netboot'] = isset($dhcpdconf['netboot']);
203
	$pconfig['bootfile_url'] = $dhcpdconf['bootfile_url'];
204
	$pconfig['netmask'] = $dhcpdconf['netmask'];
205
	$pconfig['numberoptions'] = $dhcpdconf['numberoptions'];
206
	$pconfig['dhcpv6leaseinlocaltime'] = $dhcpdconf['dhcpv6leaseinlocaltime'];
207
}
208
209 0d121100 jim-p
if (config_get_path("interfaces/{$if}/ipaddrv6") == 'track6') {
210
	$trackifname = config_get_path("interfaces/{$if}/track6-interface");
211
	$trackcfg = config_get_path("interfaces/{$trackifname}");
212 a5776226 Chris Buechler
	$ifcfgsn = "64";
213 2bf455ca Renato Botelho
	$ifcfgip = '::';
214 6c8beed3 Renato Botelho
215
	$str_help_mask = dhcpv6_pd_str_help($ifcfgsn);
216 2bf455ca Renato Botelho
} else {
217
	$ifcfgip = get_interface_ipv6($if);
218
	$ifcfgsn = get_interface_subnetv6($if);
219
}
220 99caa67c Seth Mos
221 cd2c7940 sbeaver
/*	 set the enabled flag which will tell us if DHCP relay is enabled
222
 *	 on any interface. We will use this to disable DHCP server since
223
 *	 the two are not compatible with each other.
224 99caa67c Seth Mos
 */
225
226
$dhcrelay_enabled = false;
227 1e45d13f Christian McDonald
$dhcrelaycfg = config_get_path('dhcrelay6');
228 99caa67c Seth Mos
229 9c06758b k-paulius
if (is_array($dhcrelaycfg) && isset($dhcrelaycfg['enable']) && isset($dhcrelaycfg['interface']) && !empty($dhcrelaycfg['interface'])) {
230
	$dhcrelayifs = explode(",", $dhcrelaycfg['interface']);
231
232
	foreach ($dhcrelayifs as $dhcrelayif) {
233
234
		if (isset($iflist[$dhcrelayif]) && (!link_interface_to_bridge($dhcrelayif))) {
235 99caa67c Seth Mos
			$dhcrelay_enabled = true;
236 9c06758b k-paulius
			break;
237 8f8682f7 Phil Davis
		}
238 99caa67c Seth Mos
	}
239
}
240
241 306cbbc8 Phil Davis
if (isset($_POST['apply'])) {
242 44c42356 Phil Davis
	$changes_applied = true;
243
	$retval = dhcpv6_apply_changes(false);
244 306cbbc8 Phil Davis
} elseif (isset($_POST['save'])) {
245 9bd56e9d Christian McDonald
246 99caa67c Seth Mos
	unset($input_errors);
247
248 472ad9a0 Renato Botelho
	$old_dhcpdv6_enable = ($pconfig['enable'] == true);
249
	$new_dhcpdv6_enable = ($_POST['enable'] ? true : false);
250
	$dhcpdv6_enable_changed = ($old_dhcpdv6_enable != $new_dhcpdv6_enable);
251
252 99caa67c Seth Mos
	$pconfig = $_POST;
253
254
	$numberoptions = array();
255 6c07db48 Phil Davis
	for ($x = 0; $x < 99; $x++) {
256 28e2b611 jim-p
		if (isset($_POST["number{$x}"]) && ctype_digit(strval($_POST["number{$x}"]))) {
257 99caa67c Seth Mos
			$numbervalue = array();
258
			$numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]);
259 65cce9d7 Renato Botelho
			$numbervalue['value'] = base64_encode($_POST["value{$x}"]);
260 99caa67c Seth Mos
			$numberoptions['item'][] = $numbervalue;
261
		}
262
	}
263 756da4bd Phil Davis
	// Reload the new pconfig variable that the form uses.
264 99caa67c Seth Mos
	$pconfig['numberoptions'] = $numberoptions;
265
266
	/* input validation */
267 756da4bd Phil Davis
268
	// Note: if DHCPv6 Server is not enabled, then it is OK to adjust other parameters without specifying range from-to.
269 9bd56e9d Christian McDonald
	if ($_POST['enable'] || is_numeric($pool) || ($act === 'newpool')) {
270 5c533d72 Viktor G
		if ((empty($_POST['range_from']) || empty($_POST['range_to'])) &&
271 a433a061 Marcos Mendoza
		    (config_get_path("dhcpdv6/{$if}/ramode") != 'stateless_dhcp')) {
272 9bd56e9d Christian McDonald
			$input_errors[] = gettext('A valid range must be specified for any Router Advertisement mode except "Stateless DHCP."');
273 5c533d72 Viktor G
		}
274 756da4bd Phil Davis
	}
275 99caa67c Seth Mos
276 756da4bd Phil Davis
	if (($_POST['prefixrange_from'] && !is_ipaddrv6($_POST['prefixrange_from']))) {
277
		$input_errors[] = gettext("A valid prefix range must be specified.");
278
	}
279
	if (($_POST['prefixrange_to'] && !is_ipaddrv6($_POST['prefixrange_to']))) {
280
		$input_errors[] = gettext("A valid prefix range must be specified.");
281
	}
282 bcc2b417 Renato Botelho
283 756da4bd Phil Davis
	if ($_POST['prefixrange_from'] && $_POST['prefixrange_to'] &&
284
		$_POST['prefixrange_length']) {
285
		$netmask = Net_IPv6::getNetmask($_POST['prefixrange_from'],
286
			$_POST['prefixrange_length']);
287 587995fb Phil Davis
		$netmask = text_to_compressed_ip6($netmask);
288 756da4bd Phil Davis
289 587995fb Phil Davis
		if ($netmask != text_to_compressed_ip6(strtolower(
290 756da4bd Phil Davis
			$_POST['prefixrange_from']))) {
291
			$input_errors[] = sprintf(gettext(
292
				"Prefix Delegation From address is not a valid IPv6 Netmask for %s"),
293
				$netmask . '/' . $_POST['prefixrange_length']);
294
		}
295 bcc2b417 Renato Botelho
296 756da4bd Phil Davis
		$netmask = Net_IPv6::getNetmask($_POST['prefixrange_to'],
297
			$_POST['prefixrange_length']);
298 587995fb Phil Davis
		$netmask = text_to_compressed_ip6($netmask);
299 bcc2b417 Renato Botelho
300 587995fb Phil Davis
		if ($netmask != text_to_compressed_ip6(strtolower(
301 756da4bd Phil Davis
			$_POST['prefixrange_to']))) {
302
			$input_errors[] = sprintf(gettext(
303
				"Prefix Delegation To address is not a valid IPv6 Netmask for %s"),
304
				$netmask . '/' . $_POST['prefixrange_length']);
305 bcc2b417 Renato Botelho
		}
306 756da4bd Phil Davis
	}
307 bcc2b417 Renato Botelho
308 756da4bd Phil Davis
	$range_from_to_ok = true;
309
310
	if ($_POST['range_from']) {
311
		if (!is_ipaddrv6($_POST['range_from'])) {
312
			$input_errors[] = gettext("A valid range must be specified.");
313
			$range_from_to_ok = false;
314 a433a061 Marcos Mendoza
		} elseif (config_get_path("interfaces/{$if}/ipaddrv6") == 'track6' &&
315 756da4bd Phil Davis
			!Net_IPv6::isInNetmask($_POST['range_from'], '::', $ifcfgsn)) {
316
			$input_errors[] = sprintf(gettext(
317 702fa4d0 Phil Davis
				'The prefix (upper %1$s bits) must be zero.  Use the form %2$s'),
318 756da4bd Phil Davis
				$ifcfgsn, $str_help_mask);
319
			$range_from_to_ok = false;
320 8f8682f7 Phil Davis
		}
321 756da4bd Phil Davis
	}
322
	if ($_POST['range_to']) {
323
		if (!is_ipaddrv6($_POST['range_to'])) {
324
			$input_errors[] = gettext("A valid range must be specified.");
325
			$range_from_to_ok = false;
326 a433a061 Marcos Mendoza
		} elseif (config_get_path("interfaces/{$if}/ipaddrv6") == 'track6' &&
327 756da4bd Phil Davis
			!Net_IPv6::isInNetmask($_POST['range_to'], '::', $ifcfgsn)) {
328
			$input_errors[] = sprintf(gettext(
329 702fa4d0 Phil Davis
				'The prefix (upper %1$s bits) must be zero.  Use the form %2$s'),
330 756da4bd Phil Davis
				$ifcfgsn, $str_help_mask);
331
			$range_from_to_ok = false;
332 8f8682f7 Phil Davis
		}
333 756da4bd Phil Davis
	}
334
	if (($_POST['range_from'] && !$_POST['range_to']) || ($_POST['range_to'] && !$_POST['range_from'])) {
335
		$input_errors[] = gettext("Range From and Range To must both be entered.");
336
	}
337
	if (($_POST['gateway'] && !is_ipaddrv6($_POST['gateway']))) {
338
		$input_errors[] = gettext("A valid IPv6 address must be specified for the gateway.");
339
	}
340
	if (($_POST['dns1'] && !is_ipaddrv6($_POST['dns1'])) ||
341
		($_POST['dns2'] && !is_ipaddrv6($_POST['dns2'])) ||
342
		($_POST['dns3'] && !is_ipaddrv6($_POST['dns3'])) ||
343
		($_POST['dns4'] && !is_ipaddrv6($_POST['dns4']))) {
344
		$input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers.");
345
	}
346 99caa67c Seth Mos
347 756da4bd Phil Davis
	if ($_POST['deftime'] && (!is_numeric($_POST['deftime']) || ($_POST['deftime'] < 60))) {
348
		$input_errors[] = gettext("The default lease time must be at least 60 seconds.");
349
	}
350 635e5b9d Kris Anderson
	if ($_POST['maxtime'] && (!is_numeric($_POST['maxtime']) || ($_POST['maxtime'] < 60) || ($_POST['maxtime'] < $_POST['deftime']))) {
351 ef267412 Kris Anderson
		$input_errors[] = gettext("The maximum lease time must be at least 60 seconds, and the same value or greater than the default lease time.");
352 756da4bd Phil Davis
	}
353 9fbd8f71 Viktor Gurov
	if ($_POST['ddnsupdate']) {
354
		if (!is_domain($_POST['ddnsdomain'])) {
355
			$input_errors[] = gettext("A valid domain name must be specified for the dynamic DNS registration.");
356
		}
357
		if (!is_ipaddr($_POST['ddnsdomainprimary'])) {
358
			$input_errors[] = gettext("A valid primary domain name server IP address must be specified for the dynamic domain name.");
359
		}
360
		if (!empty($_POST['ddnsdomainsecondary']) && !is_ipaddr($_POST['ddnsdomainsecondary'])) {
361
			$input_errors[] = gettext("A valid secondary domain name server IP address must be specified for the dynamic domain name.");
362
		}
363
		if (!$_POST['ddnsdomainkeyname'] || !$_POST['ddnsdomainkeyalgorithm'] || !$_POST['ddnsdomainkey']) {
364
			$input_errors[] = gettext("A valid domain key name, algorithm and secret must be specified.");
365
		}
366 07588052 Viktor G
		if (preg_match('/[^A-Za-z0-9\.\-\_]/', $_POST['ddnsdomainkeyname'])) {
367
			$input_errors[] = gettext("The domain key name may only contain the characters a-z, A-Z, 0-9, '-', '_' and '.'");
368 9fbd8f71 Viktor Gurov
		}
369
		if ($_POST['ddnsdomainkey'] && !base64_decode($_POST['ddnsdomainkey'], true)) {
370
			$input_errors[] = gettext("The domain key secret must be a Base64 encoded value.");
371
		}
372 756da4bd Phil Davis
	}
373
	if ($_POST['domainsearchlist']) {
374 534d7d69 Joeri Capens
		$domain_array = preg_split("/[ ;]+/", $_POST['domainsearchlist']);
375 756da4bd Phil Davis
		foreach ($domain_array as $curdomain) {
376
			if (!is_domain($curdomain)) {
377
				$input_errors[] = gettext("A valid domain search list must be specified.");
378
				break;
379 a3de8b9e Pierre POMES
			}
380
		}
381 756da4bd Phil Davis
	}
382 a3de8b9e Pierre POMES
383 5c52a260 kiokoman
	if (($_POST['ntp1'] && !is_ipaddrv6($_POST['ntp1'])) ||
384
	    ($_POST['ntp2'] && !is_ipaddrv6($_POST['ntp2'])) ||
385 9bd56e9d Christian McDonald
	    ($_POST['ntp3'] && !is_ipaddrv6($_POST['ntp3'])) ||
386
	    ($_POST['ntp4'] && !is_ipaddrv6($_POST['ntp4']))) {
387
		$input_errors[] = gettext('A valid IPv6 address must be specified for the NTP servers.');
388 756da4bd Phil Davis
	}
389
	if (($_POST['domain'] && !is_domain($_POST['domain']))) {
390
		$input_errors[] = gettext("A valid domain name must be specified for the DNS domain.");
391
	}
392
	if ($_POST['tftp'] && !is_ipaddr($_POST['tftp']) && !is_domain($_POST['tftp']) && !is_URL($_POST['tftp'])) {
393
		$input_errors[] = gettext("A valid IPv6 address or hostname must be specified for the TFTP server.");
394
	}
395
	if (($_POST['bootfile_url'] && !is_URL($_POST['bootfile_url']))) {
396
		$input_errors[] = gettext("A valid URL must be specified for the network bootfile.");
397
	}
398 99caa67c Seth Mos
399 756da4bd Phil Davis
	// Disallow a range that includes the virtualip
400 a229259a Christian McDonald
	if ($range_from_to_ok) {
401
		foreach (config_get_path('virtualip/vip', []) as $vip) {
402 756da4bd Phil Davis
			if ($vip['interface'] == $if) {
403
				if ($vip['subnetv6'] && is_inrange_v6($vip['subnetv6'], $_POST['range_from'], $_POST['range_to'])) {
404
					$input_errors[] = sprintf(gettext("The subnet range cannot overlap with virtual IPv6 address %s."), $vip['subnetv6']);
405 8f8682f7 Phil Davis
				}
406 99caa67c Seth Mos
			}
407
		}
408 756da4bd Phil Davis
	}
409 99caa67c Seth Mos
410 756da4bd Phil Davis
	$noip = false;
411
	if (is_array($a_maps)) {
412
		foreach ($a_maps as $map) {
413
			if (empty($map['ipaddrv6'])) {
414
				$noip = true;
415 cd2c7940 sbeaver
			}
416
		}
417 756da4bd Phil Davis
	}
418
419
	/* make sure that the DHCP Relay isn't enabled on this interface */
420
	if ($_POST['enable'] && $dhcrelay_enabled) {
421
		$input_errors[] = sprintf(gettext("The DHCP relay on the %s interface must be disabled before enabling the DHCP server."), $iflist[$if]);
422
	}
423
424
	// If nothing is wrong so far, and we have range from and to, then check conditions related to the values of range from and to.
425
	if (!$input_errors && $_POST['range_from'] && $_POST['range_to']) {
426
		/* make sure the range lies within the current subnet */
427
		$subnet_start = gen_subnetv6($ifcfgip, $ifcfgsn);
428
		$subnet_end = gen_subnetv6_max($ifcfgip, $ifcfgsn);
429 99caa67c Seth Mos
430 756da4bd Phil Davis
		if (is_ipaddrv6($ifcfgip)) {
431
			if ((!is_inrange_v6($_POST['range_from'], $subnet_start, $subnet_end)) ||
432
				(!is_inrange_v6($_POST['range_to'], $subnet_start, $subnet_end))) {
433
				$input_errors[] = gettext("The specified range lies outside of the current subnet.");
434 8f8682f7 Phil Davis
			}
435 756da4bd Phil Davis
		}
436 9bd56e9d Christian McDonald
437
		if (is_numeric($pool) || ($act === 'newpool')) {
438
			if (is_inrange_v6($_POST['range_from'],
439
				config_get_path("dhcpdv6/{$if}/range/from"),
440
				config_get_path("dhcpdv6/{$if}/range/to")) ||
441
				is_inrange_v6($_POST['range_to'],
442
				config_get_path("dhcpdv6/{$if}/range/from"),
443
				config_get_path("dhcpdv6/{$if}/range/to"))) {
444
				$input_errors[] = gettext('The specified range must not be within the primary DHCPv6 address pool for this interface.');
445
			}
446
		}
447
448
		foreach ($a_pools as $id => $p) {
449
			if (is_numeric($pool) && ($id == $pool)) {
450
				continue;
451
			}
452
453
			if (is_inrange_v6($_POST['range_from'], $p['range']['from'], $p['range']['to']) ||
454
			    is_inrange_v6($_POST['range_to'], $p['range']['from'], $p['range']['to'])) {
455
				$input_errors[] = gettext('The specified range must not be within the range configured on another DHCPv6 pool for this interface.');
456
				break;
457
			}
458
		}
459
460
461 756da4bd Phil Davis
		/* "from" cannot be higher than "to" */
462
		if (inet_pton($_POST['range_from']) > inet_pton($_POST['range_to'])) {
463
			$input_errors[] = gettext("The range is invalid (first element higher than second element).");
464
		}
465 99caa67c Seth Mos
466 756da4bd Phil Davis
		/* Verify static mappings do not overlap:
467
		   - available DHCP range
468
		   - prefix delegation range (FIXME: still need to be completed) */
469
		$dynsubnet_start = inet_pton($_POST['range_from']);
470
		$dynsubnet_end = inet_pton($_POST['range_to']);
471 731de711 Pierre POMES
472 756da4bd Phil Davis
		if (is_array($a_maps)) {
473
			foreach ($a_maps as $map) {
474
				if (empty($map['ipaddrv6'])) {
475
					continue;
476
				}
477
				if ((inet_pton($map['ipaddrv6']) > $dynsubnet_start) &&
478
					(inet_pton($map['ipaddrv6']) < $dynsubnet_end)) {
479
					$input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings."));
480
					break;
481 99caa67c Seth Mos
				}
482
			}
483
		}
484
	}
485
486
	if (!$input_errors) {
487 9bd56e9d Christian McDonald
		if (!is_numeric($pool)) {
488
			if ($act === 'newpool') {
489
				$dhcpdconf = [];
490
			} else {
491
				config_init_path("dhcpdv6/{$if}");
492
				$dhcpdconf = config_get_path("dhcpdv6/{$if}");
493
			}
494
		} else {
495
			if (is_array($a_pools[$pool])) {
496
				$dhcpdconf = $a_pools[$pool];
497
			} else {
498
				header("Location: services_dhcpv6.php");
499
				exit;
500
			}
501 5fa2a4a2 Stephen Jones
		}
502 9bd56e9d Christian McDonald
503
		if (!is_array($dhcpdconf)) {
504
			$dhcpdconf = [];
505 8f8682f7 Phil Davis
		}
506 9bd56e9d Christian McDonald
507
		if (!is_array($dhcpdconf['range'])) {
508
			$dhcpdconf['range'] = [];
509 8f8682f7 Phil Davis
		}
510 9bd56e9d Christian McDonald
		if (!is_array($dhcpdconf['range'])) {
511
			$dhcpdconf['range'] = [];
512
		}
513
514
		// Global options
515
		if (!is_numeric($pool) && !($act === 'newpool')) {
516
			$dhcpdconf['enable'] = ($_POST['enable']) ? true : false;
517
		} else {
518
			// Options that exist only in pools
519
			$dhcpdconf['descr'] = $_POST['descr'];
520 8f8682f7 Phil Davis
		}
521 99caa67c Seth Mos
522
523 9bd56e9d Christian McDonald
		if (in_array($_POST['denyunknown'], array("enabled", "class"))) {
524
			$dhcpdconf['denyunknown'] = $_POST['denyunknown'];
525
		} else {
526
			unset($dhcpdconf['denyunknown']);
527
		}
528 99caa67c Seth Mos
529 9bd56e9d Christian McDonald
		$dhcpdconf['range']['from'] = $_POST['range_from'];
530
		$dhcpdconf['range']['to'] = $_POST['range_to'];
531
		$dhcpdconf['prefixrange']['from'] = $_POST['prefixrange_from'];
532
		$dhcpdconf['prefixrange']['to'] = $_POST['prefixrange_to'];
533
		$dhcpdconf['prefixrange']['prefixlength'] = $_POST['prefixrange_length'];
534
		$dhcpdconf['defaultleasetime'] = $_POST['deftime'];
535
		$dhcpdconf['maxleasetime'] = $_POST['maxtime'];
536
		$dhcpdconf['netmask'] = $_POST['netmask'];
537
538
		unset($dhcpdconf['dnsserver']);
539 8f8682f7 Phil Davis
		if ($_POST['dns1']) {
540 9bd56e9d Christian McDonald
			$dhcpdconf['dnsserver'][] = $_POST['dns1'];
541 8f8682f7 Phil Davis
		}
542
		if ($_POST['dns2']) {
543 9bd56e9d Christian McDonald
			$dhcpdconf['dnsserver'][] = $_POST['dns2'];
544 8f8682f7 Phil Davis
		}
545
		if ($_POST['dns3']) {
546 9bd56e9d Christian McDonald
			$dhcpdconf['dnsserver'][] = $_POST['dns3'];
547 8f8682f7 Phil Davis
		}
548
		if ($_POST['dns4']) {
549 9bd56e9d Christian McDonald
			$dhcpdconf['dnsserver'][] = $_POST['dns4'];
550 8f8682f7 Phil Davis
		}
551 9bd56e9d Christian McDonald
		$dhcpdconf['dhcp6c-dns'] = ($_POST['dhcp6c-dns']) ? 'enabled' : 'disabled';
552
		$dhcpdconf['domain'] = $_POST['domain'];
553
		$dhcpdconf['domainsearchlist'] = $_POST['domainsearchlist'];
554
555
		$dhcpdconf['ddnsdomain'] = $_POST['ddnsdomain'];
556
		$dhcpdconf['ddnsdomainprimary'] = $_POST['ddnsdomainprimary'];
557
		$dhcpdconf['ddnsdomainsecondary'] = (!empty($_POST['ddnsdomainsecondary'])) ? $_POST['ddnsdomainsecondary'] : '';
558
		$dhcpdconf['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname'];
559
		$dhcpdconf['ddnsdomainkeyalgorithm'] = $_POST['ddnsdomainkeyalgorithm'];
560
		$dhcpdconf['ddnsdomainkey'] = $_POST['ddnsdomainkey'];
561
		$dhcpdconf['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false;
562
		$dhcpdconf['ddnsforcehostname'] = ($_POST['ddnsforcehostname']) ? true : false;
563
		$dhcpdconf['ddnsreverse'] = ($_POST['ddnsreverse']) ? true : false;
564
		$dhcpdconf['ddnsclientupdates'] = $_POST['ddnsclientupdates'];
565
566
		unset($dhcpdconf['ntpserver']);
567 8f8682f7 Phil Davis
		if ($_POST['ntp1']) {
568 9bd56e9d Christian McDonald
			$dhcpdconf['ntpserver'][] = $_POST['ntp1'];
569 8f8682f7 Phil Davis
		}
570
		if ($_POST['ntp2']) {
571 9bd56e9d Christian McDonald
			$dhcpdconf['ntpserver'][] = $_POST['ntp2'];
572 8f8682f7 Phil Davis
		}
573 5c52a260 kiokoman
		if ($_POST['ntp3']) {
574 9bd56e9d Christian McDonald
			$dhcpdconf['ntpserver'][] = $_POST['ntp3'];
575
		}
576
		if ($_POST['ntp4']) {
577
			$dhcpdconf['ntpserver'][] = $_POST['ntp4'];
578 5c52a260 kiokoman
		}
579 99caa67c Seth Mos
580 9bd56e9d Christian McDonald
		$dhcpdconf['tftp'] = $_POST['tftp'];
581
		$dhcpdconf['ldap'] = $_POST['ldap'];
582
		$dhcpdconf['netboot'] = ($_POST['netboot']) ? true : false;
583
		$dhcpdconf['bootfile_url'] = $_POST['bootfile_url'];
584
		$dhcpdconf['dhcpv6leaseinlocaltime'] = $_POST['dhcpv6leaseinlocaltime'];
585 99caa67c Seth Mos
586
		// Handle the custom options rowhelper
587 9bd56e9d Christian McDonald
		if (isset($dhcpdconf['numberoptions']['item'])) {
588
			unset($dhcpdconf['numberoptions']['item']);
589
		}
590
591
		$dhcpdconf['numberoptions'] = $numberoptions;
592
593
		if (is_numeric($pool) && is_array($a_pools[$pool])) {
594
			$a_pools[$pool] = $dhcpdconf;
595
		} elseif ($act === 'newpool') {
596
			$a_pools[] = $dhcpdconf;
597
		} else {
598
			config_set_path("dhcpdv6/{$if}", $dhcpdconf);
599 8f8682f7 Phil Davis
		}
600 99caa67c Seth Mos
601 9bd56e9d Christian McDonald
		mark_subsystem_dirty('dhcpd6');
602 99caa67c Seth Mos
603 9bd56e9d Christian McDonald
		write_config("DHCPv6 Server settings saved");
604 99caa67c Seth Mos
605 9bd56e9d Christian McDonald
		if (is_numeric($pool) || ($act === 'newpool')) {
606
			header('Location: /services_dhcpv6.php?if='.$if);
607
		}
608
	}
609
}
610
611
if ($act == "delpool") {
612
	if ($a_pools[$_POST['id']]) {
613
		unset($a_pools[$_POST['id']]);
614
		write_config('DHCPv6 Server pool deleted');
615
		mark_subsystem_dirty('dhcpd6');
616
		header("Location: services_dhcpv6.php?if={$if}");
617
		exit;
618 99caa67c Seth Mos
	}
619
}
620
621 c946d721 Steve Beaver
if ($_POST['act'] == "del") {
622
	if ($a_maps[$_POST['id']]) {
623
		unset($a_maps[$_POST['id']]);
624 e85ae672 Renato Botelho do Couto
		write_config("DHCPv6 server static map deleted");
625 a433a061 Marcos Mendoza
		if (config_path_enabled("dhcpdv6/{$if}")) {
626 9bd56e9d Christian McDonald
			mark_subsystem_dirty('dhcpd6');
627 a433a061 Marcos Mendoza
			if (config_path_enabled('dnsmasq') && config_path_enabled('dnsmasq/regdhcpstaticv6', 'regdhcpstaticv6')) {
628 99caa67c Seth Mos
				mark_subsystem_dirty('hosts');
629 8f8682f7 Phil Davis
			}
630 99caa67c Seth Mos
		}
631
		header("Location: services_dhcpv6.php?if={$if}");
632
		exit;
633
	}
634
}
635
636 9bd56e9d Christian McDonald
// Build an HTML table that can be inserted into a Form_StaticText element
637
function build_pooltable() {
638
	global $a_pools, $if;
639
640
	$pooltbl =	'<div class="table-responsive">';
641
	$pooltbl .=		'<table class="table table-striped table-hover table-condensed">';
642
	$pooltbl .=			'<thead>';
643
	$pooltbl .=				'<tr>';
644
	$pooltbl .=					'<th>' . gettext("Pool Start") . '</th>';
645
	$pooltbl .=					'<th>' . gettext("Pool End") . '</th>';
646
	$pooltbl .=					'<th>' . gettext("Description") . '</th>';
647
	$pooltbl .=					'<th>' . gettext("Actions") . '</th>';
648
	$pooltbl .=				'</tr>';
649
	$pooltbl .=			'</thead>';
650
	$pooltbl .=			'<tbody>';
651
652
	if (is_array($a_pools)) {
653
		$i = 0;
654
		foreach ($a_pools as $poolent) {
655
			if (!empty($poolent['range']['from']) && !empty($poolent['range']['to'])) {
656
				$pooltbl .= '<tr>';
657
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcpv6.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
658
							htmlspecialchars($poolent['range']['from']) . '</td>';
659
660
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcpv6.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
661
							htmlspecialchars($poolent['range']['to']) . '</td>';
662
663
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcpv6.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
664
							htmlspecialchars($poolent['descr']) . '</td>';
665
666
				$pooltbl .= '<td><a class="fa fa-pencil" title="'. gettext("Edit pool") . '" href="services_dhcpv6.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '"></a>';
667
668
				$pooltbl .= ' <a class="fa fa-trash" title="'. gettext("Delete pool") . '" href="services_dhcpv6.php?if=' . htmlspecialchars($if) . '&act=delpool&id=' . $i . '" usepost></a></td>';
669
				$pooltbl .= '</tr>';
670
			}
671
		$i++;
672
		}
673
	}
674
675
	$pooltbl .=			'</tbody>';
676
	$pooltbl .=		'</table>';
677
	$pooltbl .= '</div>';
678
679
	return($pooltbl);
680
}
681
682
$pgtitle = [gettext('Services'), gettext('DHCPv6 Server')];
683
$pglinks = [null, 'services_dhcpv6.php'];
684 253fa019 k-paulius
685 75173246 Chris Buechler
if (!empty($if) && isset($iflist[$if])) {
686 253fa019 k-paulius
	$pgtitle[] = $iflist[$if];
687 9bd56e9d Christian McDonald
	$pglinks[] = '/services_dhcpv6.php?if='.$if;
688
689
	if (is_numeric($pool) || ($act === 'newpool')) {
690
		$pgtitle[] = gettext('Address Pool');
691
		$pglinks[] = '@self';
692
		$pgtitle[] = gettext('Edit');
693
		$pglinks[] = '@self';
694
	}
695 253fa019 k-paulius
}
696 9bd56e9d Christian McDonald
697 b32dd0a6 jim-p
$shortcut_section = "dhcp6";
698 9bd56e9d Christian McDonald
if (dhcp_is_backend('kea')) {
699
	$shortcut_section = 'kea-dhcp6';
700
}
701 99caa67c Seth Mos
702 9bd56e9d Christian McDonald
include('head.inc');
703 99caa67c Seth Mos
704 6e3488e9 Phil Davis
if ($input_errors) {
705 cd2c7940 sbeaver
	print_input_errors($input_errors);
706 6e3488e9 Phil Davis
}
707 99caa67c Seth Mos
708 44c42356 Phil Davis
if ($changes_applied) {
709
	print_apply_result_box($retval);
710 6e3488e9 Phil Davis
}
711 99caa67c Seth Mos
712 9bd56e9d Christian McDonald
if (is_subsystem_dirty('dhcpd6')) {
713
	print_apply_box(gettext('The DHCP Server configuration has been changed.') . "<br />" . gettext('The changes must be applied for them to take effect.'));
714 6e3488e9 Phil Davis
}
715 99caa67c Seth Mos
716 9bd56e9d Christian McDonald
$is_stateless_dhcp = in_array(config_get_path('dhcpdv6/'.$if.'/ramode', 'disabled'), ['stateless_dhcp']);
717
718
$valid_ra = in_array(config_get_path('dhcpdv6/'.$if.'/ramode', 'disabled'), ['managed', 'assist', 'stateless_dhcp']);
719
if (config_path_enabled('dhcpdv6/'.$if) && !$valid_ra) {
720
	print_info_box(sprintf(gettext('DHCPv6 is enabled but not being advertised to clients on %1$s. Router Advertisement must be enabled and Router Mode set to "Managed", "Assisted" or "Stateless DHCP."'), $iflist[$if]), 'danger', false);
721
}
722
723
display_isc_warning();
724
725 cd2c7940 sbeaver
/* active tabs */
726
$tab_array = array();
727
$tabscounter = 0;
728
$i = 0;
729 c80e6a6a Stephen Beaver
730 cd2c7940 sbeaver
foreach ($iflist as $ifent => $ifname) {
731 9bd56e9d Christian McDonald
	init_config_arr(['dhcpdv6', $ifent]);
732
733 829322b3 Christian McDonald
	$oc = config_get_path("interfaces/{$ifent}");
734 2bf455ca Renato Botelho
	$valid_if_ipaddrv6 = (bool) ($oc['ipaddrv6'] == 'track6' ||
735
	    (is_ipaddrv6($oc['ipaddrv6']) &&
736
	    !is_linklocal($oc['ipaddrv6'])));
737 c80e6a6a Stephen Beaver
738 a433a061 Marcos Mendoza
	if (!config_path_enabled("dhcpdv6/{$ifent}") && !$valid_if_ipaddrv6) {
739 cd2c7940 sbeaver
		continue;
740 6e3488e9 Phil Davis
	}
741 cd2c7940 sbeaver
742 6e3488e9 Phil Davis
	if ($ifent == $if) {
743 cd2c7940 sbeaver
		$active = true;
744 6e3488e9 Phil Davis
	} else {
745 cd2c7940 sbeaver
		$active = false;
746 6e3488e9 Phil Davis
	}
747 cd2c7940 sbeaver
748
	$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
749
	$tabscounter++;
750
}
751 c80e6a6a Stephen Beaver
752
if ($tabscounter == 0) {
753 cd2c7940 sbeaver
	print_info_box(gettext("The DHCPv6 Server can only be enabled on interfaces configured with a static IPv6 address. This system has none."), 'danger');
754
	include("foot.inc");
755
	exit;
756
}
757 99caa67c Seth Mos
758 9b54ac32 Stephen Beaver
display_top_tabs($tab_array);
759
760 8f58b51b jim-p
$form = new Form();
761 cd2c7940 sbeaver
762 9bd56e9d Christian McDonald
$section = new Form_Section(gettext('General DHCPv6 Options'));
763
764
$section->addInput(new Form_StaticText(
765
	gettext('DHCP Backend'),
766
	match (dhcp_get_backend()) {
767
		'isc' => gettext('ISC DHCP'),
768
		'kea' => gettext('Kea DHCP'),
769
		default => gettext('Unknown')
770
	}
771
));
772 cd2c7940 sbeaver
773 9bd56e9d Christian McDonald
if (!is_numeric($pool) && !($act === 'newpool')) {
774
	if ($dhcrelay_enabled) {
775
		$section->addInput(new Form_Checkbox(
776
			'enable',
777
			gettext('Enable'),
778
			gettext("DHCPv6 Relay is currently enabled. DHCPv6 Server canot be enabled while the DHCPv6 Relay is enabled on any interface."),
779
			$pconfig['enable']
780
		))->setAttribute('disabled', true);
781
	} else {
782
		$section->addInput(new Form_Checkbox(
783
			'enable',
784
			gettext('Enable'),
785
			sprintf(gettext('Enable DHCPv6 server on %s interface'), htmlspecialchars($iflist[$if])),
786
			$pconfig['enable']
787
		));
788
	}
789 756da4bd Phil Davis
} else {
790 9bd56e9d Christian McDonald
	print_info_box(gettext('Editing pool-specific options. To return to the Interface, click its tab above.'), 'info', false);
791
}
792
793
$section->addInput(new Form_Select(
794
	'denyunknown',
795
	gettext('Deny Unknown Clients'),
796
	$pconfig['denyunknown'],
797
	[
798
		'disabled' => gettext('Allow all clients'),
799
		'enabled' => gettext('Allow known clients from any interface'),
800
		'class' => gettext('Allow known clients from only this interface'),
801
	]
802
))->setHelp(gettext('When set to %3$sAllow all clients%4$s, any DHCP client will get an IP address within this scope/range on this interface. '.
803
	'If set to %3$sAllow known clients from any interface%4$s, any DHCP client with a DUID listed in a static mapping on %1$s%3$sany%4$s%2$s scope(s)/interface(s) will get an IP address. ' .
804
	'If set to %3$sAllow known clients from only this interface%4$s, only DUIDs listed in static mappings on this interface will get an IP address within this scope/range.'),
805
	'<i>', '</i>', '<b>', '</b>');
806
807
if (dhcp_is_backend('kea')):
808
if (is_numeric($pool) || ($act == "newpool")) {
809
	$section->addInput(new Form_Input(
810
		'descr',
811
		gettext('Description'),
812
		'text',
813
		$pconfig['descr']
814
	))->setHelp(gettext('Description for administrative reference (not parsed).'));
815
}
816
endif;
817
818
$form->add($section);
819
820
$pool_title = gettext('Primary Address Pool');
821
if (dhcp_is_backend('kea')):
822
if (is_numeric($pool) || ($act === 'newpool')) {
823
	$pool_title = gettext('Additional Address Pool');
824 756da4bd Phil Davis
}
825 9bd56e9d Christian McDonald
endif;
826
827
$section = new Form_Section($pool_title);
828 cd2c7940 sbeaver
829 6e3488e9 Phil Davis
if (is_ipaddrv6($ifcfgip)) {
830 e1953efa Chris Buechler
	if ($ifcfgip == "::") {
831 2a9f6b40 jim-p
		$sntext = gettext("Delegated Prefix") . ':';
832 a433a061 Marcos Mendoza
		$sntext .= ' ' . convert_friendly_interface_to_friendly_descr(config_get_path("interfaces/{$if}/track6-interface"));
833
		$sntext .= '/' . config_get_path("interfaces/{$if}/track6-prefix-id");
834 29131ce9 Viktor G
		if (get_interface_track6ip($if)) {
835
			$track6ip = get_interface_track6ip($if);
836
			$pdsubnet = gen_subnetv6($track6ip[0], $track6ip[1]);
837
			$sntext .= " ({$pdsubnet}/{$track6ip[1]})";
838
		}
839 e1953efa Chris Buechler
	} else {
840
		$sntext = gen_subnetv6($ifcfgip, $ifcfgsn);
841
	}
842 cd2c7940 sbeaver
	$section->addInput(new Form_StaticText(
843 9bd56e9d Christian McDonald
		gettext('Prefix'),
844
		$sntext . '/' . $ifcfgsn
845 cd2c7940 sbeaver
		));
846
847
	$section->addInput(new Form_StaticText(
848 9bd56e9d Christian McDonald
		gettext('Prefix Range'),
849 cd2c7940 sbeaver
		$range_from = gen_subnetv6($ifcfgip, $ifcfgsn) . ' to ' . gen_subnetv6_max($ifcfgip, $ifcfgsn)
850 9bd56e9d Christian McDonald
	))->setHelp($trackifname ? gettext('Prefix Delegation subnet will be appended to the beginning of the defined range'):'');
851
852
	if (is_numeric($pool) || ($act === 'newpool')) {
853
		$ranges = [];
854
		$subnet_range = config_get_path('dhcpdv6/'.$if.'/range', []);
855
		if (!empty($subnet_range)) {
856
			$subnet_range['descr'] = gettext('Primary Pool');
857
			$ranges[] = $subnet_range;
858
		}
859
860
		foreach ($a_pools as $p) {
861
			$pa = array_get_path($p, 'range', []);
862
			if (!empty($pa)) {
863
				$pa['descr'] = trim($p['descr']);
864
				$ranges[] = $pa;
865
			}
866
		}
867
868
		$first = true;
869
		foreach ($ranges as $range) {
870
			$section->addInput(new Form_StaticText(
871
				($first ? ((count($ranges) > 1) ? gettext('In-use Ranges') : gettext('In-use Range')) : null),
872
				sprintf('%s - %s%s',
873
					array_get_path($range, 'from'),
874
					array_get_path($range, 'to'),
875
					!empty($range['descr']) ? ' ('.$range['descr'].')' : null
876
				)
877
			));
878
			$first = false;
879
		}
880
	}
881 cd2c7940 sbeaver
}
882
883
$f1 = new Form_Input(
884
	'range_from',
885
	null,
886
	'text',
887
	$pconfig['range_from']
888 218600a2 Renato Botelho
);
889
890 9bd56e9d Christian McDonald
$f1->addClass('autotrim')
891
   ->setHelp(gettext('From'));
892 cd2c7940 sbeaver
893
$f2 = new Form_Input(
894
	'range_to',
895
	null,
896
	'text',
897
	$pconfig['range_to']
898 218600a2 Renato Botelho
);
899
900 9bd56e9d Christian McDonald
$f2->addClass('autotrim')
901
   ->setHelp(gettext('To'));
902 cd2c7940 sbeaver
903 9bd56e9d Christian McDonald
/* address pool is optional when stateless */
904
$group = new Form_Group((!$is_stateless_dhcp ? '*' : '').gettext('Address Pool Range'));
905 cd2c7940 sbeaver
906
$group->add($f1);
907
$group->add($f2);
908
909 9bd56e9d Christian McDonald
$group->setHelp(gettext('The specified range for this pool must not be within the range configured on any other address pool for this interface.'));
910
911 cd2c7940 sbeaver
$section->add($group);
912
913 9bd56e9d Christian McDonald
if (dhcp_is_backend('kea')):
914
if (!is_numeric($pool) && !($act === 'newpool')) {
915
	$has_pools = false;
916
	if (is_array($a_pools) && (count($a_pools) > 0)) {
917
		$section->addInput(new Form_StaticText(
918
			gettext('Additional Pools'),
919
			build_pooltable()
920
		));
921
		$has_pools = true;
922
	}
923
924
	$btnaddpool = new Form_Button(
925
		'btnaddpool',
926
		gettext('Add Address Pool'),
927
		'services_dhcpv6.php?if=' . htmlspecialchars($if) . '&act=newpool',
928
		'fa-plus'
929
	);
930
	$btnaddpool->addClass('btn-success');
931
932
	$section->addInput(new Form_StaticText(
933
		(!$has_pools ? gettext('Additional Pools') : null),
934
		$btnaddpool
935
	))->setHelp(gettext('If additional pools of addresses are needed inside of this prefix outside the above range, they may be specified here.'));
936
}
937
endif;
938
939
$form->add($section);
940
941
if (dhcp_is_backend('isc')):
942
if (!is_numeric($pool) && !($act === 'newpool')):
943
$section = new Form_Section(gettext('Prefix Delegation Pool'));
944
945 cd2c7940 sbeaver
$f1 = new Form_Input(
946 70f17067 Stephen Beaver
	'prefixrange_from',
947 cd2c7940 sbeaver
	null,
948
	'text',
949 70f17067 Stephen Beaver
	$pconfig['prefixrange_from']
950 218600a2 Renato Botelho
);
951
952 9bd56e9d Christian McDonald
$f1->addClass('trim')
953
   ->setHelp('From');
954 cd2c7940 sbeaver
955
$f2 = new Form_Input(
956 70f17067 Stephen Beaver
	'prefixrange_to',
957 cd2c7940 sbeaver
	null,
958
	'text',
959 70f17067 Stephen Beaver
	$pconfig['prefixrange_to']
960 218600a2 Renato Botelho
);
961
962 9bd56e9d Christian McDonald
$f2->addClass('trim')
963
   ->setHelp('To');
964 cd2c7940 sbeaver
965 9bd56e9d Christian McDonald
$group = new Form_Group(gettext('Prefix Delegation Range'));
966 cd2c7940 sbeaver
967
$group->add($f1);
968
$group->add($f2);
969
970
$section->add($group);
971
972
$section->addInput(new Form_Select(
973
	'prefixrange_length',
974
	'Prefix Delegation Size',
975
	$pconfig['prefixrange_length'],
976
	array(
977
		'48' => '48',
978
		'52' => '52',
979
		'56' => '56',
980 19d905bc PiBa-NL
		'59' => '59',
981 cd2c7940 sbeaver
		'60' => '60',
982 19d905bc PiBa-NL
		'61' => '61',
983 cd2c7940 sbeaver
		'62' => '62',
984
		'63' => '63',
985
		'64' => '64'
986
		)
987 9bd56e9d Christian McDonald
))->setHelp(gettext('A prefix range can be defined here for DHCP Prefix Delegation. This allows for assigning networks to subrouters. The start and end of the range must end on boundaries of the prefix delegation size.'));
988 cd2c7940 sbeaver
989 9bd56e9d Christian McDonald
$form->add($section);
990
endif;
991
endif;
992 cd2c7940 sbeaver
993 9bd56e9d Christian McDonald
$section = new Form_Section(gettext('Server Options'));
994 9f6432f0 luckman212
995 9bd56e9d Christian McDonald
if (!is_numeric($pool) && !($act === 'newpool')):
996 e26ad76e luckman212
$section->addInput(new Form_Checkbox(
997 c58e56fb luckman212
	'dhcp6c-dns',
998 9bd56e9d Christian McDonald
	gettext('Enable DNS'),
999
	gettext('Provide DNS servers to DHCPv6 clients'),
1000 04e69275 Christian McDonald
	(($pconfig['dhcp6c-dns'] == 'enabled') || ($pconfig['dhcp6c-dns'] == 'yes'))
1001 9bd56e9d Christian McDonald
))->setHelp(gettext('Unchecking this box disables the dhcp6.name-servers option. ' .
1002
	'Use with caution, as the resulting behavior may violate RFCs and lead to unintended client behavior.'));
1003
endif;
1004
1005
$ifipv6 = get_interface_ipv6($if);
1006
1007
$dns_arrv6 = [];
1008
foreach (config_get_path('system/dnsserver', []) as $dnsserver) {
1009
	if (is_ipaddrv6($dnsserver)) {
1010
		$dns_arrv6[] = $dnsserver;
1011
	}
1012
}
1013
1014
if (config_path_enabled('dnsmasq') ||
1015
    config_path_enabled('unbound')) {
1016
	$dns_arrv6 = [$ifipv6];
1017
}
1018
1019
if (is_numeric($pool) || ($act === 'newpool')) {
1020
	$subnet_dnsservers = config_get_path('dhcpdv6/'.$if.'/dnsserver', []);
1021
	if (!empty($subnet_dnsservers)) {
1022
		$dns_arrv6 = $subnet_dnsservers;
1023
	}
1024
}
1025
1026
for ($idx = 1; $idx <= 4; $idx++) {
1027
	$last = $section->addInput(new Form_IpAddress(
1028
		'dns' . $idx,
1029
		(($idx === 1) ? gettext('DNS Servers') : null),
1030
		$pconfig['dns' . $idx],
1031
		'V6'
1032
	))->addClass('autotrim')
1033
	  ->setAttribute('placeholder', $dns_arrv6[$idx - 1] ?? sprintf('DNS Server %s', $idx));
1034
}
1035
$last->setHelp(gettext('Leave blank to use the IP address of this firewall interface if DNS Resolver or Forwarder is enabled, the servers configured in General settings or those obtained dynamically.'));
1036
1037
$form->add($section);
1038
1039
$section = new Form_Section(gettext('Other DHCPv6 Options'));
1040
1041
/* the system domain name has lowest priority */
1042
$domain_holder = config_get_path('system/domain');
1043 cd2c7940 sbeaver
1044
$section->addInput(new Form_Input(
1045
	'domain',
1046 9bd56e9d Christian McDonald
	gettext('Domain Name'),
1047 cd2c7940 sbeaver
	'text',
1048 ea6649f7 sbeaver
	$pconfig['domain']
1049 9bd56e9d Christian McDonald
))->addClass('autotrim')
1050
  ->setAttribute('placeholder', $domain_holder)
1051
  ->setHelp(gettext('The default is to use the domain name of this firewall as the default domain name provided by DHCP. An alternate domain name may be specified here.'));
1052 cd2c7940 sbeaver
1053
$section->addInput(new Form_Input(
1054
	'domainsearchlist',
1055 9bd56e9d Christian McDonald
	gettext('Domain Search List'),
1056 cd2c7940 sbeaver
	'text',
1057 ea6649f7 sbeaver
	$pconfig['domainsearchlist']
1058 9bd56e9d Christian McDonald
))->addClass('autotrim')
1059
  ->setAttribute('placeholder', 'example.com;sub.example.com')
1060
  ->setHelp(gettext('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator.'));
1061 cd2c7940 sbeaver
1062 9bd56e9d Christian McDonald
if (dhcp_is_backend('isc') ||
1063
    (dhcp_is_backend('kea') && (!is_numeric($pool) && !($act === 'newpool')))):
1064 cd2c7940 sbeaver
$section->addInput(new Form_Input(
1065
	'deftime',
1066 9bd56e9d Christian McDonald
	gettext('Default Lease Time'),
1067 cd2c7940 sbeaver
	'text',
1068 ea6649f7 sbeaver
	$pconfig['deftime']
1069 9bd56e9d Christian McDonald
))->setAttribute('placeholder', '7200')
1070
  ->setHelp(gettext('This is used for clients that do not ask for a specific expiration time. The default is 7200 seconds.'));
1071 cd2c7940 sbeaver
1072
$section->addInput(new Form_Input(
1073
	'maxtime',
1074 9bd56e9d Christian McDonald
	gettext('Maximum Lease Time'),
1075 cd2c7940 sbeaver
	'text',
1076 ea6649f7 sbeaver
	$pconfig['maxtime']
1077 9bd56e9d Christian McDonald
))->setAttribute('placeholder', '86400')
1078
  ->setHelp(gettext('This is the maximum lease time for clients that ask for a specific expiration time. The default is 86400 seconds.'));
1079
endif;
1080 cd2c7940 sbeaver
1081 9bd56e9d Christian McDonald
if (dhcp_is_backend('isc')):
1082 cd2c7940 sbeaver
$section->addInput(new Form_Checkbox(
1083
	'dhcpv6leaseinlocaltime',
1084
	'Time Format Change',
1085
	'Change DHCPv6 display lease time from UTC to local time',
1086 9bd56e9d Christian McDonald
	($pconfig['dhcpv6leaseinlocaltime'] == 'yes')
1087 cd2c7940 sbeaver
))->setHelp('By default DHCPv6 leases are displayed in UTC time. ' .
1088
			'By checking this box DHCPv6 lease time will be displayed in local time and set to time zone selected. ' .
1089
			'This will be used for all DHCPv6 interfaces lease time.');
1090 9bd56e9d Christian McDonald
endif;
1091 cd2c7940 sbeaver
1092 9bd56e9d Christian McDonald
if (dhcp_is_backend('isc')):
1093 4aa42b06 Phil Davis
$btnadv = new Form_Button(
1094
	'btnadvdns',
1095 9bd56e9d Christian McDonald
	gettext('Display Advanced'),
1096 3314e626 jim-p
	null,
1097
	'fa-cog'
1098 cd2c7940 sbeaver
);
1099
1100 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1101 cd2c7940 sbeaver
1102
$section->addInput(new Form_StaticText(
1103 9bd56e9d Christian McDonald
	gettext('Dynamic DNS'),
1104 4aa42b06 Phil Davis
	$btnadv
1105 cd2c7940 sbeaver
));
1106
1107
$section->addInput(new Form_Checkbox(
1108
	'ddnsupdate',
1109
	'DHCP Registration',
1110
	'Enable registration of DHCP client names in DNS.',
1111
	$pconfig['ddnsupdate']
1112
));
1113
1114
$section->addInput(new Form_Input(
1115
	'ddnsdomain',
1116
	'DDNS Domain',
1117
	'text',
1118 ea6649f7 sbeaver
	$pconfig['ddnsdomain']
1119 e5c4b4fc Joeri Capens
))->setHelp('Enter the dynamic DNS domain which will be used to register client names in the DNS server.');
1120 cd2c7940 sbeaver
1121 1a6bda5b Ross Williams
$section->addInput(new Form_Checkbox(
1122
	'ddnsforcehostname',
1123 cfc10a33 Ross Williams
	'DDNS Hostnames',
1124 1a6bda5b Ross Williams
	'Force dynamic DNS hostname to be the same as configured hostname for Static Mappings',
1125
	$pconfig['ddnsforcehostname']
1126 9ca5d4ab Ross Williams
))->setHelp('Default registers host name option supplied by DHCP client.');
1127 1a6bda5b Ross Williams
1128 cd2c7940 sbeaver
$section->addInput(new Form_IpAddress(
1129
	'ddnsdomainprimary',
1130 9fbd8f71 Viktor Gurov
	'Primary DDNS address',
1131 ff3d11c8 Phil Davis
	$pconfig['ddnsdomainprimary'],
1132 9fbd8f71 Viktor Gurov
	'BOTH'
1133
))->setHelp('Enter the primary domain name server IP address for the dynamic domain name.');
1134
1135
$section->addInput(new Form_IpAddress(
1136
	'ddnsdomainsecondary',
1137
	'Secondary DDNS address',
1138
	$pconfig['ddnsdomainsecondary'],
1139
	'BOTH'
1140
))->setHelp('Enter the secondary domain name server IP address for the dynamic domain name.');
1141 cd2c7940 sbeaver
1142
$section->addInput(new Form_Input(
1143
	'ddnsdomainkeyname',
1144
	'DDNS Domain Key name',
1145
	'text',
1146 ea6649f7 sbeaver
	$pconfig['ddnsdomainkeyname']
1147 cd2c7940 sbeaver
))->setHelp('Enter the dynamic DNS domain key name which will be used to register client names in the DNS server.');
1148
1149 534d7d69 Joeri Capens
$section->addInput(new Form_Select(
1150
	'ddnsdomainkeyalgorithm',
1151
	'Key algorithm',
1152
	$pconfig['ddnsdomainkeyalgorithm'],
1153
	array(
1154
		'hmac-md5' => 'HMAC-MD5 (legacy default)',
1155
		'hmac-sha1' => 'HMAC-SHA1',
1156
		'hmac-sha224' => 'HMAC-SHA224',
1157
		'hmac-sha256' => 'HMAC-SHA256 (current bind9 default)',
1158
		'hmac-sha384' => 'HMAC-SHA384',
1159
		'hmac-sha512' => 'HMAC-SHA512 (most secure)',
1160
	)
1161
));
1162
1163 cd2c7940 sbeaver
$section->addInput(new Form_Input(
1164
	'ddnsdomainkey',
1165
	'DDNS Domain Key secret',
1166
	'text',
1167 ea6649f7 sbeaver
	$pconfig['ddnsdomainkey']
1168 9fbd8f71 Viktor Gurov
))->setAttribute('placeholder', 'Base64 encoded string')
1169
->setHelp('Enter the dynamic DNS domain key secret which will be used to register client names in the DNS server.');
1170 cd2c7940 sbeaver
1171 391d63da Renato Botelho
$section->addInput(new Form_Select(
1172
	'ddnsclientupdates',
1173
	'DDNS Client Updates',
1174
	$pconfig['ddnsclientupdates'],
1175
	array(
1176
	    'allow' => gettext('Allow'),
1177
	    'deny' => gettext('Deny'),
1178
	    'ignore' => gettext('Ignore'))
1179
))->setHelp('How Forward entries are handled when client indicates they wish to update DNS.  ' .
1180
	    'Allow prevents DHCP from updating Forward entries, Deny indicates that DHCP will ' .
1181
	    'do the updates and the client should not, Ignore specifies that DHCP will do the ' .
1182
	    'update and the client can also attempt the update usually using a different domain name.');
1183
1184
$section->addInput(new Form_Checkbox(
1185
	'ddnsreverse',
1186
	'DDNS Reverse',
1187
	'Add reverse dynamic DNS entries.',
1188
	$pconfig['ddnsreverse']
1189
));
1190 9bd56e9d Christian McDonald
endif;
1191 391d63da Renato Botelho
1192 4aa42b06 Phil Davis
$btnadv = new Form_Button(
1193
	'btnadvntp',
1194 9bd56e9d Christian McDonald
	gettext('Display Advanced'),
1195 3314e626 jim-p
	null,
1196
	'fa-cog'
1197 cd2c7940 sbeaver
);
1198
1199 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1200 cd2c7940 sbeaver
1201
$section->addInput(new Form_StaticText(
1202 9bd56e9d Christian McDonald
	gettext('NTP'),
1203 4aa42b06 Phil Davis
	$btnadv
1204 cd2c7940 sbeaver
));
1205
1206 9bd56e9d Christian McDonald
$ntp_holder = [];
1207
if (is_numeric($pool) || ($act === 'newpool')) {
1208
	$subnet_ntp = config_get_path('dhcpd/'.$if.'/ntpserver', []);
1209
	if (!empty($subnet_ntp)) {
1210
		$ntp_holder = $subnet_ntp;
1211
	}
1212
}
1213 cd2c7940 sbeaver
1214 9bd56e9d Christian McDonald
$section->addInput(new Form_IpAddress(
1215 cd2c7940 sbeaver
	'ntp1',
1216 9bd56e9d Christian McDonald
	gettext('NTP Server 1'),
1217 ea6649f7 sbeaver
	$pconfig['ntp1'],
1218 9bd56e9d Christian McDonald
	'HOSTV6'
1219
))->addClass('autotrim')
1220
  ->setAttribute('placeholder', $ntp_holder[0] ?? gettext('NTP Server 1'));
1221 cd2c7940 sbeaver
1222 9bd56e9d Christian McDonald
$section->addInput(new Form_IpAddress(
1223 cd2c7940 sbeaver
	'ntp2',
1224 9bd56e9d Christian McDonald
	gettext('NTP Server 2'),
1225 ea6649f7 sbeaver
	$pconfig['ntp2'],
1226 9bd56e9d Christian McDonald
	'HOSTV6'
1227
))->addClass('autotrim')
1228
  ->setAttribute('placeholder', $ntp_holder[1] ?? gettext('NTP Server 2'));
1229 cd2c7940 sbeaver
1230 9bd56e9d Christian McDonald
$section->addInput(new Form_IpAddress(
1231 5c52a260 kiokoman
	'ntp3',
1232 9bd56e9d Christian McDonald
	gettext('NTP Server 3'),
1233 5c52a260 kiokoman
	$pconfig['ntp3'],
1234 9bd56e9d Christian McDonald
	'HOSTV6'
1235
))->addClass('autotrim')
1236
  ->setAttribute('placeholder', $ntp_holder[2] ?? gettext('NTP Server 3'));
1237 cd2c7940 sbeaver
1238 9bd56e9d Christian McDonald
$section->addInput(new Form_IpAddress(
1239
	'ntp4',
1240
	gettext('NTP Server 4'),
1241
	$pconfig['ntp4'],
1242
	'HOSTV6'
1243
))->addClass('autotrim')
1244
  ->setAttribute('placeholder', $ntp_holder[3] ?? gettext('NTP Server 4'));
1245
1246
if (dhcp_is_backend('isc')):
1247 4aa42b06 Phil Davis
$btnadv = new Form_Button(
1248
	'btnadvldap',
1249 9bd56e9d Christian McDonald
	gettext('Display Advanced'),
1250 3314e626 jim-p
	null,
1251
	'fa-cog'
1252 cd2c7940 sbeaver
);
1253
1254 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1255 cd2c7940 sbeaver
1256
$section->addInput(new Form_StaticText(
1257 9bd56e9d Christian McDonald
	gettext('LDAP'),
1258 4aa42b06 Phil Davis
	$btnadv
1259 cd2c7940 sbeaver
));
1260
1261 9bd56e9d Christian McDonald
1262
$ldap_example = 'ldap://ldap.example.com/dc=example,dc=com';
1263 cd2c7940 sbeaver
$section->addInput(new Form_Input(
1264
	'ldap',
1265 9bd56e9d Christian McDonald
	gettext('LDAP Server URI'),
1266 cd2c7940 sbeaver
	'text',
1267 ea6649f7 sbeaver
	$pconfig['ldap']
1268 9bd56e9d Christian McDonald
))->setAttribute('placeholder', sprintf(gettext('LDAP Server URI (e.g. %s)'), $ldap_example))
1269
  ->setHelp(gettext('Leave blank to disable. Enter a full URI for the LDAP server in the form %s'), $ldap_example);
1270
endif;
1271 cd2c7940 sbeaver
1272 4aa42b06 Phil Davis
$btnadv = new Form_Button(
1273
	'btnadvnetboot',
1274 9bd56e9d Christian McDonald
	gettext('Display Advanced'),
1275 3314e626 jim-p
	null,
1276
	'fa-cog'
1277 cd2c7940 sbeaver
);
1278
1279 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1280 cd2c7940 sbeaver
1281
$section->addInput(new Form_StaticText(
1282 9bd56e9d Christian McDonald
	gettext('Network Booting'),
1283 4aa42b06 Phil Davis
	$btnadv
1284 cd2c7940 sbeaver
));
1285
1286
$section->addInput(new Form_Checkbox(
1287 e46ea2c6 Stephen Jones
	'netboot',
1288 9bd56e9d Christian McDonald
	gettext('Enable'),
1289
	gettext('Enable Network Booting'),
1290 e46ea2c6 Stephen Jones
	$pconfig['netboot']
1291 cd2c7940 sbeaver
));
1292
1293
$section->addInput(new Form_Input(
1294
	'bootfile_url',
1295 9bd56e9d Christian McDonald
	gettext('Bootfile URL'),
1296 cd2c7940 sbeaver
	'text',
1297 ea6649f7 sbeaver
	$pconfig['bootfile_url']
1298 cd2c7940 sbeaver
));
1299
1300 9bd56e9d Christian McDonald
if (dhcp_is_backend('isc')):
1301 4aa42b06 Phil Davis
$btnadv = new Form_Button(
1302
	'btnadvopts',
1303
	'Display Advanced',
1304 3314e626 jim-p
	null,
1305
	'fa-cog'
1306 cd2c7940 sbeaver
);
1307
1308 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1309 cd2c7940 sbeaver
1310
$section->addInput(new Form_StaticText(
1311
	'Additional BOOTP/DHCP Options',
1312 4aa42b06 Phil Davis
	$btnadv
1313 cd2c7940 sbeaver
));
1314
1315
$form->add($section);
1316
1317
$title = 'Show Additional BOOTP/DHCP Options';
1318
1319 b090a0d9 Stephen Beaver
if (!$pconfig['numberoptions']) {
1320 0716b616 Stephen Beaver
	$noopts = true;
1321 d4cebe1f Steve Beaver
	$pconfig['numberoptions'] = array();
1322 b090a0d9 Stephen Beaver
	$pconfig['numberoptions']['item'] = array(0 => array('number' => "", 'value' => ""));
1323 0716b616 Stephen Beaver
} else {
1324
	$noopts = false;
1325 b090a0d9 Stephen Beaver
}
1326
1327
$counter = 0;
1328 a2a60a07 Stephen Jones
if (!is_array($pconfig['numberoptions'])) {
1329
	$pconfig['numberoptions'] = array();
1330
}
1331
if (!is_array($pconfig['numberoptions']['item'])) {
1332
	$pconfig['numberoptions']['item'] = array();
1333
}
1334 b090a0d9 Stephen Beaver
$last = count($pconfig['numberoptions']['item']) - 1;
1335
1336
foreach ($pconfig['numberoptions']['item'] as $item) {
1337
	$group = new Form_Group(null);
1338
	$group->addClass('repeatable');
1339 0716b616 Stephen Beaver
	$group->addClass('adnloptions');
1340 b090a0d9 Stephen Beaver
1341
	$group->add(new Form_Input(
1342
		'number' . $counter,
1343
		null,
1344
		'text',
1345
		$item['number']
1346
	))->setHelp($counter == $last ? 'Number':null);
1347
1348
	$group->add(new Form_Input(
1349
		'value' . $counter,
1350
		null,
1351
		'text',
1352
		base64_decode($item['value'])
1353
	))->setHelp($counter == $last ? 'Value':null);
1354
1355
	$btn = new Form_Button(
1356
		'deleterow' . $counter,
1357 faab522f Renato Botelho
		'Delete',
1358 cd7ddae6 jim-p
		null,
1359
		'fa-trash'
1360 b090a0d9 Stephen Beaver
	);
1361
1362 cd7ddae6 jim-p
	$btn->addClass('btn-warning');
1363 b090a0d9 Stephen Beaver
	$group->add($btn);
1364
	$section->add($group);
1365
	$counter++;
1366 cd2c7940 sbeaver
}
1367
1368 b090a0d9 Stephen Beaver
1369 cd2c7940 sbeaver
$btnaddopt = new Form_Button(
1370 9eeb91dd Stephen Beaver
	'addrow',
1371 faab522f Renato Botelho
	'Add Option',
1372 cd7ddae6 jim-p
	null,
1373
	'fa-plus'
1374 cd2c7940 sbeaver
);
1375
1376 9eeb91dd Stephen Beaver
$btnaddopt->removeClass('btn-primary')->addClass('btn-success btn-sm');
1377 cd2c7940 sbeaver
1378
$section->addInput($btnaddopt);
1379 9bd56e9d Christian McDonald
endif;
1380
1381
if (dhcp_is_backend('kea')):
1382
$form->add($section);
1383
endif;
1384
1385
if ($act === 'newpool') {
1386
	$form->addGlobal(new Form_Input(
1387
		'act',
1388
		null,
1389
		'hidden',
1390
		'newpool'
1391
	));
1392
}
1393
1394
if (is_numeric($pool)) {
1395
	$form->addGlobal(new Form_Input(
1396
		'pool',
1397
		null,
1398
		'hidden',
1399
		$pool
1400
	));
1401
}
1402 cd2c7940 sbeaver
1403 ee12dd78 Peter Feichtinger
$form->addGlobal(new Form_Input(
1404 cd2c7940 sbeaver
	'if',
1405
	null,
1406
	'hidden',
1407
	$if
1408
));
1409
1410
print($form);
1411 b090a0d9 Stephen Beaver
1412 9bd56e9d Christian McDonald
// DHCP Static Mappings table
1413
if (!is_numeric($pool) && !($act === 'newpool')):
1414 f78bbe16 Phil Davis
?>
1415 cd2c7940 sbeaver
<div class="panel panel-default">
1416 9bd56e9d Christian McDonald
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('DHCPv6 Static Mappings');?></h2></div>
1417 cd2c7940 sbeaver
	<div class="panel-body table-responsive">
1418
		<table class="table table-striped table-hover table-condensed">
1419
			<thead>
1420
				<tr>
1421
					<th><?=gettext("DUID")?></th>
1422
					<th><?=gettext("IPv6 address")?></th>
1423
					<th><?=gettext("Hostname")?></th>
1424
					<th><?=gettext("Description")?></th>
1425
					<th><!-- Buttons --></th>
1426
				</tr>
1427
			</thead>
1428
			<tbody>
1429 99caa67c Seth Mos
<?php
1430 6e3488e9 Phil Davis
if (is_array($a_maps)):
1431 99caa67c Seth Mos
	$i = 0;
1432 cd2c7940 sbeaver
	foreach ($a_maps as $mapent):
1433 6e3488e9 Phil Davis
		if ($mapent['duid'] != "" or $mapent['ipaddrv6'] != ""):
1434 99caa67c Seth Mos
?>
1435 cd2c7940 sbeaver
				<tr>
1436 7d0ad4ec Joecowboy
					<td>
1437 cd2c7940 sbeaver
						<?=htmlspecialchars($mapent['duid'])?>
1438 7d0ad4ec Joecowboy
					</td>
1439
					<td>
1440 cd2c7940 sbeaver
						<?=htmlspecialchars($mapent['ipaddrv6'])?>
1441 7d0ad4ec Joecowboy
					</td>
1442
					<td>
1443 cd2c7940 sbeaver
						<?=htmlspecialchars($mapent['hostname'])?>
1444
					</td>
1445
					<td>
1446
						<?=htmlspecialchars($mapent['descr'])?>
1447
					</td>
1448
					<td>
1449 33f0b0d5 Stephen Beaver
						<a class="fa fa-pencil"	title="<?=gettext('Edit static mapping')?>" href="services_dhcpv6_edit.php?if=<?=$if?>&amp;id=<?=$i?>"></a>
1450 c946d721 Steve Beaver
						<a class="fa fa-trash"	title="<?=gettext('Delete static mapping')?>" href="services_dhcpv6.php?if=<?=$if?>&amp;act=del&amp;id=<?=$i?>" usepost></a>
1451 7d0ad4ec Joecowboy
					</td>
1452 99caa67c Seth Mos
				</tr>
1453 cd2c7940 sbeaver
<?php
1454
		endif;
1455
	$i++;
1456
	endforeach;
1457
endif;
1458
?>
1459
			</tbody>
1460 99caa67c Seth Mos
		</table>
1461
	</div>
1462 cd2c7940 sbeaver
</div>
1463
1464 c10cb196 Stephen Beaver
<nav class="action-buttons">
1465 9bd56e9d Christian McDonald
	<a href="services_dhcpv6_edit.php?if=<?=$if?>" class="btn btn-success"/>
1466 9d5a20cf heper
		<i class="fa fa-plus icon-embed-btn"></i>
1467 9bd56e9d Christian McDonald
		<?=gettext('Add Static Mapping')?>
1468 c9679d8c Stephen Beaver
	</a>
1469 cd2c7940 sbeaver
</nav>
1470 9bd56e9d Christian McDonald
<?php endif; ?>
1471 cd2c7940 sbeaver
1472 8fd9052f Colin Fleming
<script type="text/javascript">
1473 ee9530e1 Colin Fleming
//<![CDATA[
1474 6e3488e9 Phil Davis
events.push(function() {
1475 cd2c7940 sbeaver
1476 4aa42b06 Phil Davis
	// Show advanced DNS options ======================================================================================
1477
	var showadvdns = false;
1478
1479
	function show_advdns(ispageload) {
1480
		var text;
1481
		// On page load decide the initial state based on the data.
1482
		if (ispageload) {
1483
<?php
1484
			if (!$pconfig['ddnsupdate'] &&
1485 1a6bda5b Ross Williams
			    !$pconfig['ddnsforcehostname'] &&
1486 4aa42b06 Phil Davis
			    empty($pconfig['ddnsdomain']) &&
1487
			    empty($pconfig['ddnsdomainprimary']) &&
1488 9fbd8f71 Viktor Gurov
			    empty($pconfig['ddnsdomainsecondary']) &&
1489 4aa42b06 Phil Davis
			    empty($pconfig['ddnsdomainkeyname']) &&
1490 7ba6788b jim-p
			    (empty($pconfig['ddnsdomainkeyalgorithm'])  || ($pconfig['ddnsdomainkeyalgorithm'] == "hmac-md5")) &&
1491 4aa42b06 Phil Davis
			    empty($pconfig['ddnsdomainkey']) &&
1492
			    (empty($pconfig['ddnsclientupdates']) || ($pconfig['ddnsclientupdates'] == "allow")) &&
1493
			    !$pconfig['ddnsreverse']) {
1494
				$showadv = false;
1495
			} else {
1496
				$showadv = true;
1497
			}
1498
?>
1499
			showadvdns = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1500
		} else {
1501
			// It was a click, swap the state.
1502
			showadvdns = !showadvdns;
1503
		}
1504
1505
		hideCheckbox('ddnsupdate', !showadvdns);
1506
		hideInput('ddnsdomain', !showadvdns);
1507 1a6bda5b Ross Williams
		hideCheckbox('ddnsforcehostname', !showadvdns);
1508 4aa42b06 Phil Davis
		hideInput('ddnsdomainprimary', !showadvdns);
1509 9fbd8f71 Viktor Gurov
		hideInput('ddnsdomainsecondary', !showadvdns);
1510 4aa42b06 Phil Davis
		hideInput('ddnsdomainkeyname', !showadvdns);
1511 534d7d69 Joeri Capens
		hideInput('ddnsdomainkeyalgorithm', !showadvdns);
1512 4aa42b06 Phil Davis
		hideInput('ddnsdomainkey', !showadvdns);
1513
		hideInput('ddnsclientupdates', !showadvdns);
1514
		hideCheckbox('ddnsreverse', !showadvdns);
1515
1516
		if (showadvdns) {
1517
			text = "<?=gettext('Hide Advanced');?>";
1518
		} else {
1519
			text = "<?=gettext('Display Advanced');?>";
1520
		}
1521
		$('#btnadvdns').html('<i class="fa fa-cog"></i> ' + text);
1522 cd2c7940 sbeaver
	}
1523
1524 4aa42b06 Phil Davis
	$('#btnadvdns').click(function(event) {
1525
		show_advdns();
1526 cd2c7940 sbeaver
	});
1527
1528 4aa42b06 Phil Davis
	// Show advanced NTP options ======================================================================================
1529
	var showadvntp = false;
1530 cd2c7940 sbeaver
1531 4aa42b06 Phil Davis
	function show_advntp(ispageload) {
1532
		var text;
1533
		// On page load decide the initial state based on the data.
1534
		if (ispageload) {
1535
<?php
1536 5c52a260 kiokoman
			if (empty($pconfig['ntp1']) && empty($pconfig['ntp2']) && empty($pconfig['ntp3'])) {
1537 4aa42b06 Phil Davis
				$showadv = false;
1538
			} else {
1539
				$showadv = true;
1540
			}
1541
?>
1542
			showadvntp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1543
		} else {
1544
			// It was a click, swap the state.
1545
			showadvntp = !showadvntp;
1546
		}
1547 cd2c7940 sbeaver
1548 4aa42b06 Phil Davis
		hideInput('ntp1', !showadvntp);
1549
		hideInput('ntp2', !showadvntp);
1550 5c52a260 kiokoman
		hideInput('ntp3', !showadvntp);
1551 9bd56e9d Christian McDonald
		hideInput('ntp4', !showadvntp);
1552 cd2c7940 sbeaver
1553 4aa42b06 Phil Davis
		if (showadvntp) {
1554
			text = "<?=gettext('Hide Advanced');?>";
1555
		} else {
1556
			text = "<?=gettext('Display Advanced');?>";
1557
		}
1558
		$('#btnadvntp').html('<i class="fa fa-cog"></i> ' + text);
1559
	}
1560 cd2c7940 sbeaver
1561 4aa42b06 Phil Davis
	$('#btnadvntp').click(function(event) {
1562
		show_advntp();
1563 cd2c7940 sbeaver
	});
1564
1565 4aa42b06 Phil Davis
	// Show advanced LDAP options ======================================================================================
1566
	var showadvldap = false;
1567 cd2c7940 sbeaver
1568 4aa42b06 Phil Davis
	function show_advldap(ispageload) {
1569
		var text;
1570
		// On page load decide the initial state based on the data.
1571
		if (ispageload) {
1572
<?php
1573
			if (empty($pconfig['ldap'])) {
1574
				$showadv = false;
1575
			} else {
1576
				$showadv = true;
1577
			}
1578
?>
1579
			showadvldap = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1580
		} else {
1581
			// It was a click, swap the state.
1582
			showadvldap = !showadvldap;
1583
		}
1584
1585
		hideInput('ldap', !showadvldap);
1586
1587
		if (showadvldap) {
1588
			text = "<?=gettext('Hide Advanced');?>";
1589
		} else {
1590
			text = "<?=gettext('Display Advanced');?>";
1591
		}
1592
		$('#btnadvldap').html('<i class="fa fa-cog"></i> ' + text);
1593
	}
1594
1595
	$('#btnadvldap').click(function(event) {
1596
		show_advldap();
1597 cd2c7940 sbeaver
	});
1598
1599 4aa42b06 Phil Davis
	// Show advanced Netboot options ======================================================================================
1600
	var showadvnetboot = false;
1601
1602
	function show_advnetboot(ispageload) {
1603
		var text;
1604
		// On page load decide the initial state based on the data.
1605
		if (ispageload) {
1606
<?php
1607 e46ea2c6 Stephen Jones
			if (!$pconfig['netboot'] && empty($pconfig['bootfile_url'])) {
1608 4aa42b06 Phil Davis
				$showadv = false;
1609
			} else {
1610
				$showadv = true;
1611
			}
1612
?>
1613
			showadvnetboot = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1614
		} else {
1615
			// It was a click, swap the state.
1616
			showadvnetboot = !showadvnetboot;
1617
		}
1618
1619 e46ea2c6 Stephen Jones
		hideCheckbox('netboot', !showadvnetboot);
1620 4aa42b06 Phil Davis
		hideInput('bootfile_url', !showadvnetboot);
1621
1622
		if (showadvnetboot) {
1623
			text = "<?=gettext('Hide Advanced');?>";
1624
		} else {
1625
			text = "<?=gettext('Display Advanced');?>";
1626
		}
1627
		$('#btnadvnetboot').html('<i class="fa fa-cog"></i> ' + text);
1628
	}
1629
1630
	$('#btnadvnetboot').click(function(event) {
1631
		show_advnetboot();
1632 cd2c7940 sbeaver
	});
1633
1634 4aa42b06 Phil Davis
	// Show advanced additional opts options ===========================================================================
1635
	var showadvopts = false;
1636
1637
	function show_advopts(ispageload) {
1638
		var text;
1639
		// On page load decide the initial state based on the data.
1640
		if (ispageload) {
1641
<?php
1642
			if (empty($pconfig['numberoptions']) ||
1643
			    (empty($pconfig['numberoptions']['item'][0]['number']) && (empty($pconfig['numberoptions']['item'][0]['value'])))) {
1644
				$showadv = false;
1645
			} else {
1646
				$showadv = true;
1647
			}
1648
?>
1649
			showadvopts = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1650
		} else {
1651
			// It was a click, swap the state.
1652
			showadvopts = !showadvopts;
1653
		}
1654
1655
		hideClass('adnloptions', !showadvopts);
1656
		hideInput('addrow', !showadvopts);
1657
1658
		if (showadvopts) {
1659
			text = "<?=gettext('Hide Advanced');?>";
1660
		} else {
1661
			text = "<?=gettext('Display Advanced');?>";
1662
		}
1663
		$('#btnadvopts').html('<i class="fa fa-cog"></i> ' + text);
1664
	}
1665
1666
	$('#btnadvopts').click(function(event) {
1667
		show_advopts();
1668 9eeb91dd Stephen Beaver
		checkLastRow();
1669 cd2c7940 sbeaver
	});
1670
1671
	// On initial load
1672 4aa42b06 Phil Davis
	show_advdns(true);
1673
	show_advntp(true);
1674
	show_advldap(true);
1675
	show_advnetboot(true);
1676
	show_advopts(true);
1677 611cc5ca Renato Botelho
	if ($('#enable').prop('checked')) {
1678
		hideClass('adnloptions', <?php echo json_encode($noopts); ?>);
1679
		hideInput('addrow', <?php echo json_encode($noopts); ?>);
1680
	} else {
1681
		hideClass('adnloptions', true);
1682
		hideInput('addrow', true);
1683
	}
1684 9eeb91dd Stephen Beaver
1685 cd2c7940 sbeaver
});
1686 ee9530e1 Colin Fleming
//]]>
1687 99caa67c Seth Mos
</script>
1688 cd2c7940 sbeaver
1689 9bd56e9d Christian McDonald
<?php
1690
include('foot.inc');