Project

General

Profile

Download (30.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	services_dhcpv6.php
5
	parts of m0n0wall (http://m0n0.ch/wall)
6

    
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9

    
10
	part of pfSense (https://www.pfsense.org)
11
	Copyright (C) 2010 Seth Mos <seth.mos@dds.nl>.
12
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
13
	All rights reserved.
14

    
15
	Redistribution and use in source and binary forms, with or without
16
	modification, are permitted provided that the following conditions are met:
17

    
18
	1. Redistributions of source code must retain the above copyright notice,
19
	   this list of conditions and the following disclaimer.
20

    
21
	2. Redistributions in binary form must reproduce the above copyright
22
	   notice, this list of conditions and the following disclaimer in the
23
	   documentation and/or other materials provided with the distribution.
24

    
25
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
29
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
	POSSIBILITY OF SUCH DAMAGE.
35
*/
36
/*
37
	pfSense_BUILDER_BINARIES:	/bin/rm
38
	pfSense_MODULE: interfaces
39
*/
40

    
41
##|+PRIV
42
##|*IDENT=page-services-dhcpv6server
43
##|*NAME=Services: DHCPv6 server page
44
##|*DESCR=Allow access to the 'Services: DHCPv6 server' page.
45
##|*MATCH=services_dhcpv6.php*
46
##|-PRIV
47

    
48
require("guiconfig.inc");
49
require_once("filter.inc");
50

    
51
if (!$g['services_dhcp_server_enable']) {
52
	header("Location: /");
53
	exit;
54
}
55

    
56
/*	Fix failover DHCP problem
57
 *	http://article.gmane.org/gmane.comp.security.firewalls.pfsense.support/18749
58
 */
59
ini_set("memory_limit", "64M");
60

    
61
$if = $_GET['if'];
62
if ($_POST['if']) {
63
	$if = $_POST['if'];
64
}
65

    
66
/* if OLSRD is enabled, allow WAN to house DHCP. */
67
if ($config['installedpackages']['olsrd']) {
68
	foreach ($config['installedpackages']['olsrd']['config'] as $olsrd) {
69
		if ($olsrd['enable']) {
70
			$is_olsr_enabled = true;
71
			break;
72
		}
73
	}
74
}
75

    
76
$iflist = get_configured_interface_with_descr();
77
$iflist = array_merge($iflist, get_configured_pppoe_server_interfaces());
78

    
79
/* set the starting interface */
80
if (!$if || !isset($iflist[$if])) {
81
	foreach ($iflist as $ifent => $ifname) {
82
		$oc = $config['interfaces'][$ifent];
83
		if ((is_array($config['dhcpdv6'][$ifent]) && !isset($config['dhcpdv6'][$ifent]['enable']) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))) ||
84
		    (!is_array($config['dhcpdv6'][$ifent]) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6']))))) {
85
			continue;
86
		}
87
		$if = $ifent;
88
		break;
89
	}
90
}
91

    
92
if (is_array($config['dhcpdv6'][$if])) {
93
	/* DHCPv6 */
94
	if (is_array($config['dhcpdv6'][$if]['range'])) {
95
		$pconfig['range_from'] = $config['dhcpdv6'][$if]['range']['from'];
96
		$pconfig['range_to'] = $config['dhcpdv6'][$if]['range']['to'];
97
	}
98
	if (is_array($config['dhcpdv6'][$if]['prefixrange'])) {
99
		$pconfig['prefixrange_from'] = $config['dhcpdv6'][$if]['prefixrange']['from'];
100
		$pconfig['prefixrange_to'] = $config['dhcpdv6'][$if]['prefixrange']['to'];
101
		$pconfig['prefixrange_length'] = $config['dhcpdv6'][$if]['prefixrange']['prefixlength'];
102
	}
103
	$pconfig['deftime'] = $config['dhcpdv6'][$if]['defaultleasetime'];
104
	$pconfig['maxtime'] = $config['dhcpdv6'][$if]['maxleasetime'];
105
	$pconfig['domain'] = $config['dhcpdv6'][$if]['domain'];
106
	$pconfig['domainsearchlist'] = $config['dhcpdv6'][$if]['domainsearchlist'];
107
	list($pconfig['wins1'], $pconfig['wins2']) = $config['dhcpdv6'][$if]['winsserver'];
108
	list($pconfig['dns1'], $pconfig['dns2'], $pconfig['dns3'], $pconfig['dns4']) = $config['dhcpdv6'][$if]['dnsserver'];
109
	$pconfig['enable'] = isset($config['dhcpdv6'][$if]['enable']);
110
	$pconfig['ddnsdomain'] = $config['dhcpdv6'][$if]['ddnsdomain'];
111
	$pconfig['ddnsdomainprimary'] = $config['dhcpdv6'][$if]['ddnsdomainprimary'];
112
	$pconfig['ddnsdomainkeyname'] = $config['dhcpdv6'][$if]['ddnsdomainkeyname'];
113
	$pconfig['ddnsdomainkey'] = $config['dhcpdv6'][$if]['ddnsdomainkey'];
114
	$pconfig['ddnsupdate'] = isset($config['dhcpdv6'][$if]['ddnsupdate']);
115
	list($pconfig['ntp1'], $pconfig['ntp2']) = $config['dhcpdv6'][$if]['ntpserver'];
116
	$pconfig['tftp'] = $config['dhcpdv6'][$if]['tftp'];
117
	$pconfig['ldap'] = $config['dhcpdv6'][$if]['ldap'];
118
	$pconfig['netboot'] = isset($config['dhcpdv6'][$if]['netboot']);
119
	$pconfig['bootfile_url'] = $config['dhcpdv6'][$if]['bootfile_url'];
120
	$pconfig['netmask'] = $config['dhcpdv6'][$if]['netmask'];
121
	$pconfig['numberoptions'] = $config['dhcpdv6'][$if]['numberoptions'];
122
	$pconfig['dhcpv6leaseinlocaltime'] = $config['dhcpdv6'][$if]['dhcpv6leaseinlocaltime'];
123
	if (!is_array($config['dhcpdv6'][$if]['staticmap'])) {
124
		$config['dhcpdv6'][$if]['staticmap'] = array();
125
	}
126
	$a_maps = &$config['dhcpdv6'][$if]['staticmap'];
127
}
128

    
129
$ifcfgip = get_interface_ipv6($if);
130
$ifcfgsn = get_interface_subnetv6($if);
131

    
132
/*	 set the enabled flag which will tell us if DHCP relay is enabled
133
 *	 on any interface. We will use this to disable DHCP server since
134
 *	 the two are not compatible with each other.
135
 */
136

    
137
$dhcrelay_enabled = false;
138
$dhcrelaycfg = $config['dhcrelay6'];
139

    
140
if (is_array($dhcrelaycfg)) {
141
	foreach ($dhcrelaycfg as $dhcrelayif => $dhcrelayifconf) {
142
		if (isset($dhcrelayifconf['enable']) && isset($iflist[$dhcrelayif]) &&
143
		    (!link_interface_to_bridge($dhcrelayif))) {
144
			$dhcrelay_enabled = true;
145
		}
146
	}
147
}
148

    
149
if ($_POST) {
150
	unset($input_errors);
151

    
152
	$old_dhcpdv6_enable = ($pconfig['enable'] == true);
153
	$new_dhcpdv6_enable = ($_POST['enable'] ? true : false);
154
	$dhcpdv6_enable_changed = ($old_dhcpdv6_enable != $new_dhcpdv6_enable);
155

    
156
	$pconfig = $_POST;
157

    
158
	$numberoptions = array();
159
	for ($x = 0; $x < 99; $x++) {
160
		if (isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) {
161
			$numbervalue = array();
162
			$numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]);
163
			$numbervalue['value'] = htmlspecialchars($_POST["value{$x}"]);
164
			$numberoptions['item'][] = $numbervalue;
165
		}
166
	}
167
	// Reload the new pconfig variable that the forum uses.
168
	$pconfig['numberoptions'] = $numberoptions;
169

    
170
	/* input validation */
171
	if ($_POST['enable']) {
172
		$reqdfields = explode(" ", "range_from range_to");
173
		$reqdfieldsn = array(gettext("Range begin"), gettext("Range end"));
174

    
175
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
176

    
177
		if (($_POST['prefixrange_from'] && !is_ipaddrv6($_POST['prefixrange_from']))) {
178
			$input_errors[] = gettext("A valid range must be specified.");
179
		}
180
		if (($_POST['prefixrange_to'] && !is_ipaddrv6($_POST['prefixrange_to']))) {
181
			$input_errors[] = gettext("A valid prefix range must be specified.");
182
		}
183
		if (($_POST['range_from'] && !is_ipaddrv6($_POST['range_from']))) {
184
			$input_errors[] = gettext("A valid range must be specified.");
185
		}
186
		if (($_POST['range_to'] && !is_ipaddrv6($_POST['range_to']))) {
187
			$input_errors[] = gettext("A valid range must be specified.");
188
		}
189
		if (($_POST['gateway'] && !is_ipaddrv6($_POST['gateway']))) {
190
			$input_errors[] = gettext("A valid IPv6 address must be specified for the gateway.");
191
		}
192
		if (($_POST['dns1'] && !is_ipaddrv6($_POST['dns1'])) ||
193
		    ($_POST['dns2'] && !is_ipaddrv6($_POST['dns2'])) ||
194
		    ($_POST['dns3'] && !is_ipaddrv6($_POST['dns3'])) ||
195
		    ($_POST['dns4'] && !is_ipaddrv6($_POST['dns4']))) {
196
			$input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers.");
197
		}
198

    
199
		if ($_POST['deftime'] && (!is_numeric($_POST['deftime']) || ($_POST['deftime'] < 60))) {
200
			$input_errors[] = gettext("The default lease time must be at least 60 seconds.");
201
		}
202
		if ($_POST['maxtime'] && (!is_numeric($_POST['maxtime']) || ($_POST['maxtime'] < 60) || ($_POST['maxtime'] <= $_POST['deftime']))) {
203
			$input_errors[] = gettext("The maximum lease time must be at least 60 seconds and higher than the default lease time.");
204
		}
205
		if (($_POST['ddnsdomain'] && !is_domain($_POST['ddnsdomain']))) {
206
			$input_errors[] = gettext("A valid domain name must be specified for the dynamic DNS registration.");
207
		}
208
		if (($_POST['ddnsdomain'] && !is_ipaddrv4($_POST['ddnsdomainprimary']))) {
209
			$input_errors[] = gettext("A valid primary domain name server IPv4 address must be specified for the dynamic domain name.");
210
		}
211
		if (($_POST['ddnsdomainkey'] && !$_POST['ddnsdomainkeyname']) ||
212
		    ($_POST['ddnsdomainkeyname'] && !$_POST['ddnsdomainkey'])) {
213
			$input_errors[] = gettext("You must specify both a valid domain key and key name.");
214
		}
215
		if ($_POST['domainsearchlist']) {
216
			$domain_array=preg_split("/[ ;]+/", $_POST['domainsearchlist']);
217
			foreach ($domain_array as $curdomain) {
218
				if (!is_domain($curdomain)) {
219
					$input_errors[] = gettext("A valid domain search list must be specified.");
220
					break;
221
				}
222
			}
223
		}
224

    
225
		if (($_POST['ntp1'] && !is_ipaddrv6($_POST['ntp1'])) || ($_POST['ntp2'] && !is_ipaddrv6($_POST['ntp2']))) {
226
			$input_errors[] = gettext("A valid IPv6 address must be specified for the primary/secondary NTP servers.");
227
		}
228
		if (($_POST['domain'] && !is_domain($_POST['domain']))) {
229
			$input_errors[] = gettext("A valid domain name must be specified for the DNS domain.");
230
		}
231
		if ($_POST['tftp'] && !is_ipaddr($_POST['tftp']) && !is_domain($_POST['tftp']) && !is_URL($_POST['tftp'])) {
232
			$input_errors[] = gettext("A valid IPv6 address or hostname must be specified for the TFTP server.");
233
		}
234
		if (($_POST['bootfile_url'] && !is_URL($_POST['bootfile_url']))) {
235
			$input_errors[] = gettext("A valid URL must be specified for the network bootfile.");
236
		}
237

    
238
		// Disallow a range that includes the virtualip
239
		if (is_array($config['virtualip']['vip'])) {
240
			foreach ($config['virtualip']['vip'] as $vip) {
241
				if ($vip['interface'] == $if) {
242
					if ($vip['subnetv6'] && is_inrange_v6($vip['subnetv6'], $_POST['range_from'], $_POST['range_to'])) {
243
						$input_errors[] = sprintf(gettext("The subnet range cannot overlap with virtual IPv6 address %s."), $vip['subnetv6']);
244
					}
245
				}
246
			}
247
		}
248

    
249
		$noip = false;
250
		if (is_array($a_maps)) {
251
			foreach ($a_maps as $map) {
252
				if (empty($map['ipaddrv6'])) {
253
					$noip = true;
254
				}
255
			}
256
		}
257
		if (!$input_errors) {
258
			/* make sure the range lies within the current subnet */
259
			$subnet_start = gen_subnetv6($ifcfgip, $ifcfgsn);
260
			$subnet_end = gen_subnetv6_max($ifcfgip, $ifcfgsn);
261

    
262
			if (is_ipaddrv6($ifcfgip)) {
263
				if ((!is_inrange_v6($_POST['range_from'], $subnet_start, $subnet_end)) ||
264
				    (!is_inrange_v6($_POST['range_to'], $subnet_start, $subnet_end))) {
265
					$input_errors[] = gettext("The specified range lies outside of the current subnet.");
266
				}
267
			}
268
			/* "from" cannot be higher than "to" */
269
			if (inet_pton($_POST['range_from']) > inet_pton($_POST['range_to'])) {
270
				$input_errors[] = gettext("The range is invalid (first element higher than second element).");
271
			}
272

    
273
			/* make sure that the DHCP Relay isn't enabled on this interface */
274
			if (isset($config['dhcrelay'][$if]['enable'])) {
275
				$input_errors[] = sprintf(gettext("You must disable the DHCP relay on the %s interface before enabling the DHCP server."), $iflist[$if]);
276
			}
277

    
278

    
279
			/* Verify static mappings do not overlap:
280
			   - available DHCP range
281
			   - prefix delegation range (FIXME: still need to be completed) */
282
			$dynsubnet_start = inet_pton($_POST['range_from']);
283
			$dynsubnet_end = inet_pton($_POST['range_to']);
284

    
285
			if (is_array($a_maps)) {
286
				foreach ($a_maps as $map) {
287
					if (empty($map['ipaddrv6'])) {
288
						continue;
289
					}
290
					if ((inet_pton($map['ipaddrv6']) > $dynsubnet_start) &&
291
					    (inet_pton($map['ipaddrv6']) < $dynsubnet_end)) {
292
						$input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings."));
293
						break;
294
					}
295
				}
296
			}
297
		}
298
	}
299

    
300
	if (!$input_errors) {
301
		if (!is_array($config['dhcpdv6'][$if])) {
302
			$config['dhcpdv6'][$if] = array();
303
		}
304
		if (!is_array($config['dhcpdv6'][$if]['range'])) {
305
			$config['dhcpdv6'][$if]['range'] = array();
306
		}
307
		if (!is_array($config['dhcpdv6'][$if]['prefixrange'])) {
308
			$config['dhcpdv6'][$if]['prefixrange'] = array();
309
		}
310

    
311
		$config['dhcpdv6'][$if]['range']['from'] = $_POST['range_from'];
312
		$config['dhcpdv6'][$if]['range']['to'] = $_POST['range_to'];
313
		$config['dhcpdv6'][$if]['prefixrange']['from'] = $_POST['prefixrange_from'];
314
		$config['dhcpdv6'][$if]['prefixrange']['to'] = $_POST['prefixrange_to'];
315
		$config['dhcpdv6'][$if]['prefixrange']['prefixlength'] = $_POST['prefixrange_length'];
316
		$config['dhcpdv6'][$if]['defaultleasetime'] = $_POST['deftime'];
317
		$config['dhcpdv6'][$if]['maxleasetime'] = $_POST['maxtime'];
318
		$config['dhcpdv6'][$if]['netmask'] = $_POST['netmask'];
319

    
320
		unset($config['dhcpdv6'][$if]['winsserver']);
321

    
322
		unset($config['dhcpdv6'][$if]['dnsserver']);
323
		if ($_POST['dns1']) {
324
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns1'];
325
		}
326
		if ($_POST['dns2']) {
327
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns2'];
328
		}
329
		if ($_POST['dns3']) {
330
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns3'];
331
		}
332
		if ($_POST['dns4']) {
333
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns4'];
334
		}
335

    
336
		$config['dhcpdv6'][$if]['domain'] = $_POST['domain'];
337
		$config['dhcpdv6'][$if]['domainsearchlist'] = $_POST['domainsearchlist'];
338
		$config['dhcpdv6'][$if]['enable'] = ($_POST['enable']) ? true : false;
339
		$config['dhcpdv6'][$if]['ddnsdomain'] = $_POST['ddnsdomain'];
340
		$config['dhcpdv6'][$if]['ddnsdomainprimary'] = $_POST['ddnsdomainprimary'];
341
		$config['dhcpdv6'][$if]['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname'];
342
		$config['dhcpdv6'][$if]['ddnsdomainkey'] = $_POST['ddnsdomainkey'];
343
		$config['dhcpdv6'][$if]['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false;
344

    
345
		unset($config['dhcpdv6'][$if]['ntpserver']);
346
		if ($_POST['ntp1']) {
347
			$config['dhcpdv6'][$if]['ntpserver'][] = $_POST['ntp1'];
348
		}
349
		if ($_POST['ntp2']) {
350
			$config['dhcpdv6'][$if]['ntpserver'][] = $_POST['ntp2'];
351
		}
352

    
353
		$config['dhcpdv6'][$if]['tftp'] = $_POST['tftp'];
354
		$config['dhcpdv6'][$if]['ldap'] = $_POST['ldap'];
355
		$config['dhcpdv6'][$if]['netboot'] = ($_POST['netboot']) ? true : false;
356
		$config['dhcpdv6'][$if]['bootfile_url'] = $_POST['bootfile_url'];
357
		$config['dhcpdv6'][$if]['dhcpv6leaseinlocaltime'] = $_POST['dhcpv6leaseinlocaltime'];
358

    
359
		// Handle the custom options rowhelper
360
		if (isset($config['dhcpdv6'][$if]['numberoptions']['item'])) {
361
			unset($config['dhcpdv6'][$if]['numberoptions']['item']);
362
		}
363

    
364
		$config['dhcpdv6'][$if]['numberoptions'] = $numberoptions;
365

    
366
		write_config();
367

    
368
		$retval = 0;
369
		$retvaldhcp = 0;
370
		$retvaldns = 0;
371
		/* Stop DHCPv6 so we can cleanup leases */
372
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
373
		// dhcp_clean_leases();
374
		/* dnsmasq_configure calls dhcpd_configure */
375
		/* no need to restart dhcpd twice */
376
		if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic']))	{
377
			$retvaldns = services_dnsmasq_configure();
378
			if ($retvaldns == 0) {
379
				clear_subsystem_dirty('hosts');
380
				clear_subsystem_dirty('staticmaps');
381
			}
382
		} else if (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcpstatic'])) {
383
			$retvaldns = services_unbound_configure();
384
			if ($retvaldns == 0) {
385
				clear_subsystem_dirty('unbound');
386
				clear_subsystem_dirty('staticmaps');
387
			}
388
		} else {
389
			$retvaldhcp = services_dhcpd_configure();
390
			if ($retvaldhcp == 0) {
391
				clear_subsystem_dirty('staticmaps');
392
			}
393
		}
394
		if ($dhcpdv6_enable_changed) {
395
			$retvalfc = filter_configure();
396
		}
397
		if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) {
398
			$retval = 1;
399
		}
400
		$savemsg = get_std_save_message($retval);
401
	}
