Project

General

Profile

Download (31.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	services_dhcpv6.php
5
*/
6
/* ====================================================================
7
 *	Copyright (c)  2004-2015  Electric Sheep Fencing, LLC. All rights reserved.
8
 *	Copyright (c)  2010 Seth Mos <seth.mos@dds.nl>
9
 *
10
 *  Some or all of this file is based on the m0n0wall project which is
11
 *  Copyright (c)  2004 Manuel Kasper (BSD 2 clause) 
12
 *
13
 *	Redistribution and use in source and binary forms, with or without modification,
14
 *	are permitted provided that the following conditions are met:
15
 *
16
 *	1. Redistributions of source code must retain the above copyright notice,
17
 *		this list of conditions and the following disclaimer.
18
 *
19
 *	2. Redistributions in binary form must reproduce the above copyright
20
 *		notice, this list of conditions and the following disclaimer in
21
 *		the documentation and/or other materials provided with the
22
 *		distribution.
23
 *
24
 *	3. All advertising materials mentioning features or use of this software
25
 *		must display the following acknowledgment:
26
 *		"This product includes software developed by the pfSense Project
27
 *		 for use in the pfSense software distribution. (http://www.pfsense.org/).
28
 *
29
 *	4. The names "pfSense" and "pfSense Project" must not be used to
30
 *		 endorse or promote products derived from this software without
31
 *		 prior written permission. For written permission, please contact
32
 *		 coreteam@pfsense.org.
33
 *
34
 *	5. Products derived from this software may not be called "pfSense"
35
 *		nor may "pfSense" appear in their names without prior written
36
 *		permission of the Electric Sheep Fencing, LLC.
37
 *
38
 *	6. Redistributions of any form whatsoever must retain the following
39
 *		acknowledgment:
40
 *
41
 *	"This product includes software developed by the pfSense Project
42
 *	for use in the pfSense software distribution (http://www.pfsense.org/).
43
 *
44
 *	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
45
 *	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46
 *	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47
 *	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
48
 *	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49
 *	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50
 *	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51
 *	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52
 *	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53
 *	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54
 *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55
 *	OF THE POSSIBILITY OF SUCH DAMAGE.
56
 *
57
 *	====================================================================
58
 *
59
 */
60
/*
61
	pfSense_BUILDER_BINARIES:	/bin/rm
62
	pfSense_MODULE: interfaces
63
*/
64

    
65
##|+PRIV
66
##|*IDENT=page-services-dhcpv6server
67
##|*NAME=Services: DHCPv6 server page
68
##|*DESCR=Allow access to the 'Services: DHCPv6 server' page.
69
##|*MATCH=services_dhcpv6.php*
70
##|-PRIV
71

    
72
require("guiconfig.inc");
73
require_once("filter.inc");
74

    
75
if (!$g['services_dhcp_server_enable']) {
76
	header("Location: /");
77
	exit;
78
}
79

    
80
/*	Fix failover DHCP problem
81
 *	http://article.gmane.org/gmane.comp.security.firewalls.pfsense.support/18749
82
 */
83
ini_set("memory_limit", "64M");
84

    
85
$if = $_GET['if'];
86
if ($_POST['if']) {
87
	$if = $_POST['if'];
88
}
89

    
90
/* if OLSRD is enabled, allow WAN to house DHCP. */
91
if ($config['installedpackages']['olsrd']) {
92
	foreach ($config['installedpackages']['olsrd']['config'] as $olsrd) {
93
		if ($olsrd['enable']) {
94
			$is_olsr_enabled = true;
95
			break;
96
		}
97
	}
98
}
99

    
100
$iflist = get_configured_interface_with_descr();
101
$iflist = array_merge($iflist, get_configured_pppoe_server_interfaces());
102

    
103
/* set the starting interface */
104
if (!$if || !isset($iflist[$if])) {
105
	foreach ($iflist as $ifent => $ifname) {
106
		$oc = $config['interfaces'][$ifent];
107

    
108
		if ((is_array($config['dhcpdv6'][$ifent]) && !isset($config['dhcpdv6'][$ifent]['enable']) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))) ||
109
			(!is_array($config['dhcpdv6'][$ifent]) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6']))))) {
110
			continue;
111
		}
112
		$if = $ifent;
113
		break;
114
	}
115
}
116

    
117
if (is_array($config['dhcpdv6'][$if])) {
118
	/* DHCPv6 */
119
	if (is_array($config['dhcpdv6'][$if]['range'])) {
120
		$pconfig['range_from'] = $config['dhcpdv6'][$if]['range']['from'];
121
		$pconfig['range_to'] = $config['dhcpdv6'][$if]['range']['to'];
122
	}
123
	if (is_array($config['dhcpdv6'][$if]['prefixrange'])) {
124
		$pconfig['prefixrange_from'] = $config['dhcpdv6'][$if]['prefixrange']['from'];
125
		$pconfig['prefixrange_to'] = $config['dhcpdv6'][$if]['prefixrange']['to'];
126
		$pconfig['prefixrange_length'] = $config['dhcpdv6'][$if]['prefixrange']['prefixlength'];
127
	}
128
	$pconfig['deftime'] = $config['dhcpdv6'][$if]['defaultleasetime'];
129
	$pconfig['maxtime'] = $config['dhcpdv6'][$if]['maxleasetime'];
130
	$pconfig['domain'] = $config['dhcpdv6'][$if]['domain'];
131
	$pconfig['domainsearchlist'] = $config['dhcpdv6'][$if]['domainsearchlist'];
132
	list($pconfig['wins1'], $pconfig['wins2']) = $config['dhcpdv6'][$if]['winsserver'];
133
	list($pconfig['dns1'], $pconfig['dns2'], $pconfig['dns3'], $pconfig['dns4']) = $config['dhcpdv6'][$if]['dnsserver'];
134
	$pconfig['enable'] = isset($config['dhcpdv6'][$if]['enable']);
135
	$pconfig['ddnsdomain'] = $config['dhcpdv6'][$if]['ddnsdomain'];
136
	$pconfig['ddnsdomainprimary'] = $config['dhcpdv6'][$if]['ddnsdomainprimary'];
137
	$pconfig['ddnsdomainkeyname'] = $config['dhcpdv6'][$if]['ddnsdomainkeyname'];
138
	$pconfig['ddnsdomainkey'] = $config['dhcpdv6'][$if]['ddnsdomainkey'];
139
	$pconfig['ddnsupdate'] = isset($config['dhcpdv6'][$if]['ddnsupdate']);
140
	list($pconfig['ntp1'], $pconfig['ntp2']) = $config['dhcpdv6'][$if]['ntpserver'];
141
	$pconfig['tftp'] = $config['dhcpdv6'][$if]['tftp'];
142
	$pconfig['ldap'] = $config['dhcpdv6'][$if]['ldap'];
143
	$pconfig['netboot'] = isset($config['dhcpdv6'][$if]['netboot']);
144
	$pconfig['bootfile_url'] = $config['dhcpdv6'][$if]['bootfile_url'];
145
	$pconfig['netmask'] = $config['dhcpdv6'][$if]['netmask'];
146
	$pconfig['numberoptions'] = $config['dhcpdv6'][$if]['numberoptions'];
147
	$pconfig['dhcpv6leaseinlocaltime'] = $config['dhcpdv6'][$if]['dhcpv6leaseinlocaltime'];
148
	if (!is_array($config['dhcpdv6'][$if]['staticmap'])) {
149
		$config['dhcpdv6'][$if]['staticmap'] = array();
150
	}
151
	$a_maps = &$config['dhcpdv6'][$if]['staticmap'];
152
}
153

    
154
$ifcfgip = get_interface_ipv6($if);
155
$ifcfgsn = get_interface_subnetv6($if);
156

    
157
/*	 set the enabled flag which will tell us if DHCP relay is enabled
158
 *	 on any interface. We will use this to disable DHCP server since
159
 *	 the two are not compatible with each other.
160
 */
