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

    
84
		if ((is_array($config['dhcpdv6'][$ifent]) && !isset($config['dhcpdv6'][$ifent]['enable']) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))) ||
85
			(!is_array($config['dhcpdv6'][$ifent]) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6']))))) {
86
			continue;
87
		}
88
		$if = $ifent;
89
		break;
90
	}
91
}
92

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

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

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

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

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

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

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

    
157
	$pconfig = $_POST;
158

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

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

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

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

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

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

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

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

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

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

    
279

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

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

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

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

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

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

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

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

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

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

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

    
367
		write_config();
368

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

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

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

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

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

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

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

    
441
include("head.inc");
442

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

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

    
449
if ($dhcrelay_enabled) {
450
	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');
451
	include("foot.inc");
452
	exit;
453
}
454

    
455
if (is_subsystem_dirty('staticmaps'))
456
	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.'));
457

    
458
/* active tabs */
459
$tab_array = array();
460
$tabscounter = 0;
461
$i = 0;
462

    
463
foreach ($iflist as $ifent => $ifname) {
464
	$oc = $config['interfaces'][$ifent];
465

    
466

    
467
	if((is_array($config['dhcpdv6'][$ifent]) && !isset($config['dhcpdv6'][$ifent]['enable']) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))) ||
468
		(!is_array($config['dhcpdv6'][$ifent]) && !(is_ipaddrv6($oc['ipaddrv6']) && (!is_linklocal($oc['ipaddrv6'])))))
469
		continue;
470

    
471
	if ($ifent == $if)
472
		$active = true;
473
	else
474
		$active = false;
475

    
476
	$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
477
	$tabscounter++;