402
}
403

    
404
if ($_GET['act'] == "del") {
405
	if ($a_maps[$_GET['id']]) {
406
		unset($a_maps[$_GET['id']]);
407
		write_config();
408
		if (isset($config['dhcpdv6'][$if]['enable'])) {
409
			mark_subsystem_dirty('staticmapsv6');
410
			if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstaticv6'])) {
411
				mark_subsystem_dirty('hosts');
412
			}
413
		}
414
		header("Location: services_dhcpv6.php?if={$if}");
415
		exit;
416
	}
417
}
418

    
419
// Delete a row in the options table
420
if($_GET['act'] == "delopt") {
421
	$idx = $_GET['id'];
422

    
423
	if($pconfig['numberoptions'] && is_array($pconfig['numberoptions']['item'][$idx])) {
424
	   unset($pconfig['numberoptions']['item'][$idx]);
425
	}
426
}
427

    
428
// Add an option row
429
if($_GET['act'] == "addopt") {
430
	if(!is_array($pconfig['numberoptions']['item']))
431
		$pconfig['numberoptions']['item'] = array();
432

    
433
	array_push($pconfig['numberoptions']['item'], array('number' => null, 'value' => null));
434
}
435

    
436
$closehead = false;
437
$pgtitle = array(gettext("Services"), gettext("DHCPv6 server"));
438
$shortcut_section = "dhcp6";
439

    
440
include("head.inc");
441

    
442
if ($input_errors)
443
	print_input_errors($input_errors);