161

    
162
$dhcrelay_enabled = false;
163
$dhcrelaycfg = $config['dhcrelay6'];
164

    
165
if (is_array($dhcrelaycfg)) {
166
	foreach ($dhcrelaycfg as $dhcrelayif => $dhcrelayifconf) {
167
		if (isset($dhcrelayifconf['enable']) && isset($iflist[$dhcrelayif]) &&
168
			(!link_interface_to_bridge($dhcrelayif))) {
169
			$dhcrelay_enabled = true;
170
		}
171
	}
172
}
173

    
174
if ($_POST) {
175
	unset($input_errors);
176

    
177
	$old_dhcpdv6_enable = ($pconfig['enable'] == true);
178
	$new_dhcpdv6_enable = ($_POST['enable'] ? true : false);
179
	$dhcpdv6_enable_changed = ($old_dhcpdv6_enable != $new_dhcpdv6_enable);
180

    
181
	$pconfig = $_POST;
182

    
183
	$numberoptions = array();
184
	for ($x = 0; $x < 99; $x++) {
185
		if (isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) {
186
			$numbervalue = array();
187
			$numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]);
188
			$numbervalue['value'] = htmlspecialchars($_POST["value{$x}"]);
189
			$numberoptions['item'][] = $numbervalue;
190
		}
191
	}
192
	// Reload the new pconfig variable that the forum uses.
193
	$pconfig['numberoptions'] = $numberoptions;
194

    
195
	/* input validation */
