Project

General

Profile

Download (56.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * services_dhcp.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2018 Rubicon Communications, LLC (Netgate)
7
 * All rights reserved.
8
 *
9
 * originally based on m0n0wall (http://m0n0.ch/wall)
10
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
11
 * All rights reserved.
12
 *
13
 * Licensed under the Apache License, Version 2.0 (the "License");
14
 * you may not use this file except in compliance with the License.
15
 * You may obtain a copy of the License at
16
 *
17
 * http://www.apache.org/licenses/LICENSE-2.0
18
 *
19
 * Unless required by applicable law or agreed to in writing, software
20
 * distributed under the License is distributed on an "AS IS" BASIS,
21
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
 * See the License for the specific language governing permissions and
23
 * limitations under the License.
24
 */
25

    
26
##|+PRIV
27
##|*IDENT=page-services-dhcpserver
28
##|*NAME=Services: DHCP Server
29
##|*DESCR=Allow access to the 'Services: DHCP Server' page.
30
##|*MATCH=services_dhcp.php*
31
##|-PRIV
32

    
33
require_once("guiconfig.inc");
34
require_once("filter.inc");
35
require_once('rrd.inc');
36
require_once("shaper.inc");
37

    
38
if (!$g['services_dhcp_server_enable']) {
39
	header("Location: /");
40
	exit;
41
}
42

    
43
$if = $_REQUEST['if'];
44

    
45
/* if OLSRD is enabled, allow WAN to house DHCP. */
46
if ($config['installedpackages']['olsrd']) {
47
	foreach ($config['installedpackages']['olsrd']['config'] as $olsrd) {
48
		if ($olsrd['enable']) {
49
			$is_olsr_enabled = true;
50
			break;
51
		}
52
	}
53
}
54

    
55
$iflist = get_configured_interface_with_descr();
56

    
57
/* set the starting interface */
58
if (!$if || !isset($iflist[$if])) {
59
	$found_starting_if = false;
60
	// First look for an interface with DHCP already enabled.
61
	foreach ($iflist as $ifent => $ifname) {
62
		$oc = $config['interfaces'][$ifent];
63
		if (is_array($config['dhcpd'][$ifent]) &&
64
		    isset($config['dhcpd'][$ifent]['enable']) &&
65
		    is_ipaddrv4($oc['ipaddr']) && $oc['subnet'] < 31) {
66
			$if = $ifent;
67
			$found_starting_if = true;
68
			break;
69
		}
70
	}
71

    
72
	/*
73
	 * If there is no DHCP-enabled interface and LAN is a candidate,
74
	 * then choose LAN.
75
	 */
76
	if (!$found_starting_if && isset($iflist['lan']) &&
77
	    is_ipaddrv4($config['interfaces']['lan']['ipaddr']) &&
78
	    $config['interfaces']['lan']['subnet'] < 31) {
79
		$if = 'lan';
80
		$found_starting_if = true;
81
	}
82

    
83
	// At the last select whatever can be found.
84
	if (!$found_starting_if) {
85
		foreach ($iflist as $ifent => $ifname) {
86
			$oc = $config['interfaces'][$ifent];
87

    
88
			/* Not static IPv4 or subnet >= 31 */
89
			if (!is_ipaddrv4($oc['ipaddr']) ||
90
			    empty($oc['subnet']) || $oc['subnet'] < 31) {
91
				continue;
92
			}
93

    
94
			if (!is_array($config['dhcpd'][$ifent]) ||
95
			    !isset($config['dhcpd'][$ifent]['enable'])) {
96
				continue;
97
			}
98

    
99
			$if = $ifent;
100
			break;
101
		}
102
	}
103
}
104

    
105
$act = $_REQUEST['act'];
106

    
107
$a_pools = array();
108

    
109
if (is_array($config['dhcpd'][$if])) {
110
	$pool = $_REQUEST['pool'];
111
	if (is_numeric($_POST['pool'])) {
112
		$pool = $_POST['pool'];
113
	}
114

    
115
	// If we have a pool but no interface name, that's not valid. Redirect away.
116
	if (is_numeric($pool) && empty($if)) {
117
		header("Location: services_dhcp.php");
118
		exit;
119
	}
120

    
121
	if (!is_array($config['dhcpd'][$if]['pool'])) {
122
		$config['dhcpd'][$if]['pool'] = array();
123
	}
124

    
125
	$a_pools = &$config['dhcpd'][$if]['pool'];
126

    
127
	if (is_numeric($pool) && $a_pools[$pool]) {
128
		$dhcpdconf = &$a_pools[$pool];
129
	} elseif ($act == "newpool") {
130
		$dhcpdconf = array();
131
	} else {
132
		$dhcpdconf = &$config['dhcpd'][$if];
133
	}
134

    
135
	if (!is_array($config['dhcpd'][$if]['staticmap'])) {
136
		$dhcpdconf['staticmap'] = array();
137
	}
138

    
139
	$a_maps = &$config['dhcpd'][$if]['staticmap'];
140
}
141

    
142
if (is_array($dhcpdconf)) {
143
	// Global Options
144
	if (!is_numeric($pool) && !($act == "newpool")) {
145
		$pconfig['enable'] = isset($dhcpdconf['enable']);
146
		$pconfig['staticarp'] = isset($dhcpdconf['staticarp']);
147
		// No reason to specify this per-pool, per the dhcpd.conf man page it needs to be in every
148
		//	 pool and should be specified in every pool both nodes share, so we'll treat it as global
149
		$pconfig['failover_peerip'] = $dhcpdconf['failover_peerip'];
150

    
151
		// dhcpleaseinlocaltime is global to all interfaces. So if it is selected on any interface,
152
		// then show it true/checked.
153
		foreach ($config['dhcpd'] as $dhcpdifitem) {
154
			$dhcpleaseinlocaltime = $dhcpdifitem['dhcpleaseinlocaltime'];
155
			if ($dhcpleaseinlocaltime) {
156
				break;
157
			}
158
		}
159

    
160
		$pconfig['dhcpleaseinlocaltime'] = $dhcpleaseinlocaltime;
161
	} else {
162
		// Options that exist only in pools
163
		$pconfig['descr'] = $dhcpdconf['descr'];
164
	}
165

    
166
	// Options that can be global or per-pool.
167
	if (is_array($dhcpdconf['range'])) {
168
		$pconfig['range_from'] = $dhcpdconf['range']['from'];
169
		$pconfig['range_to'] = $dhcpdconf['range']['to'];
170
	}
171

    
172
	$pconfig['deftime'] = $dhcpdconf['defaultleasetime'];
173
	$pconfig['maxtime'] = $dhcpdconf['maxleasetime'];
174
	$pconfig['gateway'] = $dhcpdconf['gateway'];
175
	$pconfig['domain'] = $dhcpdconf['domain'];
176
	$pconfig['domainsearchlist'] = $dhcpdconf['domainsearchlist'];
177
	list($pconfig['wins1'], $pconfig['wins2']) = $dhcpdconf['winsserver'];
178
	list($pconfig['dns1'], $pconfig['dns2'], $pconfig['dns3'], $pconfig['dns4']) = $dhcpdconf['dnsserver'];
179
	$pconfig['ignorebootp'] = isset($dhcpdconf['ignorebootp']);
180
	$pconfig['denyunknown'] = isset($dhcpdconf['denyunknown']);
181
	$pconfig['ignoreclientuids'] = isset($dhcpdconf['ignoreclientuids']);
182
	$pconfig['nonak'] = isset($dhcpdconf['nonak']);
183
	$pconfig['ddnsdomain'] = $dhcpdconf['ddnsdomain'];
184
	$pconfig['ddnsdomainprimary'] = $dhcpdconf['ddnsdomainprimary'];
185
	$pconfig['ddnsdomainkeyname'] = $dhcpdconf['ddnsdomainkeyname'];
186
	$pconfig['ddnsdomainkeyalgorithm'] = $dhcpdconf['ddnsdomainkeyalgorithm'];
187
	$pconfig['ddnsdomainkey'] = $dhcpdconf['ddnsdomainkey'];
188
	$pconfig['ddnsupdate'] = isset($dhcpdconf['ddnsupdate']);
189
	$pconfig['ddnsforcehostname'] = isset($dhcpdconf['ddnsforcehostname']);
190
	$pconfig['mac_allow'] = $dhcpdconf['mac_allow'];
191
	$pconfig['mac_deny'] = $dhcpdconf['mac_deny'];
192
	list($pconfig['ntp1'], $pconfig['ntp2']) = $dhcpdconf['ntpserver'];
193
	$pconfig['tftp'] = $dhcpdconf['tftp'];
194
	$pconfig['ldap'] = $dhcpdconf['ldap'];
195
	$pconfig['netboot'] = isset($dhcpdconf['netboot']);
196
	$pconfig['nextserver'] = $dhcpdconf['nextserver'];
197
	$pconfig['filename'] = $dhcpdconf['filename'];
198
	$pconfig['filename32'] = $dhcpdconf['filename32'];
199
	$pconfig['filename64'] = $dhcpdconf['filename64'];
200
	$pconfig['rootpath'] = $dhcpdconf['rootpath'];
201
	$pconfig['netmask'] = $dhcpdconf['netmask'];
202
	$pconfig['numberoptions'] = $dhcpdconf['numberoptions'];
203
	$pconfig['statsgraph'] = $dhcpdconf['statsgraph'];
204
	$pconfig['ddnsclientupdates'] = $dhcpdconf['ddnsclientupdates'];
205
}
206

    
207
$ifcfgip = $config['interfaces'][$if]['ipaddr'];
208
$ifcfgsn = $config['interfaces'][$if]['subnet'];
209

    
210
$subnet_start = gen_subnetv4($ifcfgip, $ifcfgsn);
211
$subnet_end = gen_subnetv4_max($ifcfgip, $ifcfgsn);
212

    
213
function validate_partial_mac_list($maclist) {
214
	$macs = explode(',', $maclist);
215

    
216
	// Loop through and look for invalid MACs.
217
	foreach ($macs as $mac) {
218
		if (!is_macaddr($mac, true)) {
219
			return false;
220
		}
221
	}
222

    
223
	return true;
224
}
225

    
226
if (isset($_POST['save'])) {
227

    
228
	unset($input_errors);
229

    
230
	$pconfig = $_POST;
231

    
232
	$numberoptions = array();
233
	for ($x = 0; $x < 99; $x++) {
234
		if (isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) {
235
			if ($_POST["number{$x}"] < 1 || $_POST["number{$x}"] > 254) {
236
				$input_errors[] = gettext("The DHCP option must be a number between 1 and 254.");
237
				continue;
238
			}
239
			$numbervalue = array();
240
			$numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]);
241
			$numbervalue['type'] = htmlspecialchars($_POST["itemtype{$x}"]);
242
			$numbervalue['value'] = base64_encode($_POST["value{$x}"]);
243
			$numberoptions['item'][] = $numbervalue;
244
		}
245
	}
246

    
247
	// Reload the new pconfig variable that the form uses.
248
	$pconfig['numberoptions'] = $numberoptions;
249

    
250
	/* input validation */
251

    
252
	// Note: if DHCP Server is not enabled, then it is OK to adjust other parameters without specifying range from-to.
253
	if ($_POST['enable'] || is_numeric($pool) || $act == "newpool") {
254
		$reqdfields = explode(" ", "range_from range_to");
255
		$reqdfieldsn = array(gettext("Range begin"), gettext("Range end"));
256

    
257
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
258
	}
259

    
260
	if (($_POST['nonak']) && !empty($_POST['failover_peerip'])) {
261
		$input_errors[] = gettext("Ignore Denied Clients may not be used when a Failover Peer IP is defined.");
262
	}
263

    
264
	if ($_POST['range_from'] && !is_ipaddrv4($_POST['range_from'])) {
265
		$input_errors[] = gettext("A valid IPv4 address must be specified for range from.");
266
	}
267
	if ($_POST['range_to'] && !is_ipaddrv4($_POST['range_to'])) {
268
		$input_errors[] = gettext("A valid IPv4 address must be specified for range to.");
269
	}
270
	if (($_POST['range_from'] && !$_POST['range_to']) || ($_POST['range_to'] && !$_POST['range_from'])) {
271
		$input_errors[] = gettext("Range From and Range To must both be entered.");
272
	}
273
	if (($_POST['gateway'] && $_POST['gateway'] != "none" && !is_ipaddrv4($_POST['gateway']))) {
274
		$input_errors[] = gettext("A valid IP address must be specified for the gateway.");
275
	}
276
	if (($_POST['wins1'] && !is_ipaddrv4($_POST['wins1'])) || ($_POST['wins2'] && !is_ipaddrv4($_POST['wins2']))) {
277
		$input_errors[] = gettext("A valid IP address must be specified for the primary/secondary WINS servers.");
278
	}
279
	$parent_ip = get_interface_ip($_POST['if']);
280
	if (is_ipaddrv4($parent_ip) && $_POST['gateway'] && $_POST['gateway'] != "none") {
281
		$parent_sn = get_interface_subnet($_POST['if']);
282
		if (!ip_in_subnet($_POST['gateway'], gen_subnet($parent_ip, $parent_sn) . "/" . $parent_sn) && !ip_in_interface_alias_subnet($_POST['if'], $_POST['gateway'])) {
283
			$input_errors[] = sprintf(gettext("The gateway address %s does not lie within the chosen interface's subnet."), $_POST['gateway']);
284
		}
285
	}
286

    
287
	if (($_POST['dns1'] && !is_ipaddrv4($_POST['dns1'])) || ($_POST['dns2'] && !is_ipaddrv4($_POST['dns2'])) || ($_POST['dns3'] && !is_ipaddrv4($_POST['dns3'])) || ($_POST['dns4'] && !is_ipaddrv4($_POST['dns4']))) {
288
		$input_errors[] = gettext("A valid IP address must be specified for each of the DNS servers.");
289
	}
290

    
291
	if ($_POST['deftime'] && (!is_numeric($_POST['deftime']) || ($_POST['deftime'] < 60))) {
292
		$input_errors[] = gettext("The default lease time must be at least 60 seconds.");
293
	}
294

    
295
	if (isset($config['captiveportal']) && is_array($config['captiveportal'])) {
296
		$deftime = 7200; // Default value if it's empty
297
		if (is_numeric($_POST['deftime'])) {
298
			$deftime = $_POST['deftime'];
299
		}
300

    
301
		foreach ($config['captiveportal'] as $cpZone => $cpdata) {
302
			if (!isset($cpdata['enable'])) {
303
				continue;
304
			}
305
			if (!isset($cpdata['timeout']) || !is_numeric($cpdata['timeout'])) {
306
				continue;
307
			}
308
			$cp_ifs = explode(',', $cpdata['interface']);
309
			if (!in_array($if, $cp_ifs)) {
310
				continue;
311
			}
312
			if ($cpdata['timeout'] > $deftime) {
313
				$input_errors[] = sprintf(gettext(
314
					'The Captive Portal zone (%1$s) has Hard Timeout parameter set to a value bigger than Default lease time (%2$s).'), $cpZone, $deftime);
315
			}
316
		}
317
	}
318

    
319
	if ($_POST['maxtime'] && (!is_numeric($_POST['maxtime']) || ($_POST['maxtime'] < 60) || ($_POST['maxtime'] <= $_POST['deftime']))) {
320
		$input_errors[] = gettext("The maximum lease time must be at least 60 seconds and higher than the default lease time.");
321
	}
322
	if ($_POST['ddnsupdate'] && !is_domain($_POST['ddnsdomain'])) {
323
		$input_errors[] = gettext("A valid domain name must be specified for the dynamic DNS registration.");
324
	}
325
	if ($_POST['ddnsupdate'] && !is_ipaddrv4($_POST['ddnsdomainprimary'])) {
326
		$input_errors[] = gettext("A valid primary domain name server IP address must be specified for the dynamic domain name.");
327
	}
328
	if ($_POST['ddnsupdate'] && (!$_POST['ddnsdomainkeyname'] || !$_POST['ddnsdomainkeyalgorithm'] || !$_POST['ddnsdomainkey'])) {
329
		$input_errors[] = gettext("A valid domain key name, algorithm and secret must be specified.");
330
	}
331
	if ($_POST['domainsearchlist']) {
332
		$domain_array = preg_split("/[ ;]+/", $_POST['domainsearchlist']);
333
		foreach ($domain_array as $curdomain) {
334
			if (!is_domain($curdomain)) {
335
				$input_errors[] = gettext("A valid domain search list must be specified.");
336
				break;
337
			}
338
		}
339
	}
340

    
341
	// Validate MACs
342
	if (!empty($_POST['mac_allow']) && !validate_partial_mac_list($_POST['mac_allow'])) {
343
		$input_errors[] = gettext("If a mac allow list is specified, it must contain only valid partial MAC addresses.");
344
	}
345
	if (!empty($_POST['mac_deny']) && !validate_partial_mac_list($_POST['mac_deny'])) {
346
		$input_errors[] = gettext("If a mac deny list is specified, it must contain only valid partial MAC addresses.");
347
	}
348

    
349
	if (($_POST['ntp1'] && (!is_ipaddrv4($_POST['ntp1']) && !is_hostname($_POST['ntp1']))) || ($_POST['ntp2'] && (!is_ipaddrv4($_POST['ntp2']) && !is_hostname($_POST['ntp2'])))) {
350
		$input_errors[] = gettext("A valid IP address or hostname must be specified for the primary/secondary NTP servers.");
351
	}
352
	if (($_POST['domain'] && !is_domain($_POST['domain']))) {
353
		$input_errors[] = gettext("A valid domain name must be specified for the DNS domain.");
354
	}
355
	if ($_POST['tftp'] && !is_ipaddrv4($_POST['tftp']) && !is_domain($_POST['tftp']) && !filter_var($_POST['tftp'], FILTER_VALIDATE_URL)) {
356
		$input_errors[] = gettext("A valid IP address, hostname or URL must be specified for the TFTP server.");
357
	}
358
	if (($_POST['nextserver'] && !is_ipaddrv4($_POST['nextserver']))) {
359
		$input_errors[] = gettext("A valid IP address must be specified for the network boot server.");
360
	}
361

    
362
	if (gen_subnet($ifcfgip, $ifcfgsn) == $_POST['range_from']) {
363
		$input_errors[] = gettext("The network address cannot be used in the starting subnet range.");
364
	}
365
	if (gen_subnet_max($ifcfgip, $ifcfgsn) == $_POST['range_to']) {
366
		$input_errors[] = gettext("The broadcast address cannot be used in the ending subnet range.");
367
	}
368

    
369
	// Disallow a range that includes the virtualip
370
	if (is_array($config['virtualip']['vip'])) {
371
		foreach ($config['virtualip']['vip'] as $vip) {
372
			if ($vip['interface'] == $if) {
373
				if ($vip['subnet'] && is_inrange_v4($vip['subnet'], $_POST['range_from'], $_POST['range_to'])) {
374
					$input_errors[] = sprintf(gettext("The subnet range cannot overlap with virtual IP address %s."), $vip['subnet']);
375
				}
376
			}
377
		}
378
	}
379

    
380
	$noip = false;
381
	if (is_array($a_maps)) {
382
		foreach ($a_maps as $map) {
383
			if (empty($map['ipaddr'])) {
384
				$noip = true;
385
			}
386
		}
387
	}
388

    
389
	if ($_POST['staticarp'] && $noip) {
390
		$input_errors[] = gettext("Cannot enable static ARP when there are static map entries without IP addresses. Ensure all static maps have IP addresses and try again.");
391
	}
392

    
393
	if (is_array($pconfig['numberoptions']['item'])) {
394
		foreach ($pconfig['numberoptions']['item'] as $numberoption) {
395
			$numberoption_value = base64_decode($numberoption['value']);
396
			if ($numberoption['type'] == 'text' && strstr($numberoption_value, '"')) {
397
				$input_errors[] = gettext("Text type cannot include quotation marks.");
398
			} else if ($numberoption['type'] == 'string' && !preg_match('/^"[^"]*"$/', $numberoption_value) && !preg_match('/^[0-9a-f]{2}(?:\:[0-9a-f]{2})*$/i', $numberoption_value)) {
399
				$input_errors[] = gettext("String type must be enclosed in quotes like \"this\" or must be a series of octets specified in hexadecimal, separated by colons, like 01:23:45:67:89:ab:cd:ef");
400
			} else if ($numberoption['type'] == 'boolean' && $numberoption_value != 'true' && $numberoption_value != 'false' && $numberoption_value != 'on' && $numberoption_value != 'off') {
401
				$input_errors[] = gettext("Boolean type must be true, false, on, or off.");
402
			} else if ($numberoption['type'] == 'unsigned integer 8' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 255)) {
403
				$input_errors[] = gettext("Unsigned 8-bit integer type must be a number in the range 0 to 255.");
404
			} else if ($numberoption['type'] == 'unsigned integer 16' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 65535)) {
405
				$input_errors[] = gettext("Unsigned 16-bit integer type must be a number in the range 0 to 65535.");
406
			} else if ($numberoption['type'] == 'unsigned integer 32' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 4294967295)) {
407
				$input_errors[] = gettext("Unsigned 32-bit integer type must be a number in the range 0 to 4294967295.");
408
			} else if ($numberoption['type'] == 'signed integer 8' && (!is_numeric($numberoption_value) || $numberoption_value < -128 || $numberoption_value > 127)) {
409
				$input_errors[] = gettext("Signed 8-bit integer type must be a number in the range -128 to 127.");
410
			} else if ($numberoption['type'] == 'signed integer 16' && (!is_numeric($numberoption_value) || $numberoption_value < -32768 || $numberoption_value > 32767)) {
411
				$input_errors[] = gettext("Signed 16-bit integer type must be a number in the range -32768 to 32767.");
412
			} else if ($numberoption['type'] == 'signed integer 32' && (!is_numeric($numberoption_value) || $numberoption_value < -2147483648 || $numberoption_value > 2147483647)) {
413
				$input_errors[] = gettext("Signed 32-bit integer type must be a number in the range -2147483648 to 2147483647.");
414
			} else if ($numberoption['type'] == 'ip-address' && !is_ipaddrv4($numberoption_value) && !is_hostname($numberoption_value)) {
415
				$input_errors[] = gettext("IP address or host type must be an IP address or host name.");
416
			}