444

    
445
if ($savemsg)
446
	print_info_box($savemsg, 'success');
447

    
448
if ($dhcrelay_enabled) {
449
	print_info_box(gettext("DHCP Relay is currently enabled. Cannot enable the DHCP Server service while the DHCP Relay is enabled on any interface."), 'danger');
450
	include("foot.inc");
451
	exit;
452
}
453

    
454
if (is_subsystem_dirty('staticmaps'))
455
	print_info_box_np(gettext('The static mapping configuration has been changed') . '.<br />' . gettext('You must apply the changes in order for them to take effect.'));
456

    
457
/* active tabs */
458
$tab_array = array();
459
$tabscounter = 0;
460
$i = 0;
461
foreach ($iflist as $ifent => $ifname) {
462
	$oc = $config['interfaces'][$ifent];
463
	if ((is_array($config['dhcpdv6'][$ifent]) && !isset($config['dhcpdv6'][$ifent]['enable']) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))) ||
464
		(!is_array($config['dhcpdv6'][$ifent]) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))))
465
		continue;
466

    
467
	if ($ifent == $if)
468
		$active = true;
469
	else
470
		$active = false;
471

    
472
	$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
473
	$tabscounter++;
474
}
475
/* tack on PPPoE or PPtP servers here */
476
/* pppoe server */
477
if (is_array($config['pppoes']['pppoe'])) {
478
	foreach($config['pppoes']['pppoe'] as $pppoe) {
479
		if ($pppoe['mode'] == "server") {
480
			$ifent = "poes". $pppoe['pppoeid'];
481
			$ifname = strtoupper($ifent);
482

    
483
			if ($ifent == $if)
484
				$active = true;
485
			else
486
				$active = false;
487

    
488
			$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
489
			$tabscounter++;
490
		}
491
	}
492
}
493

    
494
if (empty($tabs_array)) {
495
	print_info_box(gettext("The DHCPv6 Server can only be enabled on interfaces configured with a static IPv6 address. This system has none."), 'danger');
496
	include("foot.inc");
497
	exit;
498
}
499

    
500
$tab_array = array();
501
$tab_array[] = array(gettext("DHCPv6 Server"),		 true,	"services_dhcpv6.php?if={$if}");
502
$tab_array[] = array(gettext("Router Advertisements"), false, "services_router_advertisements.php?if={$if}");
503
display_top_tabs($tab_array);
504

    
505
require('classes/Form.class.php');
506

    
507
$form = new Form(new Form_Button(
508
	'Submit',
509
	'Save'
510
));
511

    
512
$section = new Form_Section('DHCPv6 Options');
513

    
514
$section->addInput(new Form_Checkbox(
515
	'enable',
516
	'DHCPv6 Server',
517
	'Enable DHCPv6 server on interface ' . $iflist[$if],
518
	$pconfig['enable']
519
))->toggles('.form-group:not(:first-child)');
520

    
521
if(is_ipaddrv6($ifcfgip)) {
522

    
523
	$section->addInput(new Form_StaticText(
524
		'Subnet',
525
		gen_subnetv6($ifcfgip, $ifcfgsn)
526
		));
527

    
528
	$section->addInput(new Form_StaticText(
529
		'Subnet Mask',
530
		$ifcfgsn . ' bits'
531
		));
532

    
533
	$section->addInput(new Form_StaticText(
534
		'Available Range',
535
		$range_from = gen_subnetv6($ifcfgip, $ifcfgsn) . ' to ' . gen_subnetv6_max($ifcfgip, $ifcfgsn)
536
		));
537
}
538

    
539
if($is_olsr_enabled) {
540
	$section->addInput(new Form_Select(
541
	'netmask',
542
	'Subnetmask',
543
	$pconfig['netmask'],
544
	array_combine(range(128, 1, -1), range(128, 1, -1))
545
	));
546
}
547

    
548
$f1 = new Form_Input(
549
	'range_from',
550
	null,
551
	'text',
552
	$pconfig['range_from']
553
);
554

    
555
$f1->setHelp('To');
556

    
557
$f2 = new Form_Input(
558
	'range_to',
559
	null,
560
	'text',
561
	$pconfig['range_to']
562
);
563

    
564
$f2->setHelp('From');
565

    
566
$group = new Form_Group('Range');
567

    
568
$group->add($f1);
569
$group->add($f2);
570

    
571
$section->add($group);
572

    
573
$f1 = new Form_Input(
574
	'prefix_from',
575
	null,
576
	'text',
577
	$pconfig['prefix_from']
578
);
579

    
580
$f1->setHelp('To');
581

    
582
$f2 = new Form_Input(
583
	'prefix_to',
584
	null,
585
	'text',
586
	$pconfig['prefix_to']
587
);
588

    
589
$f2->setHelp('From');
590
$group = new Form_Group('Prefix Delegation Range');
591

    
592
$group->add($f1);
593
$group->add($f2);
594

    
595
$section->add($group);
596

    
597
$section->addInput(new Form_Select(
598
	'prefixrange_length',
599
	'Prefix Delegation Size',
600
	$pconfig['prefixrange_length'],
601
	array(
602
		'48' => '48',
603
		'52' => '52',
604
		'56' => '56',
605
		'60' => '60',
606
		'62' => '62',
607
		'63' => '63',
608
		'64' => '64'
609
		)
610
))->setHelp('You can define a Prefix range 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.');
611

    
612
$group = new Form_Group('DNS Servers');
613

    
614
for($i=1;$i<=4; $i++) {
615
	$group->add(new Form_input(
616
		'dns' . $i,
617
		null,
618
		'text',
619
		$pconfig['dns' . $i]
620
	))->setHelp('DNS ' . $i);
621
}
622

    
623
$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.');
624
$section->add($group);
625

    
626
$section->addInput(new Form_Input(
627
	'domain',
628
	'Domain Name',
629
	'text',
630
	$pconfig['domain']
631
))->setHelp('The default is to use the domain name of this system as the default domain name provided by DHCP. You may specify an alternate domain name here. ');
632

    
633
$section->addInput(new Form_Input(
634
	'domainsearchlist',
635
	'Domain search list',
636
	'text',
637
	$pconfig['domainsearchlist']
638
))->setHelp('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator');
639

    
640
$section->addInput(new Form_Input(
641
	'deftime',
642
	'Default lease time',
643
	'text',
644
	$pconfig['deftime']
645
))->setHelp('Seconds . Used for clients that do not ask for a specific expiration time. ' . ' <br />' .
646
			'The default is 7200 seconds.');