478
}
479

    
480
/* tack on PPPoE or PPtP servers here */
481
/* pppoe server */
482
if (is_array($config['pppoes']['pppoe'])) {
483
	foreach($config['pppoes']['pppoe'] as $pppoe) {
484
		if ($pppoe['mode'] == "server") {
485
			$ifent = "poes". $pppoe['pppoeid'];
486
			$ifname = strtoupper($ifent);
487

    
488
			if ($ifent == $if)
489
				$active = true;
490
			else
491
				$active = false;
492

    
493
			$tab_array[] = array($ifname, $active, "services_dhcpv6.php?if={$ifent}");
494
			$tabscounter++;
495
		}
496
	}
497
}
498

    
499
if ($tabscounter == 0) {
500
	print_info_box(gettext("The DHCPv6 Server can only be enabled on interfaces configured with a static IPv6 address. This system has none."), 'danger');
501
	include("foot.inc");
502
	exit;
503
}
504

    
505
$tab_array = array();
506
$tab_array[] = array(gettext("DHCPv6 Server"),		 true,	"services_dhcpv6.php?if={$if}");
507
$tab_array[] = array(gettext("Router Advertisements"), false, "services_router_advertisements.php?if={$if}");
508
display_top_tabs($tab_array);
509

    
510
require_once('classes/Form.class.php');
511

    
512
$form = new Form(new Form_Button(
513
	'Submit',
514
	'Save'
515
));
516

    
517
$section = new Form_Section('DHCPv6 Options');
518

    
519
$section->addInput(new Form_Checkbox(
520
	'enable',
521
	'DHCPv6 Server',
522
	'Enable DHCPv6 server on interface ' . $iflist[$if],
523
	$pconfig['enable']
524
))->toggles('.form-group:not(:first-child)');
525

    
526
if(is_ipaddrv6($ifcfgip)) {
527

    
528
	$section->addInput(new Form_StaticText(
529
		'Subnet',
530
		gen_subnetv6($ifcfgip, $ifcfgsn)
531
		));
532

    
533
	$section->addInput(new Form_StaticText(
534
		'Subnet Mask',
535
		$ifcfgsn . ' bits'
536
		));
537

    
538
	$section->addInput(new Form_StaticText(
539
		'Available Range',
540
		$range_from = gen_subnetv6($ifcfgip, $ifcfgsn) . ' to ' . gen_subnetv6_max($ifcfgip, $ifcfgsn)
541
		));
542
}
543

    
544
if($is_olsr_enabled) {
545
	$section->addInput(new Form_Select(
546
	'netmask',
547
	'Subnetmask',
548
	$pconfig['netmask'],
549
	array_combine(range(128, 1, -1), range(128, 1, -1))
550
	));
551
}
552

    
553
$f1 = new Form_Input(
554
	'range_from',
555
	null,
556
	'text',
557
	$pconfig['range_from']
558
);
559

    
560
$f1->setHelp('To');
561

    
562
$f2 = new Form_Input(
563
	'range_to',
564
	null,
565
	'text',
566
	$pconfig['range_to']
567
);
568

    
569
$f2->setHelp('From');
570

    
571
$group = new Form_Group('Range');
572

    
573
$group->add($f1);
574
$group->add($f2);
575

    
576
$section->add($group);
577

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

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

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

    
594
$f2->setHelp('From');
595
$group = new Form_Group('Prefix Delegation Range');
596

    
597
$group->add($f1);
598
$group->add($f2);
599

    
600
$section->add($group);
601

    
602
$section->addInput(new Form_Select(
603
	'prefixrange_length',
604
	'Prefix Delegation Size',
605
	$pconfig['prefixrange_length'],
606
	array(
607
		'48' => '48',
608
		'52' => '52',
609
		'56' => '56',
610
		'60' => '60',
611
		'62' => '62',
612
		'63' => '63',
613
		'64' => '64'
614
		)
615
))->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.');
616

    
617
$group = new Form_Group('DNS Servers');
618

    
619
for($i=1;$i<=4; $i++) {
620
	$group->add(new Form_input(
621
		'dns' . $i,
622
		null,
623
		'text',
624
		$pconfig['dns' . $i]
625
	))->setHelp('DNS ' . $i);
626
}
627

    
628
$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.');
629
$section->add($group);
630

    
631
$section->addInput(new Form_Input(
632
	'domain',
633
	'Domain Name',
634
	'text',
635
	$pconfig['domain']
636
))->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. ');
637

    
638
$section->addInput(new Form_Input(
639
	'domainsearchlist',
640
	'Domain search list',
641
	'text',
642
	$pconfig['domainsearchlist']
643
))->setHelp('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator');
644

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

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

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

    
670
$btndyndns = new Form_Button(
671
	'btndyndns',
672
	'Advanced'
673
);
674

    
675
$btndyndns->removeClass('btn-primary')->addClass('btn-default btn-sm');
676

    
677
$section->addInput(new Form_StaticText(
678
	'Dynamic DNS',
679
	$btndyndns . '&nbsp;' . 'Show dynamic DNS settings'
680
));
681

    
682
$section->addInput(new Form_Checkbox(
683
	'ddnsupdate',
684
	'DHCP Registration',
685
	'Enable registration of DHCP client names in DNS.',
686
	$pconfig['ddnsupdate']
687
));
688

    
689
$section->addInput(new Form_Input(
690
	'ddnsdomain',
691
	'DDNS Domain',
692
	'text',
693
	$pconfig['ddnsdomain']
694
))->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.');
695

    
696
$section->addInput(new Form_IpAddress(
697
	'ddnsdomainprimary',
698
	'DDNS Server IP',
699
	$pconfig['ddnsdomainprimary']
700
))->setHelp('Enter the primary domain name server IP address for the dynamic domain name.');
701

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

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

    
716
$btnntp = new Form_Button(
717
	'btnntp',
718
	'Advanced'
719
);
720

    
721
$btnntp->removeClass('btn-primary')->addClass('btn-default btn-sm');
722

    
723
$section->addInput(new Form_StaticText(
724
	'NTP servers',
725
	$btnntp . '&nbsp;' . 'Show NTP Configuration'
726
));
727

    
728
$group = new Form_Group('NTP Servers');
729

    
730
$group->add(new Form_Input(
731
	'ntp1',
732
	'NTP Server 1',
733
	'text',
734
	$pconfig['ntp1'],
735
	['placeholder' => 'NTP 1']
736
));
737

    
738
$group->add(new Form_Input(
739
	'ntp2',
740
	'NTP Server 1',
741
	'text',
742
	$pconfig['ntp2'],
743
	['placeholder' => 'NTP 2']
744
));
745

    
746
$group->addClass('ntpclass');
747

    
748
$section->add($group);
749

    
750
$btnldap = new Form_Button(
751
	'btnldap',
752
	'Advanced'
753
);
754

    
755
$btnldap->removeClass('btn-primary')->addClass('btn-default btn-sm');
756

    
757
$section->addInput(new Form_StaticText(
758
	'LDAP',
759
	$btnldap . '&nbsp;' . 'Show LDAP Configuration'
760
));
761

    
762
$section->addInput(new Form_Input(
763
	'ldap',
764
	'LDAP URI',
765
	'text',
766
	$pconfig['ldap']
767
));
768

    
769
$btnnetboot = new Form_Button(
770
	'btnnetboot',
771
	'Advanced'
772
);
773

    
774
$btnnetboot->removeClass('btn-primary')->addClass('btn-default btn-sm');
775

    
776
$section->addInput(new Form_StaticText(
777
	'Network booting',
778
	$btnnetboot . '&nbsp;' . 'Show Netwok booting'
779
));
780

    
781
$section->addInput(new Form_Checkbox(
782
	'shownetboot',
783
	'Network booting',
784
	'Enable Network Booting',
785
	$pconfig['shownetboot']
786
));
787

    
788
$section->addInput(new Form_Input(
789
	'bootfile_url',
790
	'Bootfile URL',
791
	'text',
792
	$pconfig['bootfile_url']
793
));
794

    
795
$btnadnl = new Form_Button(
796
	'btnadnl',
797
	'Advanced'
798
);
799

    
800
$btnadnl->removeClass('btn-primary')->addClass('btn-default btn-sm');
801

    
802
$section->addInput(new Form_StaticText(
803
	'Additional BOOTP/DHCP Options',
804
	$btnadnl . '&nbsp;' . 'Aditional BOOTP/DHCP Options'
805
));
806

    
807
$form->add($section);
808

    
809
$title = 'Show Additional BOOTP/DHCP Options';
810

    
811
if($pconfig['numberoptions']) {
812
	$counter = 0;
813
	$last = count($pconfig['numberoptions']['item']) - 1;
814

    
815
	foreach($pconfig['numberoptions']['item'] as $item) {
816
		$group = new Form_Group(null);
817

    
818
		$group->add(new Form_Input(
819
			'number' . $counter,
820
			null,
821
			'text',
822
			$item['number']
823
		))->setHelp($counter == $last ? 'Number':null);
824

    
825
		$group->add(new Form_Input(
826
			'value' . $counter,
827
			null,
828
			'text',
829
			$item['value']
830
		))->setHelp($counter == $last ? 'Value':null);
831

    
832
		$btn = new Form_Button(
833
			'btn' . $counter,
834
			'Delete',
835
			'services_dhcpv6.php?if=' . $if . '&act=delopt' . '&id=' . $counter
836
		);
837

    
838
		$btn->removeClass('btn-primary')->addClass('btn-danger btn-xs adnlopt');
839
		$group->addClass('adnlopt');
840
		$group->add($btn);
841
		$section->add($group);
842
		$counter++;
843
	}
844
}
845

    
846
$btnaddopt = new Form_Button(
847
	'btnaddopt',
848
	'Add Option',
849
	'services_dhcpv6.php?if=' . $if . '&act=addopt'
850
);
851

    
852
$btnaddopt->removeClass('btn-primary')->addClass('btn-success btn-sm');
853

    
854
$section->addInput($btnaddopt);
855

    
856
$section->addInput(new Form_Input(
857
	'if',
858
	null,
859
	'hidden',
860
	$if
861
));
862

    
863
print($form);
864

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

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

    
921
<nav class="action-buttons">
922
	<a href="services_dhcpv6_edit.php?if=<?=$if?>" class="btn btn-sm btn-success"/>Add</a>