417
		}
418
	}
419

    
420
	if ((!isset($pool) || !is_numeric($pool)) && $act != "newpool") {
421
		/* If enabling DHCP Server, make sure that the DHCP Relay isn't enabled on this interface */
422
		if ($_POST['enable'] && isset($config['dhcrelay']['enable']) &&
423
		    (stristr($config['dhcrelay']['interface'], $if) !== false)) {
424
			$input_errors[] = sprintf(gettext(
425
			    "The DHCP relay on the %s interface must be disabled before enabling the DHCP server."),
426
			    $iflist[$if]);
427
		}
428

    
429
		/* If disabling DHCP Server, make sure that DHCP registration isn't enabled for DNS forwarder/resolver */
430
		if (!$_POST['enable']) {
431
			/* Find out how many other interfaces have DHCP enabled. */
432
			$dhcp_enabled_count = 0;
433
			foreach ($config['dhcpd'] as $dhif => $dhcps) {
434
				if ($dhif == $if) {
435
					/* Skip this interface, we only want to know how many others are enabled. */
436
					continue;
437
				}
438
				if (isset($dhcps['enable'])) {
439
					$dhcp_enabled_count++;
440
				}
441
			}
442

    
443
			if (isset($config['dnsmasq']['enable']) &&
444
			    ($dhcp_enabled_count == 0) &&
445
			    (isset($config['dnsmasq']['regdhcp']) ||
446
			    isset($config['dnsmasq']['regdhcpstatic']) ||
447
			    isset($config['dnsmasq']['dhcpfirst']))) {
448
				$input_errors[] = gettext(
449
				    "DHCP Registration features in the DNS Forwarder are active and require at least one enabled DHCP Server.");
450
			}
451
			if (isset($config['unbound']['enable']) &&
452
			    ($dhcp_enabled_count == 0) &&
453
			    (isset($config['unbound']['regdhcp']) ||
454
			    isset($config['unbound']['regdhcpstatic']))) {
455
				$input_errors[] = gettext(
456
				    "DHCP Registration features in the DNS Resolver are active and require at least one enabled DHCP Server.");
457
			}
458
		}
459
	}