647

    
648
$section->addInput(new Form_Input(
649
	'maxtime',
650
	'Max lease time',
651
	'text',
652
	$pconfig['maxtime']
653
))->setHelp('Maximum lease time for clients that ask for a specific expiration time.' . ' <br />' .
654
			'The default is 86400 seconds.');
655

    
656
$section->addInput(new Form_Checkbox(
657
	'dhcpv6leaseinlocaltime',
658
	'Time Format Change',
659
	'Change DHCPv6 display lease time from UTC to local time',
660
	$pconfig['dhcpv6leaseinlocaltime']
661
))->setHelp('By default DHCPv6 leases are displayed in UTC time. ' .
662
			'By checking this box DHCPv6 lease time will be displayed in local time and set to time zone selected. ' .
663
			'This will be used for all DHCPv6 interfaces lease time.');
664

    
665
$btndyndns = new Form_Button(
666
	'btndyndns',
667
	'Advanced'
668
);
669

    
670
$btndyndns->removeClass('btn-primary')->addClass('btn-default btn-sm');
671

    
672
$section->addInput(new Form_StaticText(
673
	'Dynamic DNS',
674
	$btndyndns . '&nbsp;' . 'Show dynamic DNS settings'
675
));
676

    
677
$section->addInput(new Form_Checkbox(
678
	'ddnsupdate',
679
	'DHCP Registration',
680
	'Enable registration of DHCP client names in DNS.',
681
	$pconfig['ddnsupdate']
682
));
683

    
684
$section->addInput(new Form_Input(
685
	'ddnsdomain',
686
	'DDNS Domain',
687
	'text',
688
	$pconfig['ddnsdomain']
689
))->setHelp('Leave blank to disable dynamic DNS registration. Enter the dynamic DNS domain which will be used to register client names in the DNS server.');
690

    
691
$section->addInput(new Form_IpAddress(
692
	'ddnsdomainprimary',
693
	'DDNS Server IP',
694
	$pconfig['ddnsdomainprimary']
695
))->setHelp('Enter the primary domain name server IP address for the dynamic domain name.');
696

    
697
$section->addInput(new Form_Input(
698
	'ddnsdomainkeyname',
699
	'DDNS Domain Key name',
700
	'text',
701
	$pconfig['ddnsdomainkeyname']
702
))->setHelp('Enter the dynamic DNS domain key name which will be used to register client names in the DNS server.');
703

    
704
$section->addInput(new Form_Input(
705
	'ddnsdomainkey',
706
	'DDNS Domain Key secret',
707
	'text',
708
	$pconfig['ddnsdomainkey']
709
))->setHelp('Enter the dynamic DNS domain key secret which will be used to register client names in the DNS server.');
710

    
711
$btnntp = new Form_Button(
712
	'btnntp',
713
	'Advanced'
714
);
715

    
716
$btnntp->removeClass('btn-primary')->addClass('btn-default btn-sm');
717

    
718
$section->addInput(new Form_StaticText(
719
	'NTP servers',
720
	$btnntp . '&nbsp;' . 'Show NTP Configuration'
721
));
722

    
723
$group = new Form_Group('NTP Servers');
724

    
725
$group->add(new Form_Input(
726
	'ntp1',
727
	'NTP Server 1',
728
	'text',
729
	$pconfig['ntp1'],
730
	['placeholder' => 'NTP 1']
731
));
732

    
733
$group->add(new Form_Input(
734
	'ntp2',
735
	'NTP Server 1',
736
	'text',
737
	$pconfig['ntp2'],
738
	['placeholder' => 'NTP 2']
739
));
740

    
741
$group->addClass('ntpclass');
742

    
743
$section->add($group);
744

    
745
$btnldap = new Form_Button(
746
	'btnldap',
747
	'Advanced'
748
);
749

    
750
$btnldap->removeClass('btn-primary')->addClass('btn-default btn-sm');
751

    
752
$section->addInput(new Form_StaticText(
753
	'LDAP',
754
	$btnldap . '&nbsp;' . 'Show LDAP Configuration'
755
));
756

    
757
$section->addInput(new Form_Input(
758
	'ldap',
759
	'LDAP URI',
760
	'text',
761
	$pconfig['ldap']
762
));
763

    
764
$btnnetboot = new Form_Button(
765
	'btnnetboot',
766
	'Advanced'
767
);
768

    
769
$btnnetboot->removeClass('btn-primary')->addClass('btn-default btn-sm');
770

    
771
$section->addInput(new Form_StaticText(
772
	'Network booting',
773
	$btnnetboot . '&nbsp;' . 'Show Netwok booting'
774
));
775

    
776
$section->addInput(new Form_Checkbox(
777
	'shownetboot',
778
	'Network booting',
779
	'Enable Network Booting',
780
	$pconfig['shownetboot']
781
));
782

    
783
$section->addInput(new Form_Input(
784
	'bootfile_url',
785
	'Bootfile URL',
786
	'text',
787
	$pconfig['bootfile_url']
788
));
789

    
790
$btnadnl = new Form_Button(
791
	'btnadnl',
792
	'Advanced'
793
);
794

    
795
$btnadnl->removeClass('btn-primary')->addClass('btn-default btn-sm');
796

    
797
$section->addInput(new Form_StaticText(
798
	'Additional BOOTP/DHCP Options',
799
	$btnadnl . '&nbsp;' . 'Aditional BOOTP/DHCP Options'
800
));
801

    
802
$form->add($section);
803

    
804
$title = 'Show Additional BOOTP/DHCP Options';
805

    
806
if($pconfig['numberoptions']) {
807
	$counter = 0;
808
	$last = count($pconfig['numberoptions']['item']) - 1;
809

    
810
	foreach($pconfig['numberoptions']['item'] as $item) {
811
		$group = new Form_Group(null);
812

    
813
		$group->add(new Form_Input(
814
			'number' . $counter,
815
			null,
816
			'text',
817
			$item['number']
818
		))->setHelp($counter == $last ? 'Number':null);
819

    
820
		$group->add(new Form_Input(
821
			'value' . $counter,
822
			null,
823
			'text',
824
			$item['value']
825
		))->setHelp($counter == $last ? 'Value':null);
826

    
827
		$btn = new Form_Button(
828
			'btn' . $counter,
829
			'Delete',
830
			'services_dhcpv6.php?if=' . $if . '&act=delopt' . '&id=' . $counter
831
		);
832

    
833
		$btn->removeClass('btn-primary')->addClass('btn-danger btn-xs adnlopt');
834
		$group->addClass('adnlopt');
835
		$group->add($btn);
836
		$section->add($group);
837
		$counter++;
838
	}
839
}
840

    
841
$btnaddopt = new Form_Button(
842
	'btnaddopt',
843
	'Add Option',
844
	'services_dhcpv6.php?if=' . $if . '&act=addopt'
845
);
846

    
847
$btnaddopt->removeClass('btn-primary')->addClass('btn-success btn-sm');
848

    
849
$section->addInput($btnaddopt);
850

    
851
$section->addInput(new Form_Input(
852
	'if',
853
	null,
854
	'hidden',
855
	$if
856
));
857

    
858
print($form);
859

    
860
print_info_box(gettext('The DNS servers entered in ') . '<a href="system.php">' . gettext(' System: General setup') . '</a>' .
861
			   gettext(' (or the ') . '<a href="services_dnsmasq.php"/>' . gettext('DNS forwarder') . '</a>, ' . gettext('if enabled) ') .
862
			   gettext('will be assigned to clients by the DHCP server.') . '<br />' .
863
			   gettext('The DHCP lease table can be viewed on the ') . '<a href="status_dhcpv6_leases.php">' .
864
			   gettext('Status: DHCPv6 leases') . '</a>' . gettext(' page.'));