196
	if ($_POST['enable']) {
197
		$reqdfields = explode(" ", "range_from range_to");
198
		$reqdfieldsn = array(gettext("Range begin"), gettext("Range end"));
199

    
200
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
201

    
202
		if (($_POST['prefixrange_from'] && !is_ipaddrv6($_POST['prefixrange_from']))) {
203
			$input_errors[] = gettext("A valid range must be specified.");
204
		}
205
		if (($_POST['prefixrange_to'] && !is_ipaddrv6($_POST['prefixrange_to']))) {
206
			$input_errors[] = gettext("A valid prefix range must be specified.");
207
		}
208
		if (($_POST['range_from'] && !is_ipaddrv6($_POST['range_from']))) {
209
			$input_errors[] = gettext("A valid range must be specified.");
210
		}
211
		if (($_POST['range_to'] && !is_ipaddrv6($_POST['range_to']))) {
212
			$input_errors[] = gettext("A valid range must be specified.");
213
		}
214
		if (($_POST['gateway'] && !is_ipaddrv6($_POST['gateway']))) {
215
			$input_errors[] = gettext("A valid IPv6 address must be specified for the gateway.");
216
		}
217
		if (($_POST['dns1'] && !is_ipaddrv6($_POST['dns1'])) ||
218
			($_POST['dns2'] && !is_ipaddrv6($_POST['dns2'])) ||
219
			($_POST['dns3'] && !is_ipaddrv6($_POST['dns3'])) ||
220
			($_POST['dns4'] && !is_ipaddrv6($_POST['dns4']))) {
221
			$input_errors[] = gettext("A valid IPv6 address must be specified for each of the DNS servers.");
222
		}
223

    
224
		if ($_POST['deftime'] && (!is_numeric($_POST['deftime']) || ($_POST['deftime'] < 60))) {
225
			$input_errors[] = gettext("The default lease time must be at least 60 seconds.");
226
		}
227
		if ($_POST['maxtime'] && (!is_numeric($_POST['maxtime']) || ($_POST['maxtime'] < 60) || ($_POST['maxtime'] <= $_POST['deftime']))) {
228
			$input_errors[] = gettext("The maximum lease time must be at least 60 seconds and higher than the default lease time.");
229
		}
230
		if (($_POST['ddnsdomain'] && !is_domain($_POST['ddnsdomain']))) {
231
			$input_errors[] = gettext("A valid domain name must be specified for the dynamic DNS registration.");
232
		}
233
		if (($_POST['ddnsdomain'] && !is_ipaddrv4($_POST['ddnsdomainprimary']))) {
234
			$input_errors[] = gettext("A valid primary domain name server IPv4 address must be specified for the dynamic domain name.");
235
		}
236
		if (($_POST['ddnsdomainkey'] && !$_POST['ddnsdomainkeyname']) ||
237
			($_POST['ddnsdomainkeyname'] && !$_POST['ddnsdomainkey'])) {
238
			$input_errors[] = gettext("You must specify both a valid domain key and key name.");
239
		}
240
		if ($_POST['domainsearchlist']) {
241
			$domain_array=preg_split("/[ ;]+/", $_POST['domainsearchlist']);
242
			foreach ($domain_array as $curdomain) {
243
				if (!is_domain($curdomain)) {
244
					$input_errors[] = gettext("A valid domain search list must be specified.");
245
					break;
246
				}
247
			}
248
		}
249

    
250
		if (($_POST['ntp1'] && !is_ipaddrv6($_POST['ntp1'])) || ($_POST['ntp2'] && !is_ipaddrv6($_POST['ntp2']))) {
251
			$input_errors[] = gettext("A valid IPv6 address must be specified for the primary/secondary NTP servers.");
252
		}
253
		if (($_POST['domain'] && !is_domain($_POST['domain']))) {
254
			$input_errors[] = gettext("A valid domain name must be specified for the DNS domain.");
255
		}
256
		if ($_POST['tftp'] && !is_ipaddr($_POST['tftp']) && !is_domain($_POST['tftp']) && !is_URL($_POST['tftp'])) {
257
			$input_errors[] = gettext("A valid IPv6 address or hostname must be specified for the TFTP server.");
258
		}
259
		if (($_POST['bootfile_url'] && !is_URL($_POST['bootfile_url']))) {
260
			$input_errors[] = gettext("A valid URL must be specified for the network bootfile.");
261
		}
262

    
263
		// Disallow a range that includes the virtualip
264
		if (is_array($config['virtualip']['vip'])) {
265
			foreach ($config['virtualip']['vip'] as $vip) {
266
				if ($vip['interface'] == $if) {
267
					if ($vip['subnetv6'] && is_inrange_v6($vip['subnetv6'], $_POST['range_from'], $_POST['range_to'])) {
268
						$input_errors[] = sprintf(gettext("The subnet range cannot overlap with virtual IPv6 address %s."), $vip['subnetv6']);
269
					}
270
				}
271
			}
272
		}
273

    
274
		$noip = false;
275
		if (is_array($a_maps)) {
276
			foreach ($a_maps as $map) {
277
				if (empty($map['ipaddrv6'])) {
278
					$noip = true;
279
				}
280
			}
281
		}
282
		if (!$input_errors) {
283
			/* make sure the range lies within the current subnet */
284
			$subnet_start = gen_subnetv6($ifcfgip, $ifcfgsn);
285
			$subnet_end = gen_subnetv6_max($ifcfgip, $ifcfgsn);
286

    
287
			if (is_ipaddrv6($ifcfgip)) {
288
				if ((!is_inrange_v6($_POST['range_from'], $subnet_start, $subnet_end)) ||
289
					(!is_inrange_v6($_POST['range_to'], $subnet_start, $subnet_end))) {
290
					$input_errors[] = gettext("The specified range lies outside of the current subnet.");
291
				}
292
			}
293
			/* "from" cannot be higher than "to" */
294
			if (inet_pton($_POST['range_from']) > inet_pton($_POST['range_to'])) {
295
				$input_errors[] = gettext("The range is invalid (first element higher than second element).");
296
			}
297

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

    
303

    
304
			/* Verify static mappings do not overlap:
305
			   - available DHCP range
306
			   - prefix delegation range (FIXME: still need to be completed) */
307
			$dynsubnet_start = inet_pton($_POST['range_from']);
308
			$dynsubnet_end = inet_pton($_POST['range_to']);
309

    
310
			if (is_array($a_maps)) {
311
				foreach ($a_maps as $map) {
312
					if (empty($map['ipaddrv6'])) {
313
						continue;
314
					}
315
					if ((inet_pton($map['ipaddrv6']) > $dynsubnet_start) &&
316
						(inet_pton($map['ipaddrv6']) < $dynsubnet_end)) {
317
						$input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings."));
318
						break;
319
					}
320
				}
321
			}
322
		}
323
	}