460

    
461
	// If nothing is wrong so far, and we have range from and to, then check conditions related to the values of range from and to.
462
	if (!$input_errors && $_POST['range_from'] && $_POST['range_to']) {
463
		/* make sure the range lies within the current subnet */
464
		if (ip_greater_than($_POST['range_from'], $_POST['range_to'])) {
465
			$input_errors[] = gettext("The range is invalid (first element higher than second element).");
466
		}
467

    
468
		if (!is_inrange_v4($_POST['range_from'], $subnet_start, $subnet_end) ||
469
			!is_inrange_v4($_POST['range_to'], $subnet_start, $subnet_end)) {
470
			$input_errors[] = gettext("The specified range lies outside of the current subnet.");
471
		}
472

    
473
		if (is_numeric($pool) || ($act == "newpool")) {
474
			if (is_inrange_v4($_POST['range_from'],
475
				$config['dhcpd'][$if]['range']['from'],
476
				$config['dhcpd'][$if]['range']['to']) ||
477
				is_inrange_v4($_POST['range_to'],
478
				$config['dhcpd'][$if]['range']['from'],
479
				$config['dhcpd'][$if]['range']['to'])) {
480
				$input_errors[] = gettext("The specified range must not be within the DHCP range for this interface.");
481
			}
482
		}
483

    
484
		foreach ($a_pools as $id => $p) {
485
			if (is_numeric($pool) && ($id == $pool)) {
486
				continue;
487
			}
488

    
489
			if (is_inrange_v4($_POST['range_from'],
490
				$p['range']['from'], $p['range']['to']) ||
491
				is_inrange_v4($_POST['range_to'],
492
				$p['range']['from'], $p['range']['to'])) {
493
				$input_errors[] = gettext("The specified range must not be within the range configured on a DHCP pool for this interface.");
494
				break;
495
			}
496
		}
497

    
498
		if (is_array($a_maps)) {
499
			foreach ($a_maps as $map) {
500
				if (empty($map['ipaddr'])) {
501
					continue;
502
				}
503
				if (is_inrange_v4($map['ipaddr'], $_POST['range_from'], $_POST['range_to'])) {
504
					$input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings."));
505
					break;
506
				}
507
			}
508
		}
509
	}