865
?>
866

    
867
<div class="panel panel-default">
868
	<div class="panel-heading"><h2 class="panel-title">DHCPv6 Static Mappings for this interface.</h2></div>
869
	<div class="panel-body table-responsive">
870
		<table class="table table-striped table-hover table-condensed">
871
			<thead>
872
				<tr>
873
					<th><?=gettext("DUID")?></th>
874
					<th><?=gettext("IPv6 address")?></th>
875
					<th><?=gettext("Hostname")?></th>
876
					<th><?=gettext("Description")?></th>
877
					<th><!-- Buttons --></th>
878
				</tr>
879
			</thead>
880
			<tbody>
881
<?php
882
if(is_array($a_maps)):
883
	$i = 0;
884
	foreach ($a_maps as $mapent):
885
		if($mapent['duid'] != "" or $mapent['ipaddrv6'] != ""):
886
?>
887
				<tr>
888
					<td>
889
						<?=htmlspecialchars($mapent['duid'])?>
890
					</td>
891
					<td>
892
						<?=htmlspecialchars($mapent['ipaddrv6'])?>
893
					</td>
894
					<td>
895
						<?=htmlspecialchars($mapent['hostname'])?>
896
					</td>
897
					<td>
898
						<?=htmlspecialchars($mapent['descr'])?>