324

    
325
	if (!$input_errors) {
326
		if (!is_array($config['dhcpdv6'][$if])) {
327
			$config['dhcpdv6'][$if] = array();
328
		}
329
		if (!is_array($config['dhcpdv6'][$if]['range'])) {
330
			$config['dhcpdv6'][$if]['range'] = array();
331
		}
332
		if (!is_array($config['dhcpdv6'][$if]['prefixrange'])) {
333
			$config['dhcpdv6'][$if]['prefixrange'] = array();
334
		}
335

    
336
		$config['dhcpdv6'][$if]['range']['from'] = $_POST['range_from'];
337
		$config['dhcpdv6'][$if]['range']['to'] = $_POST['range_to'];
338
		$config['dhcpdv6'][$if]['prefixrange']['from'] = $_POST['prefixrange_from'];
339
		$config['dhcpdv6'][$if]['prefixrange']['to'] = $_POST['prefixrange_to'];
340
		$config['dhcpdv6'][$if]['prefixrange']['prefixlength'] = $_POST['prefixrange_length'];
341
		$config['dhcpdv6'][$if]['defaultleasetime'] = $_POST['deftime'];
342
		$config['dhcpdv6'][$if]['maxleasetime'] = $_POST['maxtime'];
343
		$config['dhcpdv6'][$if]['netmask'] = $_POST['netmask'];
344

    
345
		unset($config['dhcpdv6'][$if]['winsserver']);
346

    
347
		unset($config['dhcpdv6'][$if]['dnsserver']);
348
		if ($_POST['dns1']) {
349
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns1'];
350
		}
351
		if ($_POST['dns2']) {
352
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns2'];
353
		}
354
		if ($_POST['dns3']) {
355
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns3'];
356
		}
357
		if ($_POST['dns4']) {
358
			$config['dhcpdv6'][$if]['dnsserver'][] = $_POST['dns4'];
359
		}
360

    
361
		$config['dhcpdv6'][$if]['domain'] = $_POST['domain'];
362
		$config['dhcpdv6'][$if]['domainsearchlist'] = $_POST['domainsearchlist'];
363
		$config['dhcpdv6'][$if]['enable'] = ($_POST['enable']) ? true : false;
364
		$config['dhcpdv6'][$if]['ddnsdomain'] = $_POST['ddnsdomain'];
365
		$config['dhcpdv6'][$if]['ddnsdomainprimary'] = $_POST['ddnsdomainprimary'];
366
		$config['dhcpdv6'][$if]['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname'];
367
		$config['dhcpdv6'][$if]['ddnsdomainkey'] = $_POST['ddnsdomainkey'];
368
		$config['dhcpdv6'][$if]['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false;
369

    
370
		unset($config['dhcpdv6'][$if]['ntpserver']);
371
		if ($_POST['ntp1']) {
372
			$config['dhcpdv6'][$if]['ntpserver'][] = $_POST['ntp1'];
373
		}
374
		if ($_POST['ntp2']) {
375
			$config['dhcpdv6'][$if]['ntpserver'][] = $_POST['ntp2'];
376
		}
377

    
378
		$config['dhcpdv6'][$if]['tftp'] = $_POST['tftp'];
379
		$config['dhcpdv6'][$if]['ldap'] = $_POST['ldap'];
380
		$config['dhcpdv6'][$if]['netboot'] = ($_POST['netboot']) ? true : false;
381
		$config['dhcpdv6'][$if]['bootfile_url'] = $_POST['bootfile_url'];
382
		$config['dhcpdv6'][$if]['dhcpv6leaseinlocaltime'] = $_POST['dhcpv6leaseinlocaltime'];
383

    
384
		// Handle the custom options rowhelper
385
		if (isset($config['dhcpdv6'][$if]['numberoptions']['item'])) {
386
			unset($config['dhcpdv6'][$if]['numberoptions']['item']);
387
		}
388

    
389
		$config['dhcpdv6'][$if]['numberoptions'] = $numberoptions;
390

    
391
		write_config();
392

    
393
		$retval = 0;
394
		$retvaldhcp = 0;
395
		$retvaldns = 0;
396
		/* Stop DHCPv6 so we can cleanup leases */
397
		killbypid("{$g['dhcpd_chroot_path']}{$g['varrun_path']}/dhcpdv6.pid");
398
		// dhcp_clean_leases();
399
		/* dnsmasq_configure calls dhcpd_configure */
400
		/* no need to restart dhcpd twice */
401
		if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic']))	{
402
			$retvaldns = services_dnsmasq_configure();
403
			if ($retvaldns == 0) {
404
				clear_subsystem_dirty('hosts');
405
				clear_subsystem_dirty('staticmaps');
406
			}
407
		} else if (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcpstatic'])) {
408
			$retvaldns = services_unbound_configure();
409
			if ($retvaldns == 0) {
410
				clear_subsystem_dirty('unbound');
411
				clear_subsystem_dirty('staticmaps');
412
			}
413
		} else {
414
			$retvaldhcp = services_dhcpd_configure();
415
			if ($retvaldhcp == 0) {
416
				clear_subsystem_dirty('staticmaps');
417
			}
418
		}
419
		if ($dhcpdv6_enable_changed) {
420
			$retvalfc = filter_configure();
421
		}
422
		if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) {
423
			$retval = 1;
424
		}