510

    
511
	if (!$input_errors) {
512
		if (!is_numeric($pool)) {
513
			if ($act == "newpool") {
514
				$dhcpdconf = array();
515
			} else {
516
				if (!is_array($config['dhcpd'])) {
517
					$config['dhcpd']= array();
518
				}
519
				if (!is_array($config['dhcpd'][$if])) {
520
					$config['dhcpd'][$if] = array();
521
				}
522
				$dhcpdconf = $config['dhcpd'][$if];
523
			}
524
		} else {
525
			if (is_array($a_pools[$pool])) {
526
				$dhcpdconf = $a_pools[$pool];
527
			} else {
528
				// Someone specified a pool but it doesn't exist. Punt.
529
				header("Location: services_dhcp.php");
530
				exit;
531
			}
532
		}
533
		if (!is_array($dhcpdconf)) {
534
			$dhcpdconf = array();
535
		}
536
		if (!is_array($dhcpdconf['range'])) {
537
			$dhcpdconf['range'] = array();
538
		}
539

    
540
		$dhcpd_enable_changed = false;
541

    
542
		// Global Options
543
		if (!is_numeric($pool) && !($act == "newpool")) {
544
			$old_dhcpd_enable = isset($dhcpdconf['enable']);
545
			$new_dhcpd_enable = ($_POST['enable']) ? true : false;
546
			if ($old_dhcpd_enable != $new_dhcpd_enable) {
547
				/* DHCP has been enabled or disabled. The pf ruleset will need to be rebuilt to allow or disallow DHCP. */
548
				$dhcpd_enable_changed = true;
549
			}
550

    
551
			$dhcpdconf['enable'] = $new_dhcpd_enable;
552
			$dhcpdconf['staticarp'] = ($_POST['staticarp']) ? true : false;
553
			$previous = $dhcpdconf['failover_peerip'];
554
			if ($previous != $_POST['failover_peerip']) {
555
				mwexec("/bin/rm -rf /var/dhcpd/var/db/*");
556
			}
557

    
558
			$dhcpdconf['failover_peerip'] = $_POST['failover_peerip'];
559
			// dhcpleaseinlocaltime is global to all interfaces. So update the setting on all interfaces.
560
			foreach ($config['dhcpd'] as &$dhcpdifitem) {
561
				$dhcpdifitem['dhcpleaseinlocaltime'] = $_POST['dhcpleaseinlocaltime'];
562
			}
563
		} else {
564
			// Options that exist only in pools
565
			$dhcpdconf['descr'] = $_POST['descr'];
566
		}
567

    
568
		// Options that can be global or per-pool.
569
		$dhcpdconf['range']['from'] = $_POST['range_from'];
570
		$dhcpdconf['range']['to'] = $_POST['range_to'];
571
		$dhcpdconf['defaultleasetime'] = $_POST['deftime'];
572
		$dhcpdconf['maxleasetime'] = $_POST['maxtime'];
573
		$dhcpdconf['netmask'] = $_POST['netmask'];
574

    
575
		unset($dhcpdconf['winsserver']);
576
		if ($_POST['wins1']) {
577
			$dhcpdconf['winsserver'][] = $_POST['wins1'];
578
		}
579
		if ($_POST['wins2']) {
580
			$dhcpdconf['winsserver'][] = $_POST['wins2'];
581
		}
582

    
583
		unset($dhcpdconf['dnsserver']);
584
		if ($_POST['dns1']) {
585
			$dhcpdconf['dnsserver'][] = $_POST['dns1'];
586
		}
587
		if ($_POST['dns2']) {
588
			$dhcpdconf['dnsserver'][] = $_POST['dns2'];
589
		}
590
		if ($_POST['dns3']) {
591
			$dhcpdconf['dnsserver'][] = $_POST['dns3'];
592
		}
593
		if ($_POST['dns4']) {
594
			$dhcpdconf['dnsserver'][] = $_POST['dns4'];
595
		}
596

    
597
		$dhcpdconf['gateway'] = $_POST['gateway'];
598
		$dhcpdconf['domain'] = $_POST['domain'];
599
		$dhcpdconf['domainsearchlist'] = $_POST['domainsearchlist'];
600
		$dhcpdconf['ignorebootp'] = ($_POST['ignorebootp']) ? true : false;
601
		$dhcpdconf['denyunknown'] = ($_POST['denyunknown']) ? true : false;
602
		$dhcpdconf['ignoreclientuids'] = ($_POST['ignoreclientuids']) ? true : false;
603
		$dhcpdconf['nonak'] = ($_POST['nonak']) ? true : false;
604
		$dhcpdconf['ddnsdomain'] = $_POST['ddnsdomain'];
605
		$dhcpdconf['ddnsdomainprimary'] = $_POST['ddnsdomainprimary'];
606
		$dhcpdconf['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname'];
607
		$dhcpdconf['ddnsdomainkeyalgorithm'] = $_POST['ddnsdomainkeyalgorithm'];
608
		$dhcpdconf['ddnsdomainkey'] = $_POST['ddnsdomainkey'];
609
		$dhcpdconf['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false;
610
		$dhcpdconf['ddnsforcehostname'] = ($_POST['ddnsforcehostname']) ? true : false;
611
		$dhcpdconf['mac_allow'] = $_POST['mac_allow'];
612
		$dhcpdconf['mac_deny'] = $_POST['mac_deny'];
613
		$dhcpdconf['ddnsclientupdates'] = $_POST['ddnsclientupdates'];
614

    
615
		unset($dhcpdconf['ntpserver']);
616
		if ($_POST['ntp1']) {
617
			$dhcpdconf['ntpserver'][] = $_POST['ntp1'];
618
		}
619
		if ($_POST['ntp2']) {
620
			$dhcpdconf['ntpserver'][] = $_POST['ntp2'];
621
		}
622

    
623
		$dhcpdconf['tftp'] = $_POST['tftp'];
624
		$dhcpdconf['ldap'] = $_POST['ldap'];
625
		$dhcpdconf['netboot'] = ($_POST['netboot']) ? true : false;
626
		$dhcpdconf['nextserver'] = $_POST['nextserver'];
627
		$dhcpdconf['filename'] = $_POST['filename'];
628
		$dhcpdconf['filename32'] = $_POST['filename32'];
629
		$dhcpdconf['filename64'] = $_POST['filename64'];
630
		$dhcpdconf['rootpath'] = $_POST['rootpath'];
631
		unset($dhcpdconf['statsgraph']);
632
		if ($_POST['statsgraph']) {
633
			$dhcpdconf['statsgraph'] = $_POST['statsgraph'];
634
			enable_rrd_graphing();
635
		}
636

    
637
		// Handle the custom options rowhelper
638
		if (isset($dhcpdconf['numberoptions']['item'])) {
639
			unset($dhcpdconf['numberoptions']['item']);
640
		}
641

    
642
		$dhcpdconf['numberoptions'] = $numberoptions;
643

    
644
		if (is_numeric($pool) && is_array($a_pools[$pool])) {
645
			$a_pools[$pool] = $dhcpdconf;
646
		} elseif ($act == "newpool") {
647
			$a_pools[] = $dhcpdconf;
648
		} else {
649
			$config['dhcpd'][$if] = $dhcpdconf;
650
		}
651

    
652
		write_config();
653
	}
654
}
655

    
656
if ((isset($_POST['save']) || isset($_POST['apply'])) && (!$input_errors)) {
657
	$changes_applied = true;
658
	$retval = 0;
659
	$retvaldhcp = 0;
660
	$retvaldns = 0;
661
	/* dnsmasq_configure calls dhcpd_configure */
662
	/* no need to restart dhcpd twice */
663
	if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic']))	{
664
		$retvaldns |= services_dnsmasq_configure();
665
		if ($retvaldns == 0) {
666
			clear_subsystem_dirty('hosts');
667
			clear_subsystem_dirty('staticmaps');
668
		}
669
	} else if (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcpstatic'])) {
670
		$retvaldns |= services_unbound_configure();
671
		if ($retvaldns == 0) {
672
			clear_subsystem_dirty('unbound');
673
			clear_subsystem_dirty('hosts');
674
			clear_subsystem_dirty('staticmaps');
675
		}
676
	} else {
677
		$retvaldhcp |= services_dhcpd_configure();
678
		if ($retvaldhcp == 0) {
679
			clear_subsystem_dirty('staticmaps');
680
		}
681
	}
682
	/* BIND package - Bug #3710 */
683
	if (!function_exists('is_package_installed')) {
684
		require_once('pkg-utils.inc');
685
	}
686
	if (is_package_installed('pfSense-pkg-bind') && isset($config['installedpackages']['bind']['config'][0]['enable_bind'])) {
687
		$reloadbind = false;
688
		if (is_array($config['installedpackages']['bindzone'])) {
689
			$bindzone = $config['installedpackages']['bindzone']['config'];
690
		} else {
691
			$bindzone = array();
692
		}
693
		for ($x = 0; $x < sizeof($bindzone); $x++) {
694
			$zone = $bindzone[$x];
695
			if ($zone['regdhcpstatic'] == 'on') {
696
				$reloadbind = true;
697
				break;
698
			}
699
		}
700
		if ($reloadbind === true) {
701
			if (file_exists("/usr/local/pkg/bind.inc")) {
702
				require_once("/usr/local/pkg/bind.inc");
703
				bind_sync();
704
			}
705
		}
706
	}
707
	if ($dhcpd_enable_changed) {
708
		$retvalfc |= filter_configure();
709
	}
710

    
711
	if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) {
712
		$retval = 1;
713
	}
714
}
715

    
716
if ($act == "delpool") {
717
	if ($a_pools[$_POST['id']]) {
718
		unset($a_pools[$_POST['id']]);
719
		write_config();
720
		header("Location: services_dhcp.php?if={$if}");
721
		exit;
722
	}
723
}
724

    
725
if ($act == "del") {
726
	if (isset($a_maps[$_POST['id']])) {
727
		/* Remove static ARP entry, if necessary */
728
		if (isset($a_maps[$_POST['id']]['arp_table_static_entry'])) {
729
			mwexec("/usr/sbin/arp -d " . escapeshellarg($a_maps[$_POST['id']]['ipaddr']));
730
		}
731
		unset($a_maps[$_POST['id']]);
732
		write_config();
733
		if (isset($config['dhcpd'][$if]['enable'])) {
734
			mark_subsystem_dirty('staticmaps');
735
			if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic'])) {
736
				mark_subsystem_dirty('hosts');
737
			}
738
		}
739

    
740
		header("Location: services_dhcp.php?if={$if}");
741
		exit;
742
	}
743
}
744

    
745
// Build an HTML table that can be inserted into a Form_StaticText element
746
function build_pooltable() {
747
	global $a_pools, $if;
748

    
749
	$pooltbl =	'<div class="table-responsive">';
750
	$pooltbl .=		'<table class="table table-striped table-hover table-condensed">';
751
	$pooltbl .=			'<thead>';
752
	$pooltbl .=				'<tr>';
753
	$pooltbl .=					'<th>' . gettext("Pool Start") . '</th>';
754
	$pooltbl .=					'<th>' . gettext("Pool End") . '</th>';
755
	$pooltbl .=					'<th>' . gettext("Description") . '</th>';
756
	$pooltbl .=					'<th>' . gettext("Actions") . '</th>';
757
	$pooltbl .=				'</tr>';
758
	$pooltbl .=			'</thead>';
759
	$pooltbl .=			'<tbody>';
760

    
761
	if (is_array($a_pools)) {
762
		$i = 0;
763
		foreach ($a_pools as $poolent) {
764
			if (!empty($poolent['range']['from']) && !empty($poolent['range']['to'])) {
765
				$pooltbl .= '<tr>';
766
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
767
							htmlspecialchars($poolent['range']['from']) . '</td>';
768

    
769
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
770
							htmlspecialchars($poolent['range']['to']) . '</td>';
771

    
772
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
773
							htmlspecialchars($poolent['descr']) . '</td>';
774

    
775
				$pooltbl .= '<td><a class="fa fa-pencil" title="'. gettext("Edit pool") . '" href="services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '"></a>';
776

    
777
				$pooltbl .= ' <a class="fa fa-trash" title="'. gettext("Delete pool") . '" href="services_dhcp.php?if=' . htmlspecialchars($if) . '&act=delpool&id=' . $i . '" usepost></a></td>';
778
				$pooltbl .= '</tr>';
779
			}
780
		$i++;
781
		}
782
	}
783

    
784
	$pooltbl .=			'</tbody>';
785
	$pooltbl .=		'</table>';
786
	$pooltbl .= '</div>';
787

    
788
	return($pooltbl);
789
}
790

    
791
$pgtitle = array(gettext("Services"), gettext("DHCP Server"));
792
$pglinks = array("", "services_dhcp.php");
793

    
794
if (!empty($if) && isset($iflist[$if])) {
795
	$pgtitle[] = $iflist[$if];
796
	$pglinks[] = "@self";
797
}
798
$shortcut_section = "dhcp";
799

    
800
include("head.inc");
801

    
802
if ($input_errors) {
803
	print_input_errors($input_errors);
804
}
805

    
806
if ($changes_applied) {
807
	print_apply_result_box($retval);
808
}
809

    
810
if (is_subsystem_dirty('staticmaps')) {
811
	print_apply_box(gettext("The static mapping configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
812
}
813

    
814
/* active tabs */
815
$tab_array = array();
816
$tabscounter = 0;
817
$i = 0;
818
$have_small_subnet = false;
819

    
820
foreach ($iflist as $ifent => $ifname) {
821
	$oc = $config['interfaces'][$ifent];
822

    
823
	/* Not static IPv4 or subnet >= 31 */
824
	if ($oc['subnet'] >= 31) {
825
		$have_small_subnet = true;
826
		$example_name = $ifname;
827
		$example_cidr = $oc['subnet'];
828
		continue;
829
	}
830
	if (!is_ipaddrv4($oc['ipaddr']) || empty($oc['subnet'])) {
831
		continue;
832
	}
833

    
834
	if ($ifent == $if) {
835
		$active = true;
836
	} else {
837
		$active = false;
838
	}
839

    
840
	$tab_array[] = array($ifname, $active, "services_dhcp.php?if={$ifent}");
841
	$tabscounter++;
842
}
843

    
844
if ($tabscounter == 0) {
845
	if ($have_small_subnet) {
846
		$sentence2 = sprintf(gettext('%1$s has a CIDR mask of %2$s, which does not contain enough addresses.'), htmlspecialchars($example_name), htmlspecialchars($example_cidr));
847
	} else {
848
		$sentence2 = gettext("This system has no interfaces configured with a static IPv4 address.");
849
	}
850
	print_info_box(gettext("The DHCP Server requires a static IPv4 subnet large enough to serve addresses to clients.") . " " . $sentence2);
851
	include("foot.inc");
852
	exit;
853
}
854

    
855
display_top_tabs($tab_array);
856

    
857
$form = new Form();
858

    
859
$section = new Form_Section('General Options');
860

    
861
if (!is_numeric($pool) && !($act == "newpool")) {
862
	if (isset($config['dhcrelay']['enable'])) {
863
		$section->addInput(new Form_Checkbox(
864
			'enable',
865
			'Enable',
866
			gettext("DHCP Relay is currently enabled. DHCP Server canot be enabled while the DHCP Relay is enabled on any interface."),
867
			$pconfig['enable']
868
		))->setAttribute('disabled', true);
869
	} else {
870
		$section->addInput(new Form_Checkbox(
871
			'enable',
872
			'Enable',
873
			sprintf(gettext("Enable DHCP server on %s interface"), htmlspecialchars($iflist[$if])),
874
			$pconfig['enable']
875
		));
876
	}
877
} else {
878
	print_info_box(gettext('Editing pool-specific options. To return to the Interface, click its tab above.'), 'info', false);
879
}
880

    
881
$section->addInput(new Form_Checkbox(
882
	'ignorebootp',
883
	'BOOTP',
884
	'Ignore BOOTP queries',
885
	$pconfig['ignorebootp']
886
));
887

    
888
$section->addInput(new Form_Checkbox(
889
	'denyunknown',
890
	'Deny unknown clients',
891
	'Only the clients defined below will get DHCP leases from this server.',
892
	$pconfig['denyunknown']
893
));
894

    
895
$section->addInput(new Form_Checkbox(
896
	'nonak',
897
	'Ignore denied clients',
898
	'Denied clients will be ignored rather than rejected.',
899
	$pconfig['nonak']
900
))->setHelp("This option is not compatible with failover and cannot be enabled when a Failover Peer IP address is configured.");
901

    
902
$section->addInput(new Form_Checkbox(
903
	'ignoreclientuids',
904
	'Ignore client identifiers',
905
	'If a client includes a unique identifier in its DHCP request, that UID will not be recorded in its lease.',
906
	$pconfig['ignoreclientuids']
907
))->setHelp("This option may be useful when a client can dual boot using different client identifiers but the same hardware (MAC) address.  Note that the resulting server behavior violates the official DHCP specification.");
908

    
909

    
910
if (is_numeric($pool) || ($act == "newpool")) {
911
	$section->addInput(new Form_Input(
912
		'descr',
913
		'Pool Description',
914
		'text',
915
		$pconfig['descr']
916
	));
917
}
918

    
919
$section->addInput(new Form_StaticText(
920
	'Subnet',
921
	gen_subnet($ifcfgip, $ifcfgsn)
922
));
923

    
924
$section->addInput(new Form_StaticText(
925
	'Subnet mask',
926
	gen_subnet_mask($ifcfgsn)
927
));
928

    
929
// Compose a string to display the required address ranges
930
$rangestr = ip_after($subnet_start) . ' - ' . ip_before($subnet_end);
931

    
932
if (is_numeric($pool) || ($act == "newpool")) {
933
	$rangestr .= '<br />' . gettext('In-use DHCP Pool Ranges:');
934
	if (is_array($config['dhcpd'][$if]['range'])) {
935
		$rangestr .= '<br />' . $config['dhcpd'][$if]['range']['from'] . ' - ' . $config['dhcpd'][$if]['range']['to'];
936
	}
937

    
938
	foreach ($a_pools as $p) {
939
		if (is_array($p['range'])) {
940
			$rangestr .= '<br />' . $p['range']['from'] . ' - ' . $p['range']['to'];
941
		}
942
	}
943
}
944

    
945
$section->addInput(new Form_StaticText(
946
	'Available range',
947
	$rangestr
948
));
949

    
950
if ($is_olsr_enabled) {
951
	$section->addInput(new Form_Select(
952
		'netmask',
953
		'Subnet mask',
954
		$pconfig['netmask'],
955
		array_combine(range(32, 1, -1), range(32, 1, -1))
956
	));
957
}
958

    
959
$group = new Form_Group('*Range');
960

    
961
$group->add(new Form_IpAddress(
962
	'range_from',
963
	null,
964
	$pconfig['range_from'],
965
	'V4'
966
))->setHelp('From');
967

    
968
$group->add(new Form_IpAddress(
969
	'range_to',
970
	null,
971
	$pconfig['range_to'],
972
	'V4'
973
))->setHelp('To');
974

    
975
$section->add($group);
976

    
977
$form->add($section);
978

    
979
if (!is_numeric($pool) && !($act == "newpool")) {
980
	$section = new Form_Section('Additional Pools');
981

    
982
	$btnaddpool = new Form_Button(
983
		'btnaddpool',
984
		'Add pool',
985
		'services_dhcp.php?if=' . htmlspecialchars($if) . '&act=newpool',
986
		'fa-plus'
987
	);
988
	$btnaddpool->addClass('btn-success');
989

    
990
	$section->addInput(new Form_StaticText(
991
		'Add',
992
		$btnaddpool
993
	))->setHelp('If additional pools of addresses are needed inside of this subnet outside the above Range, they may be specified here.');
994

    
995
	if (is_array($a_pools)) {
996
		$section->addInput(new Form_StaticText(
997
			null,
998
			build_pooltable()
999
		));
1000
	}
1001

    
1002
	$form->add($section);
1003
}
1004

    
1005
$section = new Form_Section('Servers');
1006

    
1007
$section->addInput(new Form_IpAddress(
1008
	'wins1',
1009
	'WINS servers',
1010
	$pconfig['wins1'],
1011
	'V4'
1012
))->setAttribute('placeholder', 'WINS Server 1');
1013

    
1014
$section->addInput(new Form_IpAddress(
1015
	'wins2',
1016
	null,
1017
	$pconfig['wins2'],
1018
	'V4'
1019
))->setAttribute('placeholder', 'WINS Server 2');
1020

    
1021
for ($idx=1; $idx<=4; $idx++) {
1022
	$section->addInput(new Form_IpAddress(
1023
		'dns' . $idx,
1024
		($idx == 1) ? 'DNS servers':null,
1025
		$pconfig['dns' . $idx],
1026
		'V4'
1027
	))->setAttribute('placeholder', 'DNS Server ' . $idx)->setHelp(($idx == 4) ? 'Leave blank to use the system default DNS servers: this interface\'s IP if DNS Forwarder or Resolver is enabled, otherwise the servers configured on the System / General Setup page.':'');
1028
}
1029

    
1030
$form->add($section);
1031

    
1032
$section = new Form_Section('Other Options');
1033

    
1034
$section->addInput(new Form_IpAddress(
1035
	'gateway',
1036
	'Gateway',
1037
	$pconfig['gateway'],
1038
	'V4'
1039
))->setPattern('[.a-zA-Z0-9_]+')
1040
  ->setHelp('The default is to use the IP on this interface of the firewall as the gateway. Specify an alternate gateway here if this is not the correct gateway for the network. Type "none" for no gateway assignment.');
1041

    
1042
$section->addInput(new Form_Input(
1043
	'domain',
1044
	'Domain name',
1045
	'text',
1046
	$pconfig['domain']
1047
))->setHelp('The default is to use the domain name of this system as the default domain name provided by DHCP. An alternate domain name may be specified here.');
1048

    
1049
$section->addInput(new Form_Input(
1050
	'domainsearchlist',
1051
	'Domain search list',
1052
	'text',
1053
	$pconfig['domainsearchlist']
1054
))->setHelp('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator.');
1055

    
1056
$section->addInput(new Form_Input(
1057
	'deftime',
1058
	'Default lease time',
1059
	'number',
1060
	$pconfig['deftime']
1061
))->setHelp('This is used for clients that do not ask for a specific expiration time. The default is 7200 seconds.');
1062

    
1063
$section->addInput(new Form_Input(
1064
	'maxtime',
1065
	'Maximum lease time',
1066
	'number',
1067
	$pconfig['maxtime']
1068
))->setHelp('This is the maximum lease time for clients that ask for a specific expiration time. The default is 86400 seconds.');
1069

    
1070
if (!is_numeric($pool) && !($act == "newpool")) {
1071
	$section->addInput(new Form_IpAddress(
1072
		'failover_peerip',
1073
		'Failover peer IP',
1074
		$pconfig['failover_peerip'],
1075
		'V4'
1076
	))->setHelp('Leave blank to disable. Enter the interface IP address of the other machine. Machines must be using CARP. ' .
1077
				'Interface\'s advskew determines whether the DHCPd process is Primary or Secondary. Ensure one machine\'s advskew &lt; 20 (and the other is &gt; 20).');
1078
}
1079

    
1080
if (!is_numeric($pool) && !($act == "newpool")) {
1081
	$section->addInput(new Form_Checkbox(
1082
		'staticarp',
1083
		'Static ARP',
1084
		'Enable Static ARP entries',
1085
		$pconfig['staticarp']
1086
	))->setHelp('This option persists even if DHCP server is disabled. Only the machines listed below will be able to communicate with the firewall on this interface.');
1087

    
1088
	$section->addInput(new Form_Checkbox(
1089
		'dhcpleaseinlocaltime',
1090
		'Time format change',
1091
		'Change DHCP display lease time from UTC to local time',
1092
		$pconfig['dhcpleaseinlocaltime']
1093
	))->setHelp('By default DHCP leases are displayed in UTC time.	By checking this box DHCP lease time will be displayed in local time and set to the time zone selected.' .
1094
				' This will be used for all DHCP interfaces lease time.');
1095
	$section->addInput(new Form_Checkbox(
1096
		'statsgraph',
1097
		'Statistics graphs',
1098
		'Enable RRD statistics graphs',
1099
		$pconfig['statsgraph']
1100
	))->setHelp('Enable this to add DHCP leases statistics to the RRD graphs. Disabled by default.');
1101
}
1102

    
1103
// DDNS
1104
$btnadv = new Form_Button(
1105
	'btnadvdns',
1106
	'Display Advanced',
1107
	null,
1108
	'fa-cog'
1109
);
1110

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

    
1113
$section->addInput(new Form_StaticText(
1114
	'Dynamic DNS',
1115
	$btnadv
1116
));
1117

    
1118
$section->addInput(new Form_Checkbox(
1119
	'ddnsupdate',
1120
	null,
1121
	'Enable registration of DHCP client names in DNS',
1122
	$pconfig['ddnsupdate']
1123
));
1124

    
1125
$section->addInput(new Form_Input(
1126
	'ddnsdomain',
1127
	'DDNS Domain',
1128
	'text',
1129
	$pconfig['ddnsdomain']
1130
))->setHelp('Enter the dynamic DNS domain which will be used to register client names in the DNS server.');
1131

    
1132
$section->addInput(new Form_Checkbox(
1133
	'ddnsforcehostname',
1134
	'DDNS Hostnames',
1135
	'Force dynamic DNS hostname to be the same as configured hostname for Static Mappings',
1136
	$pconfig['ddnsforcehostname']
1137
))->setHelp('Default registers host name option supplied by DHCP client.');
1138

    
1139
$section->addInput(new Form_IpAddress(
1140
	'ddnsdomainprimary',
1141
	'Primary DDNS address',
1142
	$pconfig['ddnsdomainprimary'],
1143
	'V4'
1144
))->setHelp('Primary domain name server IP address for the dynamic domain name.');
1145

    
1146
$section->addInput(new Form_Input(
1147
	'ddnsdomainkeyname',
1148
	'DNS Domain key',
1149
	'text',
1150
	$pconfig['ddnsdomainkeyname']
1151
))->setHelp('Dynamic DNS domain key name which will be used to register client names in the DNS server.');
1152

    
1153
$section->addInput(new Form_Select(
1154
	'ddnsdomainkeyalgorithm',
1155
	'Key algorithm',
1156
	$pconfig['ddnsdomainkeyalgorithm'],
1157
	array(
1158
		'hmac-md5' => 'HMAC-MD5 (legacy default)',
1159
		'hmac-sha1' => 'HMAC-SHA1',
1160
		'hmac-sha224' => 'HMAC-SHA224',
1161
		'hmac-sha256' => 'HMAC-SHA256 (current bind9 default)',
1162
		'hmac-sha384' => 'HMAC-SHA384',
1163
		'hmac-sha512' => 'HMAC-SHA512 (most secure)',
1164
	)
1165
));
1166

    
1167
$section->addInput(new Form_Input(
1168
	'ddnsdomainkey',
1169
	'DNS Domain key secret',
1170
	'text',
1171
	$pconfig['ddnsdomainkey']
1172
))->setHelp('Dynamic DNS domain key secret which will be used to register client names in the DNS server.');
1173

    
1174
$section->addInput(new Form_Select(
1175
	'ddnsclientupdates',
1176
	'DDNS Client Updates',
1177
	$pconfig['ddnsclientupdates'],
1178
	array(
1179
	    'allow' => gettext('Allow'),
1180
	    'deny' => gettext('Deny'),
1181
	    'ignore' => gettext('Ignore'))
1182
))->setHelp('How Forward entries are handled when client indicates they wish to update DNS.  ' .
1183
	    'Allow prevents DHCP from updating Forward entries, Deny indicates that DHCP will ' .
1184
	    'do the updates and the client should not, Ignore specifies that DHCP will do the ' .
1185
	    'update and the client can also attempt the update usually using a different domain name.');
1186

    
1187
// Advanced MAC
1188
$btnadv = new Form_Button(
1189
	'btnadvmac',
1190
	'Display Advanced',
1191
	null,
1192
	'fa-cog'
1193
);
1194

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

    
1197
$section->addInput(new Form_StaticText(
1198
	'MAC address control',
1199
	$btnadv
1200
));
1201

    
1202
$section->addInput(new Form_Input(
1203
	'mac_allow',
1204
	'MAC Allow',
1205
	'text',
1206
	$pconfig['mac_allow']
1207
))->setHelp('List of partial MAC addresses to allow, comma separated, no spaces, e.g.: 00:00:00,01:E5:FF');
1208

    
1209
$section->addInput(new Form_Input(
1210
	'mac_deny',
1211
	'MAC Deny',
1212
	'text',
1213
	$pconfig['mac_deny']
1214
))->setHelp('List of partial MAC addresses to deny access, comma separated, no spaces, e.g.: 00:00:00,01:E5:FF');
1215

    
1216
// Advanced NTP
1217
$btnadv = new Form_Button(
1218
	'btnadvntp',
1219
	'Display Advanced',
1220
	null,
1221
	'fa-cog'
1222
);
1223

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

    
1226
$section->addInput(new Form_StaticText(
1227
	'NTP',
1228
	$btnadv
1229
));
1230

    
1231
$section->addInput(new Form_IpAddress(
1232
	'ntp1',
1233
	'NTP Server 1',
1234
	$pconfig['ntp1'],
1235
	'HOSTV4'
1236
));
1237

    
1238
$section->addInput(new Form_IpAddress(
1239
	'ntp2',
1240
	'NTP Server 2',
1241
	$pconfig['ntp2'],
1242
	'HOSTV4'
1243
));
1244

    
1245
// Advanced TFTP
1246
$btnadv = new Form_Button(
1247
	'btnadvtftp',
1248
	'Display Advanced',
1249
	null,
1250
	'fa-cog'
1251
);
1252

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

    
1255
$section->addInput(new Form_StaticText(
1256
	'TFTP',
1257
	$btnadv
1258
));
1259

    
1260
$section->addInput(new Form_Input(
1261
	'tftp',
1262
	'TFTP Server',
1263
	'text',
1264
	$pconfig['tftp']
1265
))->setHelp('Leave blank to disable. Enter a valid IP address, hostname or URL for the TFTP server.');
1266

    
1267
// Advanced LDAP
1268
$btnadv = new Form_Button(
1269
	'btnadvldap',
1270
	'Display Advanced',
1271
	null,
1272
	'fa-cog'
1273
);
1274

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

    
1277
$section->addInput(new Form_StaticText(
1278
	'LDAP',
1279
	$btnadv
1280
));
1281

    
1282
$section->addInput(new Form_Input(
1283
	'ldap',
1284
	'LDAP Server URI',
1285
	'text',
1286
	$pconfig['ldap']
1287
))->setHelp('Leave blank to disable. Enter a full URI for the LDAP server in the form ldap://ldap.example.com/dc=example,dc=com ');
1288

    
1289
// Advanced Network Booting options
1290
$btnadv = new Form_Button(
1291
	'btnadvnwkboot',
1292
	'Display Advanced',
1293
	null,
1294
	'fa-cog'
1295
);
1296

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

    
1299
$section->addInput(new Form_StaticText(
1300
	'Network Booting',
1301
	$btnadv
1302
));
1303

    
1304
$section->addInput(new Form_Checkbox(
1305
	'netboot',
1306
	'Enable',
1307
	'Enables network booting',
1308
	$pconfig['netboot']
1309
));
1310

    
1311
$section->addInput(new Form_IpAddress(
1312
	'nextserver',
1313
	'Next Server',
1314
	$pconfig['nextserver'],
1315
	'V4'
1316
))->setHelp('Enter the IP address of the next server');
1317

    
1318
$section->addInput(new Form_Input(
1319
	'filename',
1320
	'Default BIOS file name',
1321
	'text',
1322
	$pconfig['filename']
1323
));
1324

    
1325
$section->addInput(new Form_Input(
1326
	'filename32',
1327
	'UEFI 32 bit file name',
1328
	'text',
1329
	$pconfig['filename32']
1330
));
1331

    
1332
$section->addInput(new Form_Input(
1333
	'filename64',
1334
	'UEFI 64 bit file name',
1335
	'text',
1336
	$pconfig['filename64']
1337
))->setHelp('Both a filename and a boot server must be configured for this to work! ' .
1338
			'All three filenames and a configured boot server are necessary for UEFI to work! ');
1339

    
1340
$section->addInput(new Form_Input(
1341
	'rootpath',
1342
	'Root path',
1343
	'text',
1344
	$pconfig['rootpath']
1345
))->setHelp('string-format: iscsi:(servername):(protocol):(port):(LUN):targetname ');
1346

    
1347
// Advanced Additional options
1348
$btnadv = new Form_Button(
1349
	'btnadvopts',
1350
	'Display Advanced',
1351
	null,
1352
	'fa-cog'
1353
);
1354

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

    
1357
$section->addInput(new Form_StaticText(
1358
	'Additional BOOTP/DHCP Options',
1359
	$btnadv
1360
));
1361

    
1362
$form->add($section);
1363

    
1364
$section = new Form_Section('Additional BOOTP/DHCP Options');
1365
$section->addClass('adnlopts');
1366

    
1367
$section->addInput(new Form_StaticText(
1368
	null,
1369
	'<div class="alert alert-info"> ' . gettext('Enter the DHCP option number and the value for each item to include in the DHCP lease information.') . ' ' .
1370
	sprintf(gettext('For a list of available options please visit this %1$s URL%2$s.%3$s'), '<a href="http://www.iana.org/assignments/bootp-dhcp-parameters/" target="_blank">', '</a>', '</div>')
1371
));
1372

    
1373
if (!$pconfig['numberoptions']) {
1374
	$pconfig['numberoptions'] = array();
1375
	$pconfig['numberoptions']['item']  = array(array('number' => '', 'type' => 'text', 'value' => ''));
1376
}
1377

    
1378
$customitemtypes = array(
1379
	'text' => gettext('Text'), 'string' => gettext('String'), 'boolean' => gettext('Boolean'),
1380
	'unsigned integer 8' => gettext('Unsigned 8-bit integer'), 'unsigned integer 16' => gettext('Unsigned 16-bit integer'), 'unsigned integer 32' => gettext('Unsigned 32-bit integer'),
1381
	'signed integer 8' => gettext('Signed 8-bit integer'), 'signed integer 16' => gettext('Signed 16-bit integer'), 'signed integer 32' => gettext('Signed 32-bit integer'), 'ip-address' => gettext('IP address or host')
1382
);
1383

    
1384
$numrows = count($item) -1;
1385
$counter = 0;
1386

    
1387
$numrows = count($pconfig['numberoptions']['item']) -1;
1388

    
1389
foreach ($pconfig['numberoptions']['item'] as $item) {
1390
	$number = $item['number'];
1391
	$itemtype = $item['type'];
1392
	$value = base64_decode($item['value']);
1393

    
1394
	$group = new Form_Group(($counter == 0) ? 'Option':null);
1395
	$group->addClass('repeatable');
1396

    
1397
	$group->add(new Form_Input(
1398
		'number' . $counter,
1399
		null,
1400
		'number',
1401
		$number,
1402
		['min'=>'1', 'max'=>'254']
1403
	))->setHelp($numrows == $counter ? 'Number':null);
1404

    
1405

    
1406
	$group->add(new Form_Select(
1407
		'itemtype' . $counter,
1408
		null,
1409
		$itemtype,
1410
		$customitemtypes
1411
	))->setWidth(3)->setHelp($numrows == $counter ? 'Type':null);
1412

    
1413
	$group->add(new Form_Input(
1414
		'value' . $counter,
1415
		null,
1416
		'text',
1417
		$value
1418
	))->setHelp($numrows == $counter ? 'Value':null);
1419

    
1420
	$group->add(new Form_Button(
1421
		'deleterow' . $counter,
1422
		'Delete',
1423
		null,
1424
		'fa-trash'
1425
	))->addClass('btn-warning');
1426

    
1427
	$section->add($group);
1428

    
1429
	$counter++;
1430
}
1431

    
1432
$section->addInput(new Form_Button(
1433
	'addrow',
1434
	'Add',
1435
	null,
1436
	'fa-plus'
1437
))->addClass('btn-success');
1438

    
1439
$form->add($section);
1440

    
1441
if ($act == "newpool") {
1442
	$form->addGlobal(new Form_Input(
1443
		'act',
1444
		null,
1445
		'hidden',
1446
		'newpool'
1447
	));
1448
}
1449

    
1450
if (is_numeric($pool)) {
1451
	$form->addGlobal(new Form_Input(
1452
		'pool',
1453
		null,
1454
		'hidden',
1455
		$pool
1456
	));
1457
}
1458

    
1459
$form->addGlobal(new Form_Input(
1460
	'if',
1461
	null,
1462
	'hidden',
1463
	$if
1464
));
1465

    
1466
print($form);
1467

    
1468
// DHCP Static Mappings table
1469

    
1470
if (!is_numeric($pool) && !($act == "newpool")) {
1471

    
1472
	// Decide whether display of the Client Id column is needed.
1473
	$got_cid = false;
1474
	if (is_array($a_maps)) {
1475
		foreach ($a_maps as $map) {
1476
			if (!empty($map['cid'])) {
1477
				$got_cid = true;
1478
				break;
1479
			}
1480
		}
1481
	}
1482
?>
1483

    
1484
<div class="panel panel-default">
1485
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("DHCP Static Mappings for this Interface")?></h2></div>
1486
	<div class="table-responsive">
1487
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
1488
				<thead>
1489
					<tr>
1490
						<th><?=gettext("Static ARP")?></th>
1491
						<th><?=gettext("MAC address")?></th>
1492
<?php
1493
	if ($got_cid):
1494
?>
1495
						<th><?=gettext("Client Id")?></th>
1496
<?php
1497
	endif;
1498
?>
1499
						<th><?=gettext("IP address")?></th>
1500
						<th><?=gettext("Hostname")?></th>
1501
						<th><?=gettext("Description")?></th>
1502
						<th></th>
1503
					</tr>
1504
				</thead>
1505
<?php
1506
	if (is_array($a_maps)) {
1507
		$i = 0;
1508
?>
1509
				<tbody>
1510
<?php
1511
		foreach ($a_maps as $mapent) {
1512
?>
1513
					<tr>
1514
						<td class="text-center" ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1515
							<?php if (isset($mapent['arp_table_static_entry'])): ?>
1516
								<i class="fa fa-check"></i>
1517
							<?php endif; ?>
1518
						</td>
1519
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1520
							<?=htmlspecialchars($mapent['mac'])?>
1521
						</td>
1522
<?php
1523
			if ($got_cid):
1524
?>
1525
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1526
							<?=htmlspecialchars($mapent['cid'])?>
1527
						</td>
1528
<?php
1529
			endif;
1530
?>
1531
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1532
							<?=htmlspecialchars($mapent['ipaddr'])?>
1533
						</td>
1534
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1535
							<?=htmlspecialchars($mapent['hostname'])?>
1536
						</td>
1537
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1538
							<?=htmlspecialchars($mapent['descr'])?>
1539
						</td>
1540
						<td>
1541
							<a class="fa fa-pencil"	title="<?=gettext('Edit static mapping')?>"	href="services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>"></a>
1542
							<a class="fa fa-trash"	title="<?=gettext('Delete static mapping')?>"	href="services_dhcp.php?if=<?=htmlspecialchars($if)?>&amp;act=del&amp;id=<?=$i?>" usepost></a>
1543
						</td>
1544
					</tr>
1545
<?php
1546
		$i++;
1547
		}
1548
?>
1549
				</tbody>
1550
<?php
1551
	}
1552
?>
1553
		</table>
1554
	</div>
1555
</div>
1556

    
1557
<nav class="action-buttons">
1558
	<a href="services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>" class="btn btn-sm btn-success">
1559
		<i class="fa fa-plus icon-embed-btn"></i>
1560
		<?=gettext("Add")?>
1561
	</a>
1562
</nav>
1563
<?php
1564
}
1565
?>
1566

    
1567
<script type="text/javascript">
1568
//<![CDATA[
1569
events.push(function() {
1570

    
1571
	// Show advanced DNS options ======================================================================================
1572
	var showadvdns = false;
1573

    
1574
	function show_advdns(ispageload) {
1575
		var text;
1576
		// On page load decide the initial state based on the data.
1577
		if (ispageload) {
1578
<?php
1579
			if (!$pconfig['ddnsupdate'] &&
1580
				!$pconfig['ddnsforcehostname'] &&
1581
				empty($pconfig['ddnsdomain']) &&
1582
				empty($pconfig['ddnsdomainprimary']) &&
1583
			    empty($pconfig['ddnsdomainkeyname']) &&
1584
			    (empty($pconfig['ddnsdomainkeyalgorithm']) || ($pconfig['ddnsdomainkeyalgorithm'] == "hmac-md5")) &&
1585
			    (empty($pconfig['ddnsclientupdates']) || ($pconfig['ddnsclientupdates'] == "allow")) &&
1586
			    empty($pconfig['ddnsdomainkey'])) {
1587
				$showadv = false;
1588
			} else {
1589
				$showadv = true;
1590
			}
1591
?>
1592
			showadvdns = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1593
		} else {
1594
			// It was a click, swap the state.
1595
			showadvdns = !showadvdns;
1596
		}
1597

    
1598
		hideCheckbox('ddnsupdate', !showadvdns);
1599
		hideInput('ddnsdomain', !showadvdns);
1600
		hideCheckbox('ddnsforcehostname', !showadvdns);
1601
		hideInput('ddnsdomainprimary', !showadvdns);
1602
		hideInput('ddnsdomainkeyname', !showadvdns);
1603
		hideInput('ddnsdomainkeyalgorithm', !showadvdns);
1604
		hideInput('ddnsdomainkey', !showadvdns);
1605
		hideInput('ddnsclientupdates', !showadvdns);
1606

    
1607
		if (showadvdns) {
1608
			text = "<?=gettext('Hide Advanced');?>";
1609
		} else {
1610
			text = "<?=gettext('Display Advanced');?>";
1611
		}
1612
		$('#btnadvdns').html('<i class="fa fa-cog"></i> ' + text);
1613
	}
1614

    
1615
	$('#btnadvdns').click(function(event) {
1616
		show_advdns();
1617
	});
1618

    
1619
	// Show advanced MAC options ======================================================================================
1620
	var showadvmac = false;
1621

    
1622
	function show_advmac(ispageload) {
1623
		var text;
1624
		// On page load decide the initial state based on the data.
1625
		if (ispageload) {
1626
<?php
1627
			if (empty($pconfig['mac_allow']) && empty($pconfig['mac_deny'])) {
1628
				$showadv = false;
1629
			} else {
1630
				$showadv = true;
1631
			}
1632
?>
1633
			showadvmac = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1634
		} else {
1635
			// It was a click, swap the state.
1636
			showadvmac = !showadvmac;
1637
		}
1638

    
1639
		hideInput('mac_allow', !showadvmac);
1640
		hideInput('mac_deny', !showadvmac);
1641

    
1642
		if (showadvmac) {
1643
			text = "<?=gettext('Hide Advanced');?>";
1644
		} else {
1645
			text = "<?=gettext('Display Advanced');?>";
1646
		}
1647
		$('#btnadvmac').html('<i class="fa fa-cog"></i> ' + text);
1648
	}
1649

    
1650
	$('#btnadvmac').click(function(event) {
1651
		show_advmac();
1652
	});
1653

    
1654
	// Show advanced NTP options ======================================================================================
1655
	var showadvntp = false;
1656

    
1657
	function show_advntp(ispageload) {
1658
		var text;
1659
		// On page load decide the initial state based on the data.
1660
		if (ispageload) {
1661
<?php
1662
			if (empty($pconfig['ntp1']) && empty($pconfig['ntp2'])) {
1663
				$showadv = false;
1664
			} else {
1665
				$showadv = true;
1666
			}
1667
?>
1668
			showadvntp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1669
		} else {
1670
			// It was a click, swap the state.
1671
			showadvntp = !showadvntp;
1672
		}
1673

    
1674
		hideInput('ntp1', !showadvntp);
1675
		hideInput('ntp2', !showadvntp);
1676

    
1677
		if (showadvntp) {
1678
			text = "<?=gettext('Hide Advanced');?>";
1679
		} else {
1680
			text = "<?=gettext('Display Advanced');?>";
1681
		}
1682
		$('#btnadvntp').html('<i class="fa fa-cog"></i> ' + text);
1683
	}
1684

    
1685
	$('#btnadvntp').click(function(event) {
1686
		show_advntp();
1687
	});
1688

    
1689
	// Show advanced TFTP options ======================================================================================
1690
	var showadvtftp = false;
1691

    
1692
	function show_advtftp(ispageload) {
1693
		var text;
1694
		// On page load decide the initial state based on the data.
1695
		if (ispageload) {
1696
<?php
1697
			if (empty($pconfig['tftp'])) {
1698
				$showadv = false;
1699
			} else {
1700
				$showadv = true;
1701
			}
1702
?>
1703
			showadvtftp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1704
		} else {
1705
			// It was a click, swap the state.
1706
			showadvtftp = !showadvtftp;
1707
		}
1708

    
1709
		hideInput('tftp', !showadvtftp);
1710

    
1711
		if (showadvtftp) {
1712
			text = "<?=gettext('Hide Advanced');?>";
1713
		} else {
1714
			text = "<?=gettext('Display Advanced');?>";
1715
		}
1716
		$('#btnadvtftp').html('<i class="fa fa-cog"></i> ' + text);
1717
	}
1718

    
1719
	$('#btnadvtftp').click(function(event) {
1720
		show_advtftp();
1721
	});
1722

    
1723
	// Show advanced LDAP options ======================================================================================
1724
	var showadvldap = false;
1725

    
1726
	function show_advldap(ispageload) {
1727
		var text;
1728
		// On page load decide the initial state based on the data.
1729
		if (ispageload) {
1730
<?php
1731
			if (empty($pconfig['ldap'])) {
1732
				$showadv = false;
1733
			} else {
1734
				$showadv = true;
1735
			}
1736
?>
1737
			showadvldap = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1738
		} else {
1739
			// It was a click, swap the state.
1740
			showadvldap = !showadvldap;
1741
		}
1742

    
1743
		hideInput('ldap', !showadvldap);
1744

    
1745
		if (showadvldap) {
1746
			text = "<?=gettext('Hide Advanced');?>";
1747
		} else {
1748
			text = "<?=gettext('Display Advanced');?>";
1749
		}
1750
		$('#btnadvldap').html('<i class="fa fa-cog"></i> ' + text);
1751
	}
1752

    
1753
	$('#btnadvldap').click(function(event) {
1754
		show_advldap();
1755
	});
1756

    
1757
	// Show advanced additional opts options ===========================================================================
1758
	var showadvopts = false;
1759

    
1760
	function show_advopts(ispageload) {
1761
		var text;
1762
		// On page load decide the initial state based on the data.
1763
		if (ispageload) {
1764
<?php
1765
			if (empty($pconfig['numberoptions']) ||
1766
			    (empty($pconfig['numberoptions']['item'][0]['number']) && (empty($pconfig['numberoptions']['item'][0]['value'])))) {
1767
				$showadv = false;
1768
			} else {
1769
				$showadv = true;
1770
			}
1771
?>
1772
			showadvopts = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1773
		} else {
1774
			// It was a click, swap the state.
1775
			showadvopts = !showadvopts;
1776
		}
1777

    
1778
		hideClass('adnlopts', !showadvopts);
1779

    
1780
		if (showadvopts) {
1781
			text = "<?=gettext('Hide Advanced');?>";
1782
		} else {
1783
			text = "<?=gettext('Display Advanced');?>";
1784
		}
1785
		$('#btnadvopts').html('<i class="fa fa-cog"></i> ' + text);
1786
	}
1787

    
1788
	$('#btnadvopts').click(function(event) {
1789
		show_advopts();
1790
	});
1791

    
1792
	// Show advanced Network Booting options ===========================================================================
1793
	var showadvnwkboot = false;
1794

    
1795
	function show_advnwkboot(ispageload) {
1796
		var text;
1797
		// On page load decide the initial state based on the data.
1798
		if (ispageload) {
1799
<?php
1800
			if (empty($pconfig['netboot'])) {
1801
				$showadv = false;
1802
			} else {
1803
				$showadv = true;
1804
			}
1805
?>
1806
			showadvnwkboot = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1807
		} else {
1808
			// It was a click, swap the state.
1809
			showadvnwkboot = !showadvnwkboot;
1810
		}
1811

    
1812
		hideCheckbox('netboot', !showadvnwkboot);
1813
		hideInput('nextserver', !showadvnwkboot);
1814
		hideInput('filename', !showadvnwkboot);
1815
		hideInput('filename32', !showadvnwkboot);
1816
		hideInput('filename64', !showadvnwkboot);
1817
		hideInput('rootpath', !showadvnwkboot);
1818

    
1819
		if (showadvnwkboot) {
1820
			text = "<?=gettext('Hide Advanced');?>";
1821
		} else {
1822
			text = "<?=gettext('Display Advanced');?>";
1823
		}
1824
		$('#btnadvnwkboot').html('<i class="fa fa-cog"></i> ' + text);
1825
	}
1826

    
1827
	$('#btnadvnwkboot').click(function(event) {
1828
		show_advnwkboot();
1829
	});
1830

    
1831
	// ---------- On initial page load ------------------------------------------------------------
1832

    
1833
	show_advdns(true);
1834
	show_advmac(true);
1835
	show_advntp(true);
1836
	show_advtftp(true);
1837
	show_advldap(true);
1838
	show_advopts(true);
1839
	show_advnwkboot(true);
1840

    
1841
	// Suppress "Delete row" button if there are fewer than two rows
1842
	checkLastRow();
1843
});
1844
//]]>
1845
</script>
1846

    
1847
<?php include("foot.inc");
(124-124/234)