923
</nav>
924

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

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

    
945
	// Hides all elements of the specified class. This will usually be a section or group
946
	function hideClass(s_class, hide) {
947
		if(hide)
948
			$('.' + s_class).hide();
949
		else
950
			$('.' + s_class).show();
951
	}
952

    
953
	function hideDDNS(hide) {
954
		hideCheckBox('ddnsupdate', hide);
955
		hideInput('ddnsdomain', hide);
956
		hideInput('ddnsdomainprimary', hide);
957
		hideInput('ddnsdomainkeyname', hide);
958
		hideInput('ddnsdomainkey', hide);
959
	}
960

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

    
964
	// On click, copy the hidden 'mymac' text to the 'mac' input
965
	$("#btnmymac").click(function() {
966
		$('#mac').val('<?=$mymac?>');
967
	});
968

    
969
	// Make the ‘tftp’ button a plain button, not a submit button
970
	$("#btntftp").prop('type','button');
971

    
972
	// Show tftp controls
973
	$("#btntftp").click(function() {
974
		hideInput('tftp', false);
975
	});
976

    
977
	// Make the ‘ntp’ button a plain button, not a submit button
978
	$("#btnntp").prop('type','button');
979

    
980
	// Show ntp controls
981
	$("#btnntp").click(function() {
982
		hideClass('ntpclass', false);
983
	});
984

    
985
	// Make the ‘ddns’ button a plain button, not a submit button
986
	$("#btndyndns").prop('type','button');
987

    
988
	// Show ddns controls
989
	$("#btndyndns").click(function() {
990
		hideDDNS(false);
991
	});
992

    
993
	// Make the ‘ldap’ button a plain button, not a submit button
994
	$("#btnldap").prop('type','button');
995

    
996
	// Show ldap controls
997
	$("#btnldap").click(function() {
998
		hideInput('ldap', false);
999
	});
1000

    
1001
	// Make the ‘netboot’ button a plain button, not a submit button
1002
	$("#btnnetboot").prop('type','button');
1003

    
1004
	// Show netboot controls
1005
	$("#btnnetboot").click(function() {
1006
		hideInput('bootfile_url', false);
1007
		hideCheckBox('shownetboot', false);
1008
	});
1009

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

    
1013
	// Show aditional  controls
1014
	$("#btnadnl").click(function() {
1015
		hideClass('adnlopt', false);
1016
		hideInput('btnaddopt', false);
1017
	});
1018

    
1019
	// On initial load
1020
	hideDDNS(true);
1021
	hideClass('ntpclass', true);
1022
	hideInput('tftp', true);
1023
	hideInput('ldap', true);
1024
	hideInput('bootfile_url', true);
1025
	hideCheckBox('shownetboot', true);
1026
	hideClass('adnlopt', true);
1027
	hideInput('btnaddopt', true);
1028
});
1029
//]]>
1030
</script>
1031

    
1032
<?php include('foot.inc');
(136-136/235)