425
		$savemsg = get_std_save_message($retval);
426
	}
427
}
428

    
429
if ($_GET['act'] == "del") {
430
	if ($a_maps[$_GET['id']]) {
431
		unset($a_maps[$_GET['id']]);
432
		write_config();
433
		if (isset($config['dhcpdv6'][$if]['enable'])) {
434
			mark_subsystem_dirty('staticmapsv6');
435
			if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstaticv6'])) {
436
				mark_subsystem_dirty('hosts');
437
			}
438
		}
439
		header("Location: services_dhcpv6.php?if={$if}");
440
		exit;
441
	}
442
}
443

    
444
// Delete a row in the options table
445
if($_GET['act'] == "delopt") {
446
	$idx = $_GET['id'];
447

    
448
	if($pconfig['numberoptions'] && is_array($pconfig['numberoptions']['item'][$idx])) {
449
	   unset($pconfig['numberoptions']['item'][$idx]);
450
	}
451
}
452

    
453
// Add an option row
454
if($_GET['act'] == "addopt") {
455
	if(!is_array($pconfig['numberoptions']['item']))
456
		$pconfig['numberoptions']['item'] = array();
457

    
458
	array_push($pconfig['numberoptions']['item'], array('number' => null, 'value' => null));
459
}
460

    
461
$closehead = false;
462
$pgtitle = array(gettext("Services"), gettext("DHCPv6 Server"));
463
$shortcut_section = "dhcp6";
464

    
465
include("head.inc");
466

    
467
if ($input_errors)
468
	print_input_errors($input_errors);
469

    
470
if ($savemsg)
471
	print_info_box($savemsg, 'success');
472

    
473
if ($dhcrelay_enabled) {
474
	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');
475
	include("foot.inc");
476
	exit;
477
}
478

    
479
if (is_subsystem_dirty('staticmaps'))
480
	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.'));
481

    
482
/* active tabs */
483
$tab_array = array();
484
$tabscounter = 0;
485
$i = 0;
486

    
487
foreach ($iflist as $ifent => $ifname) {
488
	$oc = $config['interfaces'][$ifent];
489

    
490

    
491
	if((is_array($config['dhcpdv6'][$ifent]) && !isset($config['dhcpdv6'][$ifent]['enable']) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))) ||
492
		(!is_array($config['dhcpdv6'][$ifent]) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))))
493
		continue;
494

    
495
	if ($ifent == $if)
496
		$active = true;
497
	else
498
		$active = false;
499

    
500
	$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
501
	$tabscounter++;