899
					</td>
900
					<td>
901
						<a href="services_dhcpv6_edit.php?if=<?=$if?>&amp;id=<?=$i?>" class="btn btn-info btn-xs"/>Edit</a>
902
						<a href="services_dhcpv6.php?if=<?=$if?>&amp;act=del&amp;id=<?=$i?>" class="btn btn-danger btn-xs"/>Delete</a>
903
					</td>
904
				</tr>
905
<?php
906
		endif;
907
	$i++;
908
	endforeach;
909
endif;
910
?>
911
			</tbody>
912
		</table>
913
	</div>
914
</div>
915

    
916
<nav class="action-buttons">
917
	<a href="services_dhcpv6_edit.php?if=<?=$if?>" class="btn btn-sm btn-success"/>Add</a>
918
</nav>
919

    
920
<script>
921
//<![CDATA[
922
events.push(function(){
923
	// Hides the <div> in which the specified input element lives so that the input, its label and help text are hidden
924
	function hideInput(id, hide) {
925
		if(hide)
926
			$('#' + id).parent().parent('div').addClass('hidden');
927
		else
928
			$('#' + id).parent().parent('div').removeClass('hidden');
929
	}
930

    
931
	// Hides the <div> in which the specified icheckbox lives so that the input, its label and help text are hidden
932
	// Checkboxes live inside <label></label> tags so we need another parent level
933
	function hideCheckBox(id, hide) {
934
		if(hide)
935
			$('#' + id).parent().parent().parent('div').addClass('hidden');
936
		else
937
			$('#' + id).parent().parent().parent('div').removeClass('hidden');
938
	}
939

    
940
	// Hides all elements of the specified class. This will usually be a section or group
941
	function hideClass(s_class, hide) {
942
		if(hide)
943
			$('.' + s_class).hide();
944
		else
945
			$('.' + s_class).show();
946
	}
947

    
948
	function hideDDNS(hide) {
949
		hideCheckBox('ddnsupdate', hide);
950
		hideInput('ddnsdomain', hide);
951
		hideInput('ddnsdomainprimary', hide);
952
		hideInput('ddnsdomainkeyname', hide);
953
		hideInput('ddnsdomainkey', hide);
954
	}
955

    
956
	// Make the ‘Copy My MAC’ button a plain button, not a submit button
957
	$("#btnmymac").prop('type','button');
958

    
959
	// On click, copy the hidden 'mymac' text to the 'mac' input
960
	$("#btnmymac").click(function() {
961
		$('#mac').val('<?=$mymac?>');
962
	});
963

    
964
	// Make the ‘tftp’ button a plain button, not a submit button
965
	$("#btntftp").prop('type','button');
966

    
967
	// Show tftp controls
968
	$("#btntftp").click(function() {
969
		hideInput('tftp', false);
970
	});
971

    
972
	// Make the ‘ntp’ button a plain button, not a submit button
973
	$("#btnntp").prop('type','button');
974

    
975
	// Show ntp controls
976
	$("#btnntp").click(function() {
977
		hideClass('ntpclass', false);
978
	});
979

    
980
	// Make the ‘ddns’ button a plain button, not a submit button
981
	$("#btndyndns").prop('type','button');
982

    
983
	// Show ddns controls
984
	$("#btndyndns").click(function() {
985
		hideDDNS(false);
986
	});
987

    
988
	// Make the ‘ldap’ button a plain button, not a submit button
989
	$("#btnldap").prop('type','button');
990

    
991
	// Show ldap controls
992
	$("#btnldap").click(function() {
993
		hideInput('ldap', false);
994
	});
995

    
996
	// Make the ‘netboot’ button a plain button, not a submit button
997
	$("#btnnetboot").prop('type','button');
998

    
999
	// Show netboot controls
1000
	$("#btnnetboot").click(function() {
1001
		hideInput('bootfile_url', false);
1002
		hideCheckBox('shownetboot', false);
1003
	});
1004

    
1005
	// Make the ‘aditional options’ button a plain button, not a submit button
1006
	$("#btnadnl").prop('type','button');
1007

    
1008
	// Show aditional  controls
1009
	$("#btnadnl").click(function() {
1010
		hideClass('adnlopt', false);
1011
		hideInput('btnaddopt', false);
1012
	});
1013

    
1014
	// On initial load
1015
	hideDDNS(true);
1016
	hideClass('ntpclass', true);
1017
	hideInput('tftp', true);
1018
	hideInput('ldap', true);
1019
	hideInput('bootfile_url', true);
1020
	hideCheckBox('shownetboot', true);
1021
	hideClass('adnlopt', true);
1022
	hideInput('btnaddopt', true);
1023
});
1024
//]]>
1025
</script>
1026

    
1027
<?php include('foot.inc');
(135-135/237)