Project

General

Profile

Download (40.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * services_dhcpv6.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2020 Rubicon Communications, LLC (Netgate)
9
 * Copyright (c) 2010 Seth Mos <seth.mos@dds.nl>
10
 * All rights reserved.
11
 *
12
 * originally based on m0n0wall (http://m0n0.ch/wall)
13
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
14
 * All rights reserved.
15
 *
16
 * 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
 *
20
 * http://www.apache.org/licenses/LICENSE-2.0
21
 *
22
 * 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
 */
28

    
29
##|+PRIV
30
##|*IDENT=page-services-dhcpv6server
31
##|*NAME=Services: DHCPv6 Server
32
##|*DESCR=Allow access to the 'Services: DHCPv6 Server' page.
33
##|*MATCH=services_dhcpv6.php*
34
##|-PRIV
35

    
36
require_once("guiconfig.inc");
37
require_once("filter.inc");
38

    
39
function dhcpv6_apply_changes($dhcpdv6_enable_changed) {
40
	$retval = 0;
41
	$retvaldhcp = 0;
42
	$retvaldns = 0;
43
	/* Stop DHCPv6 so we can cleanup leases */
44
	killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
45
	// dhcp_clean_leases();
46
	/* dnsmasq_configure calls dhcpd_configure */
47
	/* no need to restart dhcpd twice */
48
	if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic']))	{
49
		$retvaldns |= services_dnsmasq_configure();
50
		if ($retvaldns == 0) {
51
			clear_subsystem_dirty('hosts');
52
			clear_subsystem_dirty('staticmaps');
53
		}
54
	} else if (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcpstatic'])) {
55
		$retvaldns |= services_unbound_configure();
56
		if ($retvaldns == 0) {
57
			clear_subsystem_dirty('unbound');
58
			clear_subsystem_dirty('staticmaps');
59
		}
60
	} else {
61
		$retvaldhcp |= services_dhcpd_configure();
62
		if ($retvaldhcp == 0) {
63
			clear_subsystem_dirty('staticmaps');
64
		}
65
	}
66
	/* BIND package - Bug #3710 */
67
	if (!function_exists('is_package_installed')) {
68
		require_once('pkg-utils.inc');
69
	}
70
	if (is_package_installed('pfSense-pkg-bind') && isset($config['installedpackages']['bind']['config'][0]['enable_bind'])) {
71
		$reloadbind = false;
72
		if (is_array($config['installedpackages']['bindzone'])) {
73
			$bindzone = $config['installedpackages']['bindzone']['config'];
74
		} else {
75
			$bindzone = array();
76
		}
77
		for ($x = 0; $x < sizeof($bindzone); $x++) {
78
			$zone = $bindzone[$x];
79
			if ($zone['regdhcpstatic'] == 'on') {
80
				$reloadbind = true;
81
				break;
82
			}
83
		}
84
		if ($reloadbind === true) {
85
			if (file_exists("/usr/local/pkg/bind.inc")) {
86
				require_once("/usr/local/pkg/bind.inc");
87
				bind_sync();
88
			}
89
		}
90
	}
91
	if ($dhcpdv6_enable_changed) {
92
		$retvalfc |= filter_configure();
93
	}
94
	if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) {
95
		$retval = 1;
96
	}
97
	return $retval;
98
}
99

    
100
if (!$g['services_dhcp_server_enable']) {
101
	header("Location: /");
102
	exit;
103
}
104

    
105
$if = $_REQUEST['if'];
106
$iflist = get_configured_interface_with_descr();
107
$iflist = array_merge($iflist, get_configured_pppoe_server_interfaces());
108

    
109
/* set the starting interface */
110
if (!$if || !isset($iflist[$if])) {
111
	foreach ($iflist as $ifent => $ifname) {
112
		$oc = $config['interfaces'][$ifent];
113
		$valid_if_ipaddrv6 = (bool) ($oc['ipaddrv6'] == 'track6' ||
114
		    (is_ipaddrv6($oc['ipaddrv6']) &&
115
		    !is_linklocal($oc['ipaddrv6'])));
116

    
117
		if ((!is_array($config['dhcpdv6'][$ifent]) ||
118
		    !isset($config['dhcpdv6'][$ifent]['enable'])) &&
119
		    !$valid_if_ipaddrv6) {
120
			continue;
121
		}
122
		$if = $ifent;
123
		break;
124
	}
125
}
126

    
127
if (is_array($config['dhcpdv6'][$if])) {
128
	/* DHCPv6 */
129
	if (is_array($config['dhcpdv6'][$if]['range'])) {
130
		$pconfig['range_from'] = $config['dhcpdv6'][$if]['range']['from'];
131
		$pconfig['range_to'] = $config['dhcpdv6'][$if]['range']['to'];
132
	}
133
	if (is_array($config['dhcpdv6'][$if]['prefixrange'])) {
134
		$pconfig['prefixrange_from'] = $config['dhcpdv6'][$if]['prefixrange']['from'];
135
		$pconfig['prefixrange_to'] = $config['dhcpdv6'][$if]['prefixrange']['to'];
136
		$pconfig['prefixrange_length'] = $config['dhcpdv6'][$if]['prefixrange']['prefixlength'];
137
	}
138
	$pconfig['deftime'] = $config['dhcpdv6'][$if]['defaultleasetime'];
139
	$pconfig['maxtime'] = $config['dhcpdv6'][$if]['maxleasetime'];
140
	$pconfig['domain'] = $config['dhcpdv6'][$if]['domain'];
141
	$pconfig['domainsearchlist'] = $config['dhcpdv6'][$if]['domainsearchlist'];
142
	list($pconfig['wins1'], $pconfig['wins2']) = $config['dhcpdv6'][$if]['winsserver'];
143
	list($pconfig['dns1'], $pconfig['dns2'], $pconfig['dns3'], $pconfig['dns4']) = $config['dhcpdv6'][$if]['dnsserver'];
144
	$pconfig['dhcp6c-dns'] = ($config['dhcpdv6'][$if]['dhcp6c-dns'] != 'disabled') ? "enabled" : "disabled";
145
	$pconfig['enable'] = isset($config['dhcpdv6'][$if]['enable']);
146
	$pconfig['ddnsdomain'] = $config['dhcpdv6'][$if]['ddnsdomain'];
147
	$pconfig['ddnsdomainprimary'] = $config['dhcpdv6'][$if]['ddnsdomainprimary'];
148
	$pconfig['ddnsdomainsecondary'] = $config['dhcpdv6'][$if]['ddnsdomainsecondary'];
149
	$pconfig['ddnsdomainkeyname'] = $config['dhcpdv6'][$if]['ddnsdomainkeyname'];
150
	$pconfig['ddnsdomainkeyalgorithm'] = $config['dhcpdv6'][$if]['ddnsdomainkeyalgorithm'];
151
	$pconfig['ddnsdomainkey'] = $config['dhcpdv6'][$if]['ddnsdomainkey'];
152
	$pconfig['ddnsupdate'] = isset($config['dhcpdv6'][$if]['ddnsupdate']);
153
	$pconfig['ddnsforcehostname'] = isset($config['dhcpdv6'][$if]['ddnsforcehostname']);
154
	$pconfig['ddnsreverse'] = isset($config['dhcpdv6'][$if]['ddnsreverse']);
155
	$pconfig['ddnsclientupdates'] = $config['dhcpdv6'][$if]['ddnsclientupdates'];
156
	list($pconfig['ntp1'], $pconfig['ntp2'], $pconfig['ntp3'] ) = $config['dhcpdv6'][$if]['ntpserver'];
157
	$pconfig['tftp'] = $config['dhcpdv6'][$if]['tftp'];
158
	$pconfig['ldap'] = $config['dhcpdv6'][$if]['ldap'];
159
	$pconfig['netboot'] = isset($config['dhcpdv6'][$if]['netboot']);
160
	$pconfig['bootfile_url'] = $config['dhcpdv6'][$if]['bootfile_url'];
161
	$pconfig['netmask'] = $config['dhcpdv6'][$if]['netmask'];
162
	$pconfig['numberoptions'] = $config['dhcpdv6'][$if]['numberoptions'];
163
	$pconfig['dhcpv6leaseinlocaltime'] = $config['dhcpdv6'][$if]['dhcpv6leaseinlocaltime'];
164
	if (!is_array($config['dhcpdv6'][$if]['staticmap'])) {
165
		$config['dhcpdv6'][$if]['staticmap'] = array();
166
	}
167
	init_config_arr(array('dhcpdv6', $if, 'staticmap'));
168
	$a_maps = &$config['dhcpdv6'][$if]['staticmap'];
169
}
170

    
171
if ($config['interfaces'][$if]['ipaddrv6'] == 'track6') {
172
	$trackifname = $config['interfaces'][$if]['track6-interface'];
173
	$trackcfg = $config['interfaces'][$trackifname];
174
	$ifcfgsn = "64";
175
	$ifcfgip = '::';
176

    
177
	$str_help_mask = dhcpv6_pd_str_help($ifcfgsn);
178
} else {
179
	$ifcfgip = get_interface_ipv6($if);
180
	$ifcfgsn = get_interface_subnetv6($if);
181
}
182

    
183
/*	 set the enabled flag which will tell us if DHCP relay is enabled
184
 *	 on any interface. We will use this to disable DHCP server since
185
 *	 the two are not compatible with each other.
186
 */