502
}
503

    
504
/* tack on PPPoE or PPtP servers here */
505
/* pppoe server */
506
if (is_array($config['pppoes']['pppoe'])) {
507
	foreach($config['pppoes']['pppoe'] as $pppoe) {
508
		if ($pppoe['mode'] == "server") {
509
			$ifent = "poes". $pppoe['pppoeid'];
510
			$ifname = strtoupper($ifent);
511

    
512
			if ($ifent == $if)
513
				$active = true;
514
			else
515
				$active = false;
516

    
517
			$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
518
			$tabscounter++;
519
		}
520
	}
521
}
522

    
523
if ($tabscounter == 0) {
524
	print_info_box(gettext("The DHCPv6 Server can only be enabled on interfaces configured with a static IPv6 address. This system has none."), 'danger');
525
	include("foot.inc");
526
	exit;
527
}
528

    
529
display_top_tabs($tab_array);
530

    
531
$tab_array = array();
532
$tab_array[] = array(gettext("DHCPv6 Server"),		 true,	"services_dhcpv6.php?if={$if}");
533
$tab_array[] = array(gettext("Router Advertisements"), false, "services_router_advertisements.php?if={$if}");
534
display_top_tabs($tab_array, false, 'nav nav-tabs' );
535

    
536
require_once('classes/Form.class.php');
537

    
538
$form = new Form(new Form_Button(
539
	'Submit',
540
	'Save'
541
));
542

    
543
$section = new Form_Section('DHCPv6 Options');
544

    
545
$section->addInput(new Form_Checkbox(
546
	'enable',
547
	'DHCPv6 Server',
548
	'Enable DHCPv6 server on interface ' . $iflist[$if],
549
	$pconfig['enable']
550
))->toggles('.form-group:not(:first-child)');
551

    
552
if(is_ipaddrv6($ifcfgip)) {
553

    
554
	$section->addInput(new Form_StaticText(
555
		'Subnet',
556
		gen_subnetv6($ifcfgip, $ifcfgsn)
557
		));
558

    
559
	$section->addInput(new Form_StaticText(
560
		'Subnet Mask',
561
		$ifcfgsn . ' bits'
562
		));
563

    
564
	$section->addInput(new Form_StaticText(
565
		'Available Range',
566
		$range_from = gen_subnetv6($ifcfgip, $ifcfgsn) . ' to ' . gen_subnetv6_max($ifcfgip, $ifcfgsn)
567
		));
568
}
569

    
570
if($is_olsr_enabled) {
571
	$section->addInput(new Form_Select(
572
	'netmask',
573
	'Subnet Mask',
574
	$pconfig['netmask'],
575
	array_combine(range(128, 1, -1), range(128, 1, -1))
576
	));
577
}
578

    
579
$f1 = new Form_Input(
580
	'range_from',
581
	null,
582
	'text',
583
	$pconfig['range_from']
584
);
585

    
586
$f1->setHelp('To');
587

    
588
$f2 = new Form_Input(
589
	'range_to',
590
	null,
591
	'text',
592
	$pconfig['range_to']
593
);
594

    
595
$f2->setHelp('From');
596

    
597
$group = new Form_Group('Range');
598

    
599
$group->add($f1);
600
$group->add($f2);
601

    
602
$section->add($group);
603

    
604
$f1 = new Form_Input(
605
	'prefix_from',
606
	null,
607
	'text',
608
	$pconfig['prefix_from']
609
);
610

    
611
$f1->setHelp('To');
612

    
613
$f2 = new Form_Input(
614
	'prefix_to',
615
	null,
616
	'text',
617
	$pconfig['prefix_to']
618
);
619

    
620
$f2->setHelp('From');
621
$group = new Form_Group('Prefix Delegation Range');
622

    
623
$group->add($f1);
624
$group->add($f2);
625

    
626
$section->add($group);
627

    
628
$section->addInput(new Form_Select(
629
	'prefixrange_length',
630
	'Prefix Delegation Size',
631
	$pconfig['prefixrange_length'],
632
	array(
633
		'48' => '48',
634
		'52' => '52',
635
		'56' => '56',
636
		'60' => '60',
637
		'62' => '62',
638
		'63' => '63',
639
		'64' => '64'
640
		)
641
))->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.');
642

    
643
$group = new Form_Group('DNS Servers');
644

    
645
for($i=1;$i<=4; $i++) {
646
	$group->add(new Form_input(
647
		'dns' . $i,
648
		null,
649
		'text',
650
		$pconfig['dns' . $i],
651
		['placeholder' => 'DNS ' . $i]
652
	));
653
}
654

    
655
$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.');
656
$section->add($group);
657

    
658
$section->addInput(new Form_Input(
659
	'domain',
660
	'Domain Name',
661
	'text',
662
	$pconfig['domain']
663
))->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. ');
664

    
665
$section->addInput(new Form_Input(
666
	'domainsearchlist',
667
	'Domain search list',
668
	'text',
669
	$pconfig['domainsearchlist']
670
))->setHelp('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator');
671

    
672
$section->addInput(new Form_Input(
673
	'deftime',
674
	'Default lease time',
675
	'text',
676
	$pconfig['deftime']
677
))->setHelp('Seconds . Used for clients that do not ask for a specific expiration time. ' . ' <br />' .
678
			'The default is 7200 seconds.');
679

    
680
$section->addInput(new Form_Input(
681
	'maxtime',
682
	'Max lease time',
683
	'text',
684
	$pconfig['maxtime']
685
))->setHelp('Maximum lease time for clients that ask for a specific expiration time.' . ' <br />' .
686
			'The default is 86400 seconds.');
687

    
688
$section->addInput(new Form_Checkbox(
689
	'dhcpv6leaseinlocaltime',
690
	'Time Format Change',
691
	'Change DHCPv6 display lease time from UTC to local time',
692
	$pconfig['dhcpv6leaseinlocaltime']
693
))->setHelp('By default DHCPv6 leases are displayed in UTC time. ' .
694
			'By checking this box DHCPv6 lease time will be displayed in local time and set to time zone selected. ' .
695
			'This will be used for all DHCPv6 interfaces lease time.');
696

    
697
$btndyndns = new Form_Button(
698
	'btndyndns',
699
	'Advanced'
700
);
701

    
702
$btndyndns->removeClass('btn-primary')->addClass('btn-default btn-sm');
703

    
704
$section->addInput(new Form_StaticText(
705
	'Dynamic DNS',
706
	$btndyndns . '&nbsp;' . 'Show dynamic DNS settings'
707
));
708

    
709
$section->addInput(new Form_Checkbox(
710
	'ddnsupdate',
711
	'DHCP Registration',
712
	'Enable registration of DHCP client names in DNS.',
713
	$pconfig['ddnsupdate']
714
));
715

    
716
$section->addInput(new Form_Input(
717
	'ddnsdomain',
718
	'DDNS Domain',
719
	'text',
720
	$pconfig['ddnsdomain']
721
))->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.');
722

    
723
$section->addInput(new Form_IpAddress(
724
	'ddnsdomainprimary',
725
	'DDNS Server IP',
726
	$pconfig['ddnsdomainprimary']
727
))->setHelp('Enter the primary domain name server IP address for the dynamic domain name.');
728

    
729
$section->addInput(new Form_Input(
730
	'ddnsdomainkeyname',
731
	'DDNS Domain Key name',
732
	'text',
733
	$pconfig['ddnsdomainkeyname']
734
))->setHelp('Enter the dynamic DNS domain key name which will be used to register client names in the DNS server.');
735

    
736
$section->addInput(new Form_Input(
737
	'ddnsdomainkey',
738
	'DDNS Domain Key secret',
739
	'text',
740
	$pconfig['ddnsdomainkey']
741
))->setHelp('Enter the dynamic DNS domain key secret which will be used to register client names in the DNS server.');
742

    
743
$btnntp = new Form_Button(
744
	'btnntp',
745
	'Advanced'
746
);
747

    
748
$btnntp->removeClass('btn-primary')->addClass('btn-default btn-sm');
749

    
750
$section->addInput(new Form_StaticText(
751
	'NTP servers',
752
	$btnntp . '&nbsp;' . 'Show NTP Configuration'
753
));
754

    
755
$group = new Form_Group('NTP Servers');
756

    
757
$group->add(new Form_Input(
758
	'ntp1',
759
	'NTP Server 1',
760
	'text',
761
	$pconfig['ntp1'],
762
	['placeholder' => 'NTP 1']
763
));
764

    
765
$group->add(new Form_Input(
766
	'ntp2',
767
	'NTP Server 2',
768
	'text',
769
	$pconfig['ntp2'],
770
	['placeholder' => 'NTP 2']
771
));
772

    
773
$group->addClass('ntpclass');
774

    
775
$section->add($group);
776

    
777
$btnldap = new Form_Button(
778
	'btnldap',
779
	'Advanced'
780
);
781

    
782
$btnldap->removeClass('btn-primary')->addClass('btn-default btn-sm');
783

    
784
$section->addInput(new Form_StaticText(
785
	'LDAP',
786
	$btnldap . '&nbsp;' . 'Show LDAP Configuration'
787
));
788

    
789
$section->addInput(new Form_Input(
790
	'ldap',
791
	'LDAP URI',
792
	'text',
793
	$pconfig['ldap']
794
));
795

    
796
$btnnetboot = new Form_Button(
797
	'btnnetboot',
798
	'Advanced'
799
);
800

    
801
$btnnetboot->removeClass('btn-primary')->addClass('btn-default btn-sm');
802

    
803
$section->addInput(new Form_StaticText(
804
	'Network booting',
805
	$btnnetboot . '&nbsp;' . 'Show Network booting'
806
));
807

    
808
$section->addInput(new Form_Checkbox(
809
	'shownetboot',
810
	'Network booting',
811
	'Enable Network Booting',
812
	$pconfig['shownetboot']
813
));
814

    
815
$section->addInput(new Form_Input(
816
	'bootfile_url',
817
	'Bootfile URL',
818
	'text',
819
	$pconfig['bootfile_url']
820
));
821

    
822
$btnadnl = new Form_Button(
823
	'btnadnl',
824
	'Advanced'
825
);
826

    
827
$btnadnl->removeClass('btn-primary')->addClass('btn-default btn-sm');
828

    
829
$section->addInput(new Form_StaticText(
830
	'Additional BOOTP/DHCP Options',
831
	$btnadnl . '&nbsp;' . 'Additional BOOTP/DHCP Options'
832
));
833

    
834
$form->add($section);
835

    
836
$title = 'Show Additional BOOTP/DHCP Options';
837

    
838
if($pconfig['numberoptions']) {
839
	$counter = 0;
840
	$last = count($pconfig['numberoptions']['item']) - 1;
841

    
842
	foreach($pconfig['numberoptions']['item'] as $item) {
843
		$group = new Form_Group(null);
844

    
845
		$group->add(new Form_Input(
846
			'number' . $counter,
847
			null,
848
			'text',
849
			$item['number']
850
		))->setHelp($counter == $last ? 'Number':null);
851

    
852
		$group->add(new Form_Input(
853
			'value' . $counter,
854
			null,
855
			'text',
856
			$item['value']
857
		))->setHelp($counter == $last ? 'Value':null);
858

    
859
		$btn = new Form_Button(
860
			'btn' . $counter,
861
			'Delete',
862
			'services_dhcpv6.php?if=' . $if . '&act=delopt' . '&id=' . $counter
863
		);
864

    
865
		$btn->removeClass('btn-primary')->addClass('btn-danger btn-xs adnlopt');
866
		$group->addClass('adnlopt');
867
		$group->add($btn);
868
		$section->add($group);
869
		$counter++;
870
	}
871
}
872

    
873
$btnaddopt = new Form_Button(
874
	'btnaddopt',
875
	'Add Option',
876
	'services_dhcpv6.php?if=' . $if . '&act=addopt'
877
);
878

    
879
$btnaddopt->removeClass('btn-primary')->addClass('btn-success btn-sm');
880

    
881
$section->addInput($btnaddopt);
882

    
883
$section->addInput(new Form_Input(
884
	'if',
885
	null,
886
	'hidden',
887
	$if
888
));
889

    
890
print($form);
891

    
892
print_info_box(gettext('The DNS servers entered in ') . '<a href="system.php">' . gettext(' System: General setup') . '</a>' .
893
			   gettext(' (or the ') . '<a href="services_dnsmasq.php"/>' . gettext('DNS forwarder') . '</a>, ' . gettext('if enabled) ') .
894
			   gettext('will be assigned to clients by the DHCP server.') . '<br />' .
895
			   gettext('The DHCP lease table can be viewed on the ') . '<a href="status_dhcpv6_leases.php">' .
896
			   gettext('Status: DHCPv6 leases') . '</a>' . gettext(' page.'));
897
?>
898

    
899
<div class="panel panel-default">
900
	<div class="panel-heading"><h2 class="panel-title">DHCPv6 Static Mappings for this interface.</h2></div>
901
	<div class="panel-body table-responsive">
902
		<table class="table table-striped table-hover table-condensed">
903
			<thead>
904
				<tr>
905
					<th><?=gettext("DUID")?></th>
906
					<th><?=gettext("IPv6 address")?></th>
907
					<th><?=gettext("Hostname")?></th>
908
					<th><?=gettext("Description")?></th>
909
					<th><!-- Buttons --></th>
910
				</tr>
911
			</thead>
912
			<tbody>
913
<?php
914
if(is_array($a_maps)):
915
	$i = 0;
916
	foreach ($a_maps as $mapent):
917
		if($mapent['duid'] != "" or $mapent['ipaddrv6'] != ""):
918
?>
919
				<tr>
920
					<td>
921
						<?=htmlspecialchars($mapent['duid'])?>
922
					</td>
923
					<td>
924
						<?=htmlspecialchars($mapent['ipaddrv6'])?>
925
					</td>
926
					<td>
927
						<?=htmlspecialchars($mapent['hostname'])?>
928
					</td>
929
					<td>
930
						<?=htmlspecialchars($mapent['descr'])?>
931
					</td>
932
					<td>
933
						<a class="fa fa-pencil"	title="<?=gettext('Edit static mapping')?>" href="services_dhcpv6_edit.php?if=<?=$if?>&amp;id=<?=$i?>"></a>
934
						<a class="fa fa-trash"	title="<?=gettext('Delete static mapping')?>" href="services_dhcpv6.php?if=<?=$if?>&amp;act=del&amp;id=<?=$i?>"></a>
935
					</td>
936
				</tr>
937
<?php
938
		endif;
939
	$i++;
940
	endforeach;
941
endif;
942
?>
943
			</tbody>
944
		</table>
945
	</div>
946
</div>
947

    
948
<nav class="action-buttons">
949
	<a href="services_dhcpv6_edit.php?if=<?=$if?>" class="btn btn-sm btn-success"/>
950
		<i class="fa fa-plus icon-embed-btn"></i>
951
		<?=gettext("Add")?>
952
	</a>
953
</nav>
954

    
955
<script>
956
//<![CDATA[
957
events.push(function(){
958

    
959
	function hideDDNS(hide) {
960
		hideCheckBox('ddnsupdate', hide);
961
		hideInput('ddnsdomain', hide);
962
		hideInput('ddnsdomainprimary', hide);
963
		hideInput('ddnsdomainkeyname', hide);
964
		hideInput('ddnsdomainkey', hide);
965
	}
966

    
967
	// Make the 'Copy My MAC' button a plain button, not a submit button
968
	$("#btnmymac").prop('type','button');
969

    
970
	// On click, copy the hidden 'mymac' text to the 'mac' input
971
	$("#btnmymac").click(function() {
972
		$('#mac').val('<?=$mymac?>');
973
	});
974

    
975
	// Make the 'tftp' button a plain button, not a submit button
976
	$("#btntftp").prop('type','button');
977

    
978
	// Show tftp controls
979
	$("#btntftp").click(function() {
980
		hideInput('tftp', false);
981
	});
982

    
983
	// Make the 'ntp' button a plain button, not a submit button
984
	$("#btnntp").prop('type','button');
985

    
986
	// Show ntp controls
987
	$("#btnntp").click(function() {
988
		hideClass('ntpclass', false);
989
	});
990

    
991
	// Make the 'ddns' button a plain button, not a submit button
992
	$("#btndyndns").prop('type','button');
993

    
994
	// Show ddns controls
995
	$("#btndyndns").click(function() {
996
		hideDDNS(false);
997
	});
998

    
999
	// Make the 'ldap' button a plain button, not a submit button
1000
	$("#btnldap").prop('type','button');
1001

    
1002
	// Show ldap controls
1003
	$("#btnldap").click(function() {
1004
		hideInput('ldap', false);
1005
	});
1006

    
1007
	// Make the 'netboot' button a plain button, not a submit button
1008
	$("#btnnetboot").prop('type','button');
1009

    
1010
	// Show netboot controls
1011
	$("#btnnetboot").click(function() {
1012
		hideInput('bootfile_url', false);
1013
		hideCheckBox('shownetboot', false);
1014
	});
1015

    
1016
	// Make the 'additional options' button a plain button, not a submit button
1017
	$("#btnadnl").prop('type','button');
1018

    
1019
	// Show additional  controls
1020
	$("#btnadnl").click(function() {
1021
		hideClass('adnlopt', false);
1022
		hideInput('btnaddopt', false);
1023
	});
1024

    
1025
	// On initial load
1026
	hideDDNS(true);
1027
	hideClass('ntpclass', true);
1028
	hideInput('tftp', true);
1029
	hideInput('ldap', true);
1030
	hideInput('bootfile_url', true);
1031
	hideCheckBox('shownetboot', true);
1032
	hideClass('adnlopt', true);
1033
	hideInput('btnaddopt', true);
1034
});
1035
//]]>
1036
</script>
1037

    
1038
<?php include('foot.inc');
(135-135/234)