187

    
188
$dhcrelay_enabled = false;
189
$dhcrelaycfg = $config['dhcrelay6'];
190

    
191
if (is_array($dhcrelaycfg) && isset($dhcrelaycfg['enable']) && isset($dhcrelaycfg['interface']) && !empty($dhcrelaycfg['interface'])) {
192
	$dhcrelayifs = explode(",", $dhcrelaycfg['interface']);
193

    
194
	foreach ($dhcrelayifs as $dhcrelayif) {
195

    
196
		if (isset($iflist[$dhcrelayif]) && (!link_interface_to_bridge($dhcrelayif))) {
197
			$dhcrelay_enabled = true;
198
			break;
199
		}
200
	}
201
}
202

    
203
if (isset($_POST['apply'])) {
204
	$changes_applied = true;
205
	$retval = dhcpv6_apply_changes(false);
206
} elseif (isset($_POST['save'])) {
207
	unset($input_errors);
208

    
209
	$old_dhcpdv6_enable = ($pconfig['enable'] == true);
210
	$new_dhcpdv6_enable = ($_POST['enable'] ? true : false);
211
	$dhcpdv6_enable_changed = ($old_dhcpdv6_enable != $new_dhcpdv6_enable);
212

    
213
	$pconfig = $_POST;
214

    
215
	$numberoptions = array();
216
	for ($x = 0; $x < 99; $x++) {
217
		if (isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) {
218
			$numbervalue = array();
219
			$numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]);
220
			$numbervalue['value'] = base64_encode($_POST["value{$x}"]);
221
			$numberoptions['item'][] = $numbervalue;
222
		}
223
	}
224
	// Reload the new pconfig variable that the form uses.
225
	$pconfig['numberoptions'] = $numberoptions;
226

    
227
	/* input validation */
228

    
229
	// Note: if DHCPv6 Server is not enabled, then it is OK to adjust other parameters without specifying range from-to.
230
	if ($_POST['enable']) {
231
		if ((empty($_POST['range_from']) || empty($_POST['range_to'])) &&
232
		    ($config['dhcpdv6'][$if]['ramode'] != 'stateless_dhcp')) {
233
			$input_errors[] = gettext("A valid range must be specified for any mode except Stateless DHCP.");
234
		}
235
	}
236

    
237
	if (($_POST['prefixrange_from'] && !is_ipaddrv6($_POST['prefixrange_from']))) {
238
		$input_errors[] = gettext("A valid prefix range must be specified.");
239
	}
240
	if (($_POST['prefixrange_to'] && !is_ipaddrv6($_POST['prefixrange_to']))) {
241
		$input_errors[] = gettext("A valid prefix range must be specified.");
242
	}
243

    
244
	if ($_POST['prefixrange_from'] && $_POST['prefixrange_to'] &&
245
		$_POST['prefixrange_length']) {
246
		$netmask = Net_IPv6::getNetmask($_POST['prefixrange_from'],
247
			$_POST['prefixrange_length']);
248
		$netmask = text_to_compressed_ip6($netmask);
249

    
250
		if ($netmask != text_to_compressed_ip6(strtolower(
251
			$_POST['prefixrange_from']))) {
252
			$input_errors[] = sprintf(gettext(
253
				"Prefix Delegation From address is not a valid IPv6 Netmask for %s"),
254
				$netmask . '/' . $_POST['prefixrange_length']);
255
		}
256

    
257
		$netmask = Net_IPv6::getNetmask($_POST['prefixrange_to'],
258
			$_POST['prefixrange_length']);
259
		$netmask = text_to_compressed_ip6($netmask);
260

    
261
		if ($netmask != text_to_compressed_ip6(strtolower(
262
			$_POST['prefixrange_to']))) {
263
			$input_errors[] = sprintf(gettext(
264
				"Prefix Delegation To address is not a valid IPv6 Netmask for %s"),
265
				$netmask . '/' . $_POST['prefixrange_length']);
266
		}
267
	}
268

    
269
	$range_from_to_ok = true;
270

    
271
	if ($_POST['range_from']) {
272
		if (!is_ipaddrv6($_POST['range_from'])) {
273
			$input_errors[] = gettext("A valid range must be specified.");
274
			$range_from_to_ok = false;
275
		} elseif ($config['interfaces'][$if]['ipaddrv6'] == 'track6' &&
276
			!Net_IPv6::isInNetmask($_POST['range_from'], '::', $ifcfgsn)) {
277
			$input_errors[] = sprintf(gettext(
278
				'The prefix (upper %1$s bits) must be zero.  Use the form %2$s'),
279
				$ifcfgsn, $str_help_mask);
280
			$range_from_to_ok = false;
281
		}
282
	}
283
	if ($_POST['range_to']) {
284
		if (!is_ipaddrv6($_POST['range_to'])) {
285
			$input_errors[] = gettext("A valid range must be specified.");
286
			$range_from_to_ok = false;
287
		} elseif ($config['interfaces'][$if]['ipaddrv6'] == 'track6' &&
288
			!Net_IPv6::isInNetmask($_POST['range_to'], '::', $ifcfgsn)) {
289
			$input_errors[] = sprintf(gettext(
290
				'The prefix (upper %1$s bits) must be zero.  Use the form %2$s'),
291
				$ifcfgsn, $str_help_mask);
292
			$range_from_to_ok = false;
293
		}
294
	}
295
	if (($_POST['range_from'] && !$_POST['range_to']) || ($_POST['range_to'] && !$_POST['range_from'])) {
296
		$input_errors[] = gettext("Range From and Range To must both be entered.");
297
	}
298
	if (($_POST['gateway'] && !is_ipaddrv6($_POST['gateway']))) {
299
		$input_errors[] = gettext("A valid IPv6 address must be specified for the gateway.");
300
	}
301
	if (($_POST['dns1'] && !is_ipaddrv6($_POST['dns1'])) ||
302
		($_POST['dns2'] && !is_ipaddrv6($_POST['dns2'])) ||
303
		($_POST['dns3'] && !is_ipaddrv6($_POST['dns3'])) ||
304
		($_POST['dns4'] && !is_ipaddrv6($_POST['dns4']))) {
305
		$input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers.");
306
	}
307

    
308
	if ($_POST['deftime'] && (!is_numeric($_POST['deftime']) || ($_POST['deftime'] < 60))) {
309
		$input_errors[] = gettext("The default lease time must be at least 60 seconds.");
310
	}
311
	if ($_POST['maxtime'] && (!is_numeric($_POST['maxtime']) || ($_POST['maxtime'] < 60) || ($_POST['maxtime'] <= $_POST['deftime']))) {
312
		$input_errors[] = gettext("The maximum lease time must be at least 60 seconds and higher than the default lease time.");
313
	}
314
	if ($_POST['ddnsupdate']) {
315
		if (!is_domain($_POST['ddnsdomain'])) {
316
			$input_errors[] = gettext("A valid domain name must be specified for the dynamic DNS registration.");
317
		}
318
		if (!is_ipaddr($_POST['ddnsdomainprimary'])) {
319
			$input_errors[] = gettext("A valid primary domain name server IP address must be specified for the dynamic domain name.");
320
		}
321
		if (!empty($_POST['ddnsdomainsecondary']) && !is_ipaddr($_POST['ddnsdomainsecondary'])) {
322
			$input_errors[] = gettext("A valid secondary domain name server IP address must be specified for the dynamic domain name.");
323
		}
324
		if (!$_POST['ddnsdomainkeyname'] || !$_POST['ddnsdomainkeyalgorithm'] || !$_POST['ddnsdomainkey']) {
325
			$input_errors[] = gettext("A valid domain key name, algorithm and secret must be specified.");
326
		}
327
		if (preg_match('/[^A-Za-z0-9\-_]/', $_POST['ddnsdomainkeyname'])) {
328
			$input_errors[] = gettext("The domain key name may only contain the characters a-z, A-Z, 0-9, '-' and '_'");
329
		}
330
		if ($_POST['ddnsdomainkey'] && !base64_decode($_POST['ddnsdomainkey'], true)) {
331
			$input_errors[] = gettext("The domain key secret must be a Base64 encoded value.");
332
		}
333
	}
334
	if ($_POST['domainsearchlist']) {
335
		$domain_array = preg_split("/[ ;]+/", $_POST['domainsearchlist']);
336
		foreach ($domain_array as $curdomain) {
337
			if (!is_domain($curdomain)) {
338
				$input_errors[] = gettext("A valid domain search list must be specified.");
339
				break;
340
			}
341
		}
342
	}
343

    
344
	if (($_POST['ntp1'] && !is_ipaddrv6($_POST['ntp1'])) ||
345
	    ($_POST['ntp2'] && !is_ipaddrv6($_POST['ntp2'])) ||
346
	    ($_POST['ntp3'] && !is_ipaddrv6($_POST['ntp3']))) {
347
		$input_errors[] = gettext("A valid IPv6 address must be specified for the primary/secondary NTP servers.");
348
	}
349
	if (($_POST['domain'] && !is_domain($_POST['domain']))) {
350
		$input_errors[] = gettext("A valid domain name must be specified for the DNS domain.");
351
	}
352
	if ($_POST['tftp'] && !is_ipaddr($_POST['tftp']) && !is_domain($_POST['tftp']) && !is_URL($_POST['tftp'])) {
353
		$input_errors[] = gettext("A valid IPv6 address or hostname must be specified for the TFTP server.");
354
	}
355
	if (($_POST['bootfile_url'] && !is_URL($_POST['bootfile_url']))) {
356
		$input_errors[] = gettext("A valid URL must be specified for the network bootfile.");
357
	}
358

    
359
	// Disallow a range that includes the virtualip
360
	if ($range_from_to_ok && is_array($config['virtualip']['vip'])) {
361
		foreach ($config['virtualip']['vip'] as $vip) {
362
			if ($vip['interface'] == $if) {
363
				if ($vip['subnetv6'] && is_inrange_v6($vip['subnetv6'], $_POST['range_from'], $_POST['range_to'])) {
364
					$input_errors[] = sprintf(gettext("The subnet range cannot overlap with virtual IPv6 address %s."), $vip['subnetv6']);
365
				}
366
			}
367
		}
368
	}
369

    
370
	$noip = false;
371
	if (is_array($a_maps)) {
372
		foreach ($a_maps as $map) {
373
			if (empty($map['ipaddrv6'])) {
374
				$noip = true;
375
			}
376
		}
377
	}
378

    
379
	/* make sure that the DHCP Relay isn't enabled on this interface */
380
	if ($_POST['enable'] && $dhcrelay_enabled) {
381
		$input_errors[] = sprintf(gettext("The DHCP relay on the %s interface must be disabled before enabling the DHCP server."), $iflist[$if]);
382
	}
383

    
384
	// 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.
385
	if (!$input_errors && $_POST['range_from'] && $_POST['range_to']) {
386
		/* make sure the range lies within the current subnet */
387
		$subnet_start = gen_subnetv6($ifcfgip, $ifcfgsn);
388
		$subnet_end = gen_subnetv6_max($ifcfgip, $ifcfgsn);
389

    
390
		if (is_ipaddrv6($ifcfgip)) {
391
			if ((!is_inrange_v6($_POST['range_from'], $subnet_start, $subnet_end)) ||
392
				(!is_inrange_v6($_POST['range_to'], $subnet_start, $subnet_end))) {
393
				$input_errors[] = gettext("The specified range lies outside of the current subnet.");
394
			}
395
		}
396
		/* "from" cannot be higher than "to" */
397
		if (inet_pton($_POST['range_from']) > inet_pton($_POST['range_to'])) {
398
			$input_errors[] = gettext("The range is invalid (first element higher than second element).");
399
		}
400

    
401
		/* Verify static mappings do not overlap:
402
		   - available DHCP range
403
		   - prefix delegation range (FIXME: still need to be completed) */
404
		$dynsubnet_start = inet_pton($_POST['range_from']);
405
		$dynsubnet_end = inet_pton($_POST['range_to']);
406

    
407
		if (is_array($a_maps)) {
408
			foreach ($a_maps as $map) {
409
				if (empty($map['ipaddrv6'])) {
410
					continue;
411
				}
412
				if ((inet_pton($map['ipaddrv6']) > $dynsubnet_start) &&
413
					(inet_pton($map['ipaddrv6']) < $dynsubnet_end)) {
414
					$input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings."));
415
					break;
416
				}
417
			}
418
		}
419
	}
420

    
421
	if (!$input_errors) {
422
		if (!is_array($config['dhcpdv6'])) {
423
			$config['dhcpdv6'] = array();
424
		}
425
		if (!is_array($config['dhcpdv6'][$if])) {
426
			$config['dhcpdv6'][$if] = array();
427
		}
428
		if (!is_array($config['dhcpdv6'][$if]['range'])) {
429
			$config['dhcpdv6'][$if]['range'] = array();
430
		}
431
		if (!is_array($config['dhcpdv6'][$if]['prefixrange'])) {
432
			$config['dhcpdv6'][$if]['prefixrange'] = array();
433
		}
434

    
435
		$config['dhcpdv6'][$if]['range']['from'] = $_POST['range_from'];
436
		$config['dhcpdv6'][$if]['range']['to'] = $_POST['range_to'];
437
		$config['dhcpdv6'][$if]['prefixrange']['from'] = $_POST['prefixrange_from'];
438
		$config['dhcpdv6'][$if]['prefixrange']['to'] = $_POST['prefixrange_to'];
439
		$config['dhcpdv6'][$if]['prefixrange']['prefixlength'] = $_POST['prefixrange_length'];
440
		$config['dhcpdv6'][$if]['defaultleasetime'] = $_POST['deftime'];
441
		$config['dhcpdv6'][$if]['maxleasetime'] = $_POST['maxtime'];
442
		$config['dhcpdv6'][$if]['netmask'] = $_POST['netmask'];
443

    
444
		unset($config['dhcpdv6'][$if]['winsserver']);
445

    
446
		unset($config['dhcpdv6'][$if]['dnsserver']);
447
		if ($_POST['dns1']) {
448
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns1'];
449
		}
450
		if ($_POST['dns2']) {
451
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns2'];
452
		}
453
		if ($_POST['dns3']) {
454
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns3'];
455
		}
456
		if ($_POST['dns4']) {
457
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns4'];
458
		}
459
		$config['dhcpdv6'][$if]['dhcp6c-dns'] = ($_POST['dhcp6c-dns']) ? "enabled" : "disabled";
460
		$config['dhcpdv6'][$if]['domain'] = $_POST['domain'];
461
		$config['dhcpdv6'][$if]['domainsearchlist'] = $_POST['domainsearchlist'];
462
		$config['dhcpdv6'][$if]['enable'] = ($_POST['enable']) ? true : false;
463
		$config['dhcpdv6'][$if]['ddnsdomain'] = $_POST['ddnsdomain'];
464
		$config['dhcpdv6'][$if]['ddnsdomainprimary'] = $_POST['ddnsdomainprimary'];
465
		$config['dhcpdv6'][$if]['ddnsdomainsecondary'] = (!empty($_POST['ddnsdomainsecondary'])) ? $_POST['ddnsdomainsecondary'] : ''; 
466
		$config['dhcpdv6'][$if]['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname'];
467
		$config['dhcpdv6'][$if]['ddnsdomainkeyalgorithm'] = $_POST['ddnsdomainkeyalgorithm'];
468
		$config['dhcpdv6'][$if]['ddnsdomainkey'] = $_POST['ddnsdomainkey'];
469
		$config['dhcpdv6'][$if]['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false;
470
		$config['dhcpdv6'][$if]['ddnsforcehostname'] = ($_POST['ddnsforcehostname']) ? true : false;
471
		$config['dhcpdv6'][$if]['ddnsreverse'] = ($_POST['ddnsreverse']) ? true : false;
472
		$config['dhcpdv6'][$if]['ddnsclientupdates'] = $_POST['ddnsclientupdates'];
473

    
474
		unset($config['dhcpdv6'][$if]['ntpserver']);
475
		if ($_POST['ntp1']) {
476
			$config['dhcpdv6'][$if]['ntpserver'][] = $_POST['ntp1'];
477
		}
478
		if ($_POST['ntp2']) {
479
			$config['dhcpdv6'][$if]['ntpserver'][] = $_POST['ntp2'];
480
		}
481
		if ($_POST['ntp3']) {
482
			$config['dhcpdv6'][$if]['ntpserver'][] = $_POST['ntp3'];
483
		}
484

    
485
		$config['dhcpdv6'][$if]['tftp'] = $_POST['tftp'];
486
		$config['dhcpdv6'][$if]['ldap'] = $_POST['ldap'];
487
		$config['dhcpdv6'][$if]['netboot'] = ($_POST['netboot']) ? true : false;
488
		$config['dhcpdv6'][$if]['bootfile_url'] = $_POST['bootfile_url'];
489
		$config['dhcpdv6'][$if]['dhcpv6leaseinlocaltime'] = $_POST['dhcpv6leaseinlocaltime'];
490

    
491
		// Handle the custom options rowhelper
492
		if (isset($config['dhcpdv6'][$if]['numberoptions']['item'])) {
493
			unset($config['dhcpdv6'][$if]['numberoptions']['item']);
494
		}
495

    
496
		$config['dhcpdv6'][$if]['numberoptions'] = $numberoptions;
497

    
498
		write_config();
499

    
500
		$changes_applied = true;
501
		$retval = dhcpv6_apply_changes($dhcpdv6_enable_changed);
502
	}
503
}
504

    
505
if ($_POST['act'] == "del") {
506
	if ($a_maps[$_POST['id']]) {
507
		unset($a_maps[$_POST['id']]);
508
		write_config();
509
		if (isset($config['dhcpdv6'][$if]['enable'])) {
510
			mark_subsystem_dirty('staticmapsv6');
511
			if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstaticv6'])) {
512
				mark_subsystem_dirty('hosts');
513
			}
514
		}
515
		header("Location: services_dhcpv6.php?if={$if}");
516
		exit;
517
	}
518
}
519

    
520
$pgtitle = array(gettext("Services"), htmlspecialchars(gettext("DHCPv6 Server & RA")));
521
$pglinks = array("", "services_dhcpv6.php");
522

    
523
if (!empty($if) && isset($iflist[$if])) {
524
	$pgtitle[] = $iflist[$if];
525
	$pglinks[] = "@self";
526
	$pgtitle[] = gettext("DHCPv6 Server");
527
	$pglinks[] = "@self";
528
}
529
$shortcut_section = "dhcp6";
530

    
531
include("head.inc");
532

    
533
if ($input_errors) {
534
	print_input_errors($input_errors);
535
}
536

    
537
if ($changes_applied) {
538
	print_apply_result_box($retval);
539
}
540

    
541
if (is_subsystem_dirty('staticmaps')) {
542
	print_apply_box(gettext('The static mapping configuration has been changed.') . '<br />' . gettext('The changes must be applied for them to take effect.'));
543
}
544

    
545
/* active tabs */
546
$tab_array = array();
547
$tabscounter = 0;
548
$i = 0;
549

    
550
foreach ($iflist as $ifent => $ifname) {
551
	$oc = $config['interfaces'][$ifent];
552
	$valid_if_ipaddrv6 = (bool) ($oc['ipaddrv6'] == 'track6' ||
553
	    (is_ipaddrv6($oc['ipaddrv6']) &&
554
	    !is_linklocal($oc['ipaddrv6'])));
555

    
556
	if ((!is_array($config['dhcpdv6'][$ifent]) ||
557
	    !isset($config['dhcpdv6'][$ifent]['enable'])) &&
558
	    !$valid_if_ipaddrv6) {
559
		continue;
560
	}
561

    
562
	if ($ifent == $if) {
563
		$active = true;
564
	} else {
565
		$active = false;
566
	}
567

    
568
	$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
569
	$tabscounter++;
570
}
571

    
572
/* tack on PPPoE or PPtP servers here */
573
/* pppoe server */
574
if (is_array($config['pppoes']['pppoe'])) {
575
	foreach ($config['pppoes']['pppoe'] as $pppoe) {
576
		if ($pppoe['mode'] == "server") {
577
			$ifent = "poes". $pppoe['pppoeid'];
578
			$ifname = strtoupper($ifent);
579

    
580
			if ($ifent == $if) {
581
				$active = true;
582
			} else {
583
				$active = false;
584
			}
585

    
586
			$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
587
			$tabscounter++;
588
		}
589
	}
590
}
591

    
592
if ($tabscounter == 0) {
593
	print_info_box(gettext("The DHCPv6 Server can only be enabled on interfaces configured with a static IPv6 address. This system has none."), 'danger');
594
	include("foot.inc");
595
	exit;
596
}
597

    
598
display_top_tabs($tab_array);
599

    
600
$tab_array = array();
601
$tab_array[] = array(gettext("DHCPv6 Server"),		 true,	"services_dhcpv6.php?if={$if}");
602
$tab_array[] = array(gettext("Router Advertisements"), false, "services_router_advertisements.php?if={$if}");
603
display_top_tabs($tab_array, false, 'nav nav-tabs');
604

    
605
$form = new Form();
606

    
607
$section = new Form_Section('DHCPv6 Options');
608

    
609
if ($dhcrelay_enabled) {
610
	$section->addInput(new Form_Checkbox(
611
		'enable',
612
		'DHCPv6 Server',
613
		gettext("DHCPv6 Relay is currently enabled. DHCPv6 Server canot be enabled while the DHCPv6 Relay is enabled on any interface."),
614
		$pconfig['enable']
615
	))->setAttribute('disabled', true);
616
} else {
617
	$section->addInput(new Form_Checkbox(
618
		'enable',
619
		'DHCPv6 Server',
620
		'Enable DHCPv6 server on interface ' . $iflist[$if],
621
		$pconfig['enable']
622
	));
623
}
624

    
625
if (is_ipaddrv6($ifcfgip)) {
626

    
627
	if ($ifcfgip == "::") {
628
		$sntext = "Prefix Delegation";
629
	} else {
630
		$sntext = gen_subnetv6($ifcfgip, $ifcfgsn);
631
	}
632
	$section->addInput(new Form_StaticText(
633
		'Subnet',
634
		$sntext
635
		));
636

    
637
	$section->addInput(new Form_StaticText(
638
		'Subnet Mask',
639
		$ifcfgsn . ' bits'
640
		));
641

    
642
	$section->addInput(new Form_StaticText(
643
		'Available Range',
644
		$range_from = gen_subnetv6($ifcfgip, $ifcfgsn) . ' to ' . gen_subnetv6_max($ifcfgip, $ifcfgsn)
645
		))->setHelp($trackifname ? 'Prefix Delegation subnet will be appended to the beginning of the defined range':'');
646
}
647

    
648
$f1 = new Form_Input(
649
	'range_from',
650
	null,
651
	'text',
652
	$pconfig['range_from']
653
);
654

    
655
$f1->setHelp('From');
656

    
657
$f2 = new Form_Input(
658
	'range_to',
659
	null,
660
	'text',
661
	$pconfig['range_to']
662
);
663

    
664
$f2->setHelp('To');
665

    
666
$group = new Form_Group('*Range');
667

    
668
$group->add($f1);
669
$group->add($f2);
670

    
671
$section->add($group);
672

    
673
$f1 = new Form_Input(
674
	'prefixrange_from',
675
	null,
676
	'text',
677
	$pconfig['prefixrange_from']
678
);
679

    
680
$f1->setHelp('From');
681

    
682
$f2 = new Form_Input(
683
	'prefixrange_to',
684
	null,
685
	'text',
686
	$pconfig['prefixrange_to']
687
);
688

    
689
$f2->setHelp('To');
690

    
691
$group = new Form_Group('Prefix Delegation Range');
692

    
693
$group->add($f1);
694
$group->add($f2);
695

    
696
$section->add($group);
697

    
698
$section->addInput(new Form_Select(
699
	'prefixrange_length',
700
	'Prefix Delegation Size',
701
	$pconfig['prefixrange_length'],
702
	array(
703
		'48' => '48',
704
		'52' => '52',
705
		'56' => '56',
706
		'59' => '59',
707
		'60' => '60',
708
		'61' => '61',
709
		'62' => '62',
710
		'63' => '63',
711
		'64' => '64'
712
		)
713
))->setHelp('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.');
714

    
715
$group = new Form_Group('DNS Servers');
716

    
717
for ($i=1;$i<=4; $i++) {
718
	$group->add(new Form_input(
719
		'dns' . $i,
720
		null,
721
		'text',
722
		$pconfig['dns' . $i],
723
		['placeholder' => 'DNS ' . $i]
724
	));
725
}
726

    
727
$group->setHelp('Leave blank to use the system default DNS servers, this interface\'s IP if DNS forwarder is enabled, or the servers configured on the "General" page.');
728
$section->add($group);
729

    
730
$section->addInput(new Form_Checkbox(
731
	'dhcp6c-dns',
732
	null,
733
	'Provide DNS servers to DHCPv6 clients',
734
	($pconfig['dhcp6c-dns'] == "enabled")
735
))->setHelp('Unchecking this box disables the dhcp6.name-servers option. ' .
736
			'Use with caution, as the resulting behavior may violate RFCs and lead to unintended client behavior.');
737

    
738
$section->addInput(new Form_Input(
739
	'domain',
740
	'Domain name',
741
	'text',
742
	$pconfig['domain']
743
))->setHelp('The default is to use the domain name of this system as the default domain name provided by DHCP. An alternate domain name may be specified here. ');
744

    
745
$section->addInput(new Form_Input(
746
	'domainsearchlist',
747
	'Domain search list',
748
	'text',
749
	$pconfig['domainsearchlist']
750
))->setHelp('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator.');
751

    
752
$section->addInput(new Form_Input(
753
	'deftime',
754
	'Default lease time',
755
	'text',
756
	$pconfig['deftime']
757
))->setHelp('Lease time in seconds. Used for clients that do not ask for a specific expiration time. %1$s' .
758
			'The default is 7200 seconds.', '<br />');
759

    
760
$section->addInput(new Form_Input(
761
	'maxtime',
762
	'Max lease time',
763
	'text',
764
	$pconfig['maxtime']
765
))->setHelp('Maximum lease time for clients that ask for a specific expiration time. %1$s' .
766
			'The default is 86400 seconds.', '<br />');
767

    
768
$section->addInput(new Form_Checkbox(
769
	'dhcpv6leaseinlocaltime',
770
	'Time Format Change',
771
	'Change DHCPv6 display lease time from UTC to local time',
772
	$pconfig['dhcpv6leaseinlocaltime']
773
))->setHelp('By default DHCPv6 leases are displayed in UTC time. ' .
774
			'By checking this box DHCPv6 lease time will be displayed in local time and set to time zone selected. ' .
775
			'This will be used for all DHCPv6 interfaces lease time.');
776

    
777
$btnadv = new Form_Button(
778
	'btnadvdns',
779
	'Display Advanced',
780
	null,
781
	'fa-cog'
782
);
783

    
784
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
785

    
786
$section->addInput(new Form_StaticText(
787
	'Dynamic DNS',
788
	$btnadv
789
));
790

    
791
$section->addInput(new Form_Checkbox(
792
	'ddnsupdate',
793
	'DHCP Registration',
794
	'Enable registration of DHCP client names in DNS.',
795
	$pconfig['ddnsupdate']
796
));
797

    
798
$section->addInput(new Form_Input(
799
	'ddnsdomain',
800
	'DDNS Domain',
801
	'text',
802
	$pconfig['ddnsdomain']
803
))->setHelp('Enter the dynamic DNS domain which will be used to register client names in the DNS server.');
804

    
805
$section->addInput(new Form_Checkbox(
806
	'ddnsforcehostname',
807
	'DDNS Hostnames',
808
	'Force dynamic DNS hostname to be the same as configured hostname for Static Mappings',
809
	$pconfig['ddnsforcehostname']
810
))->setHelp('Default registers host name option supplied by DHCP client.');
811

    
812
$section->addInput(new Form_IpAddress(
813
	'ddnsdomainprimary',
814
	'Primary DDNS address',
815
	$pconfig['ddnsdomainprimary'],
816
	'BOTH'
817
))->setHelp('Enter the primary domain name server IP address for the dynamic domain name.');
818

    
819
$section->addInput(new Form_IpAddress(
820
	'ddnsdomainsecondary',
821
	'Secondary DDNS address',
822
	$pconfig['ddnsdomainsecondary'],
823
	'BOTH'
824
))->setHelp('Enter the secondary domain name server IP address for the dynamic domain name.');
825

    
826
$section->addInput(new Form_Input(
827
	'ddnsdomainkeyname',
828
	'DDNS Domain Key name',
829
	'text',
830
	$pconfig['ddnsdomainkeyname']
831
))->setHelp('Enter the dynamic DNS domain key name which will be used to register client names in the DNS server.');
832

    
833
$section->addInput(new Form_Select(
834
	'ddnsdomainkeyalgorithm',
835
	'Key algorithm',
836
	$pconfig['ddnsdomainkeyalgorithm'],
837
	array(
838
		'hmac-md5' => 'HMAC-MD5 (legacy default)',
839
		'hmac-sha1' => 'HMAC-SHA1',
840
		'hmac-sha224' => 'HMAC-SHA224',
841
		'hmac-sha256' => 'HMAC-SHA256 (current bind9 default)',
842
		'hmac-sha384' => 'HMAC-SHA384',
843
		'hmac-sha512' => 'HMAC-SHA512 (most secure)',
844
	)
845
));
846

    
847
$section->addInput(new Form_Input(
848
	'ddnsdomainkey',
849
	'DDNS Domain Key secret',
850
	'text',
851
	$pconfig['ddnsdomainkey']
852
))->setAttribute('placeholder', 'Base64 encoded string')
853
->setHelp('Enter the dynamic DNS domain key secret which will be used to register client names in the DNS server.');
854

    
855
$section->addInput(new Form_Select(
856
	'ddnsclientupdates',
857
	'DDNS Client Updates',
858
	$pconfig['ddnsclientupdates'],
859
	array(
860
	    'allow' => gettext('Allow'),
861
	    'deny' => gettext('Deny'),
862
	    'ignore' => gettext('Ignore'))
863
))->setHelp('How Forward entries are handled when client indicates they wish to update DNS.  ' .
864
	    'Allow prevents DHCP from updating Forward entries, Deny indicates that DHCP will ' .
865
	    'do the updates and the client should not, Ignore specifies that DHCP will do the ' .
866
	    'update and the client can also attempt the update usually using a different domain name.');
867

    
868
$section->addInput(new Form_Checkbox(
869
	'ddnsreverse',
870
	'DDNS Reverse',
871
	'Add reverse dynamic DNS entries.',
872
	$pconfig['ddnsreverse']
873
));
874

    
875
$btnadv = new Form_Button(
876
	'btnadvntp',
877
	'Display Advanced',
878
	null,
879
	'fa-cog'
880
);
881

    
882
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
883

    
884
$section->addInput(new Form_StaticText(
885
	'NTP servers',
886
	$btnadv
887
));
888

    
889
$group = new Form_Group('NTP Servers');
890

    
891
$group->add(new Form_Input(
892
	'ntp1',
893
	'NTP Server 1',
894
	'text',
895
	$pconfig['ntp1'],
896
	['placeholder' => 'NTP 1']
897
));
898

    
899
$group->add(new Form_Input(
900
	'ntp2',
901
	'NTP Server 2',
902
	'text',
903
	$pconfig['ntp2'],
904
	['placeholder' => 'NTP 2']
905
));
906

    
907
$group->add(new Form_Input(
908
	'ntp3',
909
	'NTP Server 3',
910
	'text',
911
	$pconfig['ntp3'],
912
	['placeholder' => 'NTP 3']
913
));
914

    
915
$group->addClass('ntpclass');
916

    
917
$section->add($group);
918

    
919
$btnadv = new Form_Button(
920
	'btnadvldap',
921
	'Display Advanced',
922
	null,
923
	'fa-cog'
924
);
925

    
926
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
927

    
928
$section->addInput(new Form_StaticText(
929
	'LDAP',
930
	$btnadv
931
));
932

    
933
$section->addInput(new Form_Input(
934
	'ldap',
935
	'LDAP URI',
936
	'text',
937
	$pconfig['ldap']
938
));
939

    
940
$btnadv = new Form_Button(
941
	'btnadvnetboot',
942
	'Display Advanced',
943
	null,
944
	'fa-cog'
945
);
946

    
947
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
948

    
949
$section->addInput(new Form_StaticText(
950
	'Network booting',
951
	$btnadv
952
));
953

    
954
$section->addInput(new Form_Checkbox(
955
	'netboot',
956
	'Network booting',
957
	'Enable Network Booting',
958
	$pconfig['netboot']
959
));
960

    
961
$section->addInput(new Form_Input(
962
	'bootfile_url',
963
	'Bootfile URL',
964
	'text',
965
	$pconfig['bootfile_url']
966
));
967

    
968
$btnadv = new Form_Button(
969
	'btnadvopts',
970
	'Display Advanced',
971
	null,
972
	'fa-cog'
973
);
974

    
975
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
976

    
977
$section->addInput(new Form_StaticText(
978
	'Additional BOOTP/DHCP Options',
979
	$btnadv
980
));
981

    
982
$form->add($section);
983

    
984
$title = 'Show Additional BOOTP/DHCP Options';
985

    
986
if (!$pconfig['numberoptions']) {
987
	$noopts = true;
988
	$pconfig['numberoptions'] = array();
989
	$pconfig['numberoptions']['item'] = array(0 => array('number' => "", 'value' => ""));
990
} else {
991
	$noopts = false;
992
}
993

    
994
$counter = 0;
995
if (!is_array($pconfig['numberoptions'])) {
996
	$pconfig['numberoptions'] = array();
997
}
998
if (!is_array($pconfig['numberoptions']['item'])) {
999
	$pconfig['numberoptions']['item'] = array();
1000
}
1001
$last = count($pconfig['numberoptions']['item']) - 1;
1002

    
1003
foreach ($pconfig['numberoptions']['item'] as $item) {
1004
	$group = new Form_Group(null);
1005
	$group->addClass('repeatable');
1006
	$group->addClass('adnloptions');
1007

    
1008
	$group->add(new Form_Input(
1009
		'number' . $counter,
1010
		null,
1011
		'text',
1012
		$item['number']
1013
	))->setHelp($counter == $last ? 'Number':null);
1014

    
1015
	$group->add(new Form_Input(
1016
		'value' . $counter,
1017
		null,
1018
		'text',
1019
		base64_decode($item['value'])
1020
	))->setHelp($counter == $last ? 'Value':null);
1021

    
1022
	$btn = new Form_Button(
1023
		'deleterow' . $counter,
1024
		'Delete',
1025
		null,
1026
		'fa-trash'
1027
	);
1028

    
1029
	$btn->addClass('btn-warning');
1030
	$group->add($btn);
1031
	$section->add($group);
1032
	$counter++;
1033
}
1034

    
1035

    
1036
$btnaddopt = new Form_Button(
1037
	'addrow',
1038
	'Add Option',
1039
	null,
1040
	'fa-plus'
1041
);
1042

    
1043
$btnaddopt->removeClass('btn-primary')->addClass('btn-success btn-sm');
1044

    
1045
$section->addInput($btnaddopt);
1046

    
1047
$form->addGlobal(new Form_Input(
1048
	'if',
1049
	null,
1050
	'hidden',
1051
	$if
1052
));
1053

    
1054
print($form);
1055

    
1056
?>
1057
<div class="infoblock blockopen">
1058
<?php
1059
print_info_box(
1060
	sprintf(
1061
		gettext('The DNS servers entered in %1$sSystem: General Setup%3$s (or the %2$sDNS forwarder%3$s if enabled) will be assigned to clients by the DHCP server.'),
1062
		'<a href="system.php">',
1063
		'<a href="services_dnsmasq.php"/>',
1064
		'</a>') .
1065
	'<br />' .
1066
	sprintf(
1067
		gettext('The DHCP lease table can be viewed on the %1$sStatus: DHCPv6 leases%2$s page.'),
1068
		'<a href="status_dhcpv6_leases.php">',
1069
		'</a>'),
1070
	'info',
1071
	false);
1072
?>
1073
</div>
1074
<div class="panel panel-default">
1075
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("DHCPv6 Static Mappings for this Interface");?></h2></div>
1076
	<div class="panel-body table-responsive">
1077
		<table class="table table-striped table-hover table-condensed">
1078
			<thead>
1079
				<tr>
1080
					<th><?=gettext("DUID")?></th>
1081
					<th><?=gettext("IPv6 address")?></th>
1082
					<th><?=gettext("Hostname")?></th>
1083
					<th><?=gettext("Description")?></th>
1084
					<th><!-- Buttons --></th>
1085
				</tr>
1086
			</thead>
1087
			<tbody>
1088
<?php
1089
if (is_array($a_maps)):
1090
	$i = 0;
1091
	foreach ($a_maps as $mapent):
1092
		if ($mapent['duid'] != "" or $mapent['ipaddrv6'] != ""):
1093
?>
1094
				<tr>
1095
					<td>
1096
						<?=htmlspecialchars($mapent['duid'])?>
1097
					</td>
1098
					<td>
1099
						<?=htmlspecialchars($mapent['ipaddrv6'])?>
1100
					</td>
1101
					<td>
1102
						<?=htmlspecialchars($mapent['hostname'])?>
1103
					</td>
1104
					<td>
1105
						<?=htmlspecialchars($mapent['descr'])?>
1106
					</td>
1107
					<td>
1108
						<a class="fa fa-pencil"	title="<?=gettext('Edit static mapping')?>" href="services_dhcpv6_edit.php?if=<?=$if?>&amp;id=<?=$i?>"></a>
1109
						<a class="fa fa-trash"	title="<?=gettext('Delete static mapping')?>" href="services_dhcpv6.php?if=<?=$if?>&amp;act=del&amp;id=<?=$i?>" usepost></a>
1110
					</td>
1111
				</tr>
1112
<?php
1113
		endif;
1114
	$i++;
1115
	endforeach;
1116
endif;
1117
?>
1118
			</tbody>
1119
		</table>
1120
	</div>
1121
</div>
1122

    
1123
<nav class="action-buttons">
1124
	<a href="services_dhcpv6_edit.php?if=<?=$if?>" class="btn btn-sm btn-success"/>
1125
		<i class="fa fa-plus icon-embed-btn"></i>
1126
		<?=gettext("Add")?>
1127
	</a>
1128
</nav>
1129

    
1130
<script type="text/javascript">
1131
//<![CDATA[
1132
events.push(function() {
1133

    
1134
	// Show advanced DNS options ======================================================================================
1135
	var showadvdns = false;
1136

    
1137
	function show_advdns(ispageload) {
1138
		var text;
1139
		// On page load decide the initial state based on the data.
1140
		if (ispageload) {
1141
<?php
1142
			if (!$pconfig['ddnsupdate'] &&
1143
			    !$pconfig['ddnsforcehostname'] &&
1144
			    empty($pconfig['ddnsdomain']) &&
1145
			    empty($pconfig['ddnsdomainprimary']) &&
1146
			    empty($pconfig['ddnsdomainsecondary']) &&
1147
			    empty($pconfig['ddnsdomainkeyname']) &&
1148
			    (empty($pconfig['ddnsdomainkeyalgorithm'])  || ($pconfig['ddnsdomainkeyalgorithm'] == "hmac-md5")) &&
1149
			    empty($pconfig['ddnsdomainkey']) &&
1150
			    (empty($pconfig['ddnsclientupdates']) || ($pconfig['ddnsclientupdates'] == "allow")) &&
1151
			    !$pconfig['ddnsreverse']) {
1152
				$showadv = false;
1153
			} else {
1154
				$showadv = true;
1155
			}
1156
?>
1157
			showadvdns = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1158
		} else {
1159
			// It was a click, swap the state.
1160
			showadvdns = !showadvdns;
1161
		}
1162

    
1163
		hideCheckbox('ddnsupdate', !showadvdns);
1164
		hideInput('ddnsdomain', !showadvdns);
1165
		hideCheckbox('ddnsforcehostname', !showadvdns);
1166
		hideInput('ddnsdomainprimary', !showadvdns);
1167
		hideInput('ddnsdomainsecondary', !showadvdns);
1168
		hideInput('ddnsdomainkeyname', !showadvdns);
1169
		hideInput('ddnsdomainkeyalgorithm', !showadvdns);
1170
		hideInput('ddnsdomainkey', !showadvdns);
1171
		hideInput('ddnsclientupdates', !showadvdns);
1172
		hideCheckbox('ddnsreverse', !showadvdns);
1173

    
1174
		if (showadvdns) {
1175
			text = "<?=gettext('Hide Advanced');?>";
1176
		} else {
1177
			text = "<?=gettext('Display Advanced');?>";
1178
		}
1179
		$('#btnadvdns').html('<i class="fa fa-cog"></i> ' + text);
1180
	}
1181

    
1182
	$('#btnadvdns').click(function(event) {
1183
		show_advdns();
1184
	});
1185

    
1186
	// Show advanced NTP options ======================================================================================
1187
	var showadvntp = false;
1188

    
1189
	function show_advntp(ispageload) {
1190
		var text;
1191
		// On page load decide the initial state based on the data.
1192
		if (ispageload) {
1193
<?php
1194
			if (empty($pconfig['ntp1']) && empty($pconfig['ntp2']) && empty($pconfig['ntp3'])) {
1195
				$showadv = false;
1196
			} else {
1197
				$showadv = true;
1198
			}
1199
?>
1200
			showadvntp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1201
		} else {
1202
			// It was a click, swap the state.
1203
			showadvntp = !showadvntp;
1204
		}
1205

    
1206
		hideInput('ntp1', !showadvntp);
1207
		hideInput('ntp2', !showadvntp);
1208
		hideInput('ntp3', !showadvntp);
1209

    
1210
		if (showadvntp) {
1211
			text = "<?=gettext('Hide Advanced');?>";
1212
		} else {
1213
			text = "<?=gettext('Display Advanced');?>";
1214
		}
1215
		$('#btnadvntp').html('<i class="fa fa-cog"></i> ' + text);
1216
	}
1217

    
1218
	$('#btnadvntp').click(function(event) {
1219
		show_advntp();
1220
	});
1221

    
1222
	// Show advanced LDAP options ======================================================================================
1223
	var showadvldap = false;
1224

    
1225
	function show_advldap(ispageload) {
1226
		var text;
1227
		// On page load decide the initial state based on the data.
1228
		if (ispageload) {
1229
<?php
1230
			if (empty($pconfig['ldap'])) {
1231
				$showadv = false;
1232
			} else {
1233
				$showadv = true;
1234
			}
1235
?>
1236
			showadvldap = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1237
		} else {
1238
			// It was a click, swap the state.
1239
			showadvldap = !showadvldap;
1240
		}
1241

    
1242
		hideInput('ldap', !showadvldap);
1243

    
1244
		if (showadvldap) {
1245
			text = "<?=gettext('Hide Advanced');?>";
1246
		} else {
1247
			text = "<?=gettext('Display Advanced');?>";
1248
		}
1249
		$('#btnadvldap').html('<i class="fa fa-cog"></i> ' + text);
1250
	}
1251

    
1252
	$('#btnadvldap').click(function(event) {
1253
		show_advldap();
1254
	});
1255

    
1256
	// Show advanced Netboot options ======================================================================================
1257
	var showadvnetboot = false;
1258

    
1259
	function show_advnetboot(ispageload) {
1260
		var text;
1261
		// On page load decide the initial state based on the data.
1262
		if (ispageload) {
1263
<?php
1264
			if (!$pconfig['netboot'] && empty($pconfig['bootfile_url'])) {
1265
				$showadv = false;
1266
			} else {
1267
				$showadv = true;
1268
			}
1269
?>
1270
			showadvnetboot = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1271
		} else {
1272
			// It was a click, swap the state.
1273
			showadvnetboot = !showadvnetboot;
1274
		}
1275

    
1276
		hideCheckbox('netboot', !showadvnetboot);
1277
		hideInput('bootfile_url', !showadvnetboot);
1278

    
1279
		if (showadvnetboot) {
1280
			text = "<?=gettext('Hide Advanced');?>";
1281
		} else {
1282
			text = "<?=gettext('Display Advanced');?>";
1283
		}
1284
		$('#btnadvnetboot').html('<i class="fa fa-cog"></i> ' + text);
1285
	}
1286

    
1287
	$('#btnadvnetboot').click(function(event) {
1288
		show_advnetboot();
1289
	});
1290

    
1291
	// Show advanced additional opts options ===========================================================================
1292
	var showadvopts = false;
1293

    
1294
	function show_advopts(ispageload) {
1295
		var text;
1296
		// On page load decide the initial state based on the data.
1297
		if (ispageload) {
1298
<?php
1299
			if (empty($pconfig['numberoptions']) ||
1300
			    (empty($pconfig['numberoptions']['item'][0]['number']) && (empty($pconfig['numberoptions']['item'][0]['value'])))) {
1301
				$showadv = false;
1302
			} else {
1303
				$showadv = true;
1304
			}
1305
?>
1306
			showadvopts = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1307
		} else {
1308
			// It was a click, swap the state.
1309
			showadvopts = !showadvopts;
1310
		}
1311

    
1312
		hideClass('adnloptions', !showadvopts);
1313
		hideInput('addrow', !showadvopts);
1314

    
1315
		if (showadvopts) {
1316
			text = "<?=gettext('Hide Advanced');?>";
1317
		} else {
1318
			text = "<?=gettext('Display Advanced');?>";
1319
		}
1320
		$('#btnadvopts').html('<i class="fa fa-cog"></i> ' + text);
1321
	}
1322

    
1323
	$('#btnadvopts').click(function(event) {
1324
		show_advopts();
1325
		checkLastRow();
1326
	});
1327

    
1328
	// On initial load
1329
	show_advdns(true);
1330
	show_advntp(true);
1331
	show_advldap(true);
1332
	show_advnetboot(true);
1333
	show_advopts(true);
1334
	if ($('#enable').prop('checked')) {
1335
		hideClass('adnloptions', <?php echo json_encode($noopts); ?>);
1336
		hideInput('addrow', <?php echo json_encode($noopts); ?>);
1337
	} else {
1338
		hideClass('adnloptions', true);
1339
		hideInput('addrow', true);
1340
	}
1341

    
1342
});
1343
//]]>
1344
</script>
1345

    
1346
<?php include('foot.inc');
(122-122/228)