Project

General

Profile

Download (55 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
}
205

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

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

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

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

    
222
	return true;
223
}
224

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

    
227
	unset($input_errors);
228

    
229
	$pconfig = $_POST;
230

    
231
	$numberoptions = array();
232
	for ($x = 0; $x < 99; $x++) {
233
		if (isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) {
234
			$numbervalue = array();
235
			$numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]);
236
			$numbervalue['type'] = htmlspecialchars($_POST["itemtype{$x}"]);
237
			$numbervalue['value'] = base64_encode($_POST["value{$x}"]);
238
			$numberoptions['item'][] = $numbervalue;
239
		}
240
	}
241

    
242
	// Reload the new pconfig variable that the form uses.
243
	$pconfig['numberoptions'] = $numberoptions;
244

    
245
	/* input validation */
246

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

    
252
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
253
	}
254

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

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

    
282
	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']))) {
283
		$input_errors[] = gettext("A valid IP address must be specified for each of the DNS servers.");
284
	}
285

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

    
290
	if (isset($config['captiveportal']) && is_array($config['captiveportal'])) {
291
		$deftime = 7200; // Default value if it's empty
292
		if (is_numeric($_POST['deftime'])) {
293
			$deftime = $_POST['deftime'];
294
		}
295

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

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

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

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

    
357
	if (gen_subnet($ifcfgip, $ifcfgsn) == $_POST['range_from']) {
358
		$input_errors[] = gettext("The network address cannot be used in the starting subnet range.");
359
	}
360
	if (gen_subnet_max($ifcfgip, $ifcfgsn) == $_POST['range_to']) {
361
		$input_errors[] = gettext("The broadcast address cannot be used in the ending subnet range.");
362
	}
363

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

    
375
	$noip = false;
376
	if (is_array($a_maps)) {
377
		foreach ($a_maps as $map) {
378
			if (empty($map['ipaddr'])) {
379
				$noip = true;
380
			}
381
		}
382
	}
383

    
384
	if ($_POST['staticarp'] && $noip) {
385
		$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.");
386
	}
387

    
388
	if (is_array($pconfig['numberoptions']['item'])) {
389
		foreach ($pconfig['numberoptions']['item'] as $numberoption) {
390
			$numberoption_value = base64_decode($numberoption['value']);
391
			if ($numberoption['type'] == 'text' && strstr($numberoption_value, '"')) {
392
				$input_errors[] = gettext("Text type cannot include quotation marks.");
393
			} else if ($numberoption['type'] == 'string' && !preg_match('/^"[^"]*"$/', $numberoption_value) && !preg_match('/^[0-9a-f]{2}(?:\:[0-9a-f]{2})*$/i', $numberoption_value)) {
394
				$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");
395
			} else if ($numberoption['type'] == 'boolean' && $numberoption_value != 'true' && $numberoption_value != 'false' && $numberoption_value != 'on' && $numberoption_value != 'off') {
396
				$input_errors[] = gettext("Boolean type must be true, false, on, or off.");
397
			} else if ($numberoption['type'] == 'unsigned integer 8' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 255)) {
398
				$input_errors[] = gettext("Unsigned 8-bit integer type must be a number in the range 0 to 255.");
399
			} else if ($numberoption['type'] == 'unsigned integer 16' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 65535)) {
400
				$input_errors[] = gettext("Unsigned 16-bit integer type must be a number in the range 0 to 65535.");
401
			} else if ($numberoption['type'] == 'unsigned integer 32' && (!is_numeric($numberoption_value) || $numberoption_value < 0 || $numberoption_value > 4294967295)) {
402
				$input_errors[] = gettext("Unsigned 32-bit integer type must be a number in the range 0 to 4294967295.");
403
			} else if ($numberoption['type'] == 'signed integer 8' && (!is_numeric($numberoption_value) || $numberoption_value < -128 || $numberoption_value > 127)) {
404
				$input_errors[] = gettext("Signed 8-bit integer type must be a number in the range -128 to 127.");
405
			} else if ($numberoption['type'] == 'signed integer 16' && (!is_numeric($numberoption_value) || $numberoption_value < -32768 || $numberoption_value > 32767)) {
406
				$input_errors[] = gettext("Signed 16-bit integer type must be a number in the range -32768 to 32767.");
407
			} else if ($numberoption['type'] == 'signed integer 32' && (!is_numeric($numberoption_value) || $numberoption_value < -2147483648 || $numberoption_value > 2147483647)) {
408
				$input_errors[] = gettext("Signed 32-bit integer type must be a number in the range -2147483648 to 2147483647.");
409
			} else if ($numberoption['type'] == 'ip-address' && !is_ipaddrv4($numberoption_value) && !is_hostname($numberoption_value)) {
410
				$input_errors[] = gettext("IP address or host type must be an IP address or host name.");
411
			}
412
		}
413
	}
414

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

    
424
		/* If disabling DHCP Server, make sure that DHCP registration isn't enabled for DNS forwarder/resolver */
425
		if (!$_POST['enable']) {
426
			if (isset($config['dnsmasq']['enable']) &&
427
			    (isset($config['dnsmasq']['regdhcp']) ||
428
			    isset($config['dnsmasq']['regdhcpstatic']) ||
429
			    isset($config['dnsmasq']['dhcpfirst']))) {
430
				$input_errors[] = gettext(
431
				    "Disable DHCP Registration features in DNS Forwarder before disabling DHCP Server.");
432
			}
433
			if (isset($config['unbound']['enable']) &&
434
			    (isset($config['unbound']['regdhcp']) ||
435
			    isset($config['unbound']['regdhcpstatic']))) {
436
				$input_errors[] = gettext(
437
				    "Disable DHCP Registration features in DNS Resolver before disabling DHCP Server.");
438
			}
439
		}
440
	}
441

    
442
	// 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.
443
	if (!$input_errors && $_POST['range_from'] && $_POST['range_to']) {
444
		/* make sure the range lies within the current subnet */
445
		if (ip_greater_than($_POST['range_from'], $_POST['range_to'])) {
446
			$input_errors[] = gettext("The range is invalid (first element higher than second element).");
447
		}
448

    
449
		if (!is_inrange_v4($_POST['range_from'], $subnet_start, $subnet_end) ||
450
			!is_inrange_v4($_POST['range_to'], $subnet_start, $subnet_end)) {
451
			$input_errors[] = gettext("The specified range lies outside of the current subnet.");
452
		}
453

    
454
		if (is_numeric($pool) || ($act == "newpool")) {
455
			if (is_inrange_v4($_POST['range_from'],
456
				$config['dhcpd'][$if]['range']['from'],
457
				$config['dhcpd'][$if]['range']['to']) ||
458
				is_inrange_v4($_POST['range_to'],
459
				$config['dhcpd'][$if]['range']['from'],
460
				$config['dhcpd'][$if]['range']['to'])) {
461
				$input_errors[] = gettext("The specified range must not be within the DHCP range for this interface.");
462
			}
463
		}
464

    
465
		foreach ($a_pools as $id => $p) {
466
			if (is_numeric($pool) && ($id == $pool)) {
467
				continue;
468
			}
469

    
470
			if (is_inrange_v4($_POST['range_from'],
471
				$p['range']['from'], $p['range']['to']) ||
472
				is_inrange_v4($_POST['range_to'],
473
				$p['range']['from'], $p['range']['to'])) {
474
				$input_errors[] = gettext("The specified range must not be within the range configured on a DHCP pool for this interface.");
475
				break;
476
			}
477
		}
478

    
479
		if (is_array($a_maps)) {
480
			foreach ($a_maps as $map) {
481
				if (empty($map['ipaddr'])) {
482
					continue;
483
				}
484
				if (is_inrange_v4($map['ipaddr'], $_POST['range_from'], $_POST['range_to'])) {
485
					$input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings."));
486
					break;
487
				}
488
			}
489
		}
490
	}
491

    
492
	if (!$input_errors) {
493
		if (!is_numeric($pool)) {
494
			if ($act == "newpool") {
495
				$dhcpdconf = array();
496
			} else {
497
				if (!is_array($config['dhcpd'][$if])) {
498
					$config['dhcpd'][$if] = array();
499
				}
500
				$dhcpdconf = $config['dhcpd'][$if];
501
			}
502
		} else {
503
			if (is_array($a_pools[$pool])) {
504
				$dhcpdconf = $a_pools[$pool];
505
			} else {
506
				// Someone specified a pool but it doesn't exist. Punt.
507
				header("Location: services_dhcp.php");
508
				exit;
509
			}
510
		}
511
		if (!is_array($dhcpdconf['range'])) {
512
			$dhcpdconf['range'] = array();
513
		}
514

    
515
		$dhcpd_enable_changed = false;
516

    
517
		// Global Options
518
		if (!is_numeric($pool) && !($act == "newpool")) {
519
			$old_dhcpd_enable = isset($dhcpdconf['enable']);
520
			$new_dhcpd_enable = ($_POST['enable']) ? true : false;
521
			if ($old_dhcpd_enable != $new_dhcpd_enable) {
522
				/* DHCP has been enabled or disabled. The pf ruleset will need to be rebuilt to allow or disallow DHCP. */
523
				$dhcpd_enable_changed = true;
524
			}
525

    
526
			$dhcpdconf['enable'] = $new_dhcpd_enable;
527
			$dhcpdconf['staticarp'] = ($_POST['staticarp']) ? true : false;
528
			$previous = $dhcpdconf['failover_peerip'];
529
			if ($previous != $_POST['failover_peerip']) {
530
				mwexec("/bin/rm -rf /var/dhcpd/var/db/*");
531
			}
532

    
533
			$dhcpdconf['failover_peerip'] = $_POST['failover_peerip'];
534
			// dhcpleaseinlocaltime is global to all interfaces. So update the setting on all interfaces.
535
			foreach ($config['dhcpd'] as &$dhcpdifitem) {
536
				$dhcpdifitem['dhcpleaseinlocaltime'] = $_POST['dhcpleaseinlocaltime'];
537
			}
538
		} else {
539
			// Options that exist only in pools
540
			$dhcpdconf['descr'] = $_POST['descr'];
541
		}
542

    
543
		// Options that can be global or per-pool.
544
		$dhcpdconf['range']['from'] = $_POST['range_from'];
545
		$dhcpdconf['range']['to'] = $_POST['range_to'];
546
		$dhcpdconf['defaultleasetime'] = $_POST['deftime'];
547
		$dhcpdconf['maxleasetime'] = $_POST['maxtime'];
548
		$dhcpdconf['netmask'] = $_POST['netmask'];
549

    
550
		unset($dhcpdconf['winsserver']);
551
		if ($_POST['wins1']) {
552
			$dhcpdconf['winsserver'][] = $_POST['wins1'];
553
		}
554
		if ($_POST['wins2']) {
555
			$dhcpdconf['winsserver'][] = $_POST['wins2'];
556
		}
557

    
558
		unset($dhcpdconf['dnsserver']);
559
		if ($_POST['dns1']) {
560
			$dhcpdconf['dnsserver'][] = $_POST['dns1'];
561
		}
562
		if ($_POST['dns2']) {
563
			$dhcpdconf['dnsserver'][] = $_POST['dns2'];
564
		}
565
		if ($_POST['dns3']) {
566
			$dhcpdconf['dnsserver'][] = $_POST['dns3'];
567
		}
568
		if ($_POST['dns4']) {
569
			$dhcpdconf['dnsserver'][] = $_POST['dns4'];
570
		}
571

    
572
		$dhcpdconf['gateway'] = $_POST['gateway'];
573
		$dhcpdconf['domain'] = $_POST['domain'];
574
		$dhcpdconf['domainsearchlist'] = $_POST['domainsearchlist'];
575
		$dhcpdconf['ignorebootp'] = ($_POST['ignorebootp']) ? true : false;
576
		$dhcpdconf['denyunknown'] = ($_POST['denyunknown']) ? true : false;
577
		$dhcpdconf['ignoreclientuids'] = ($_POST['ignoreclientuids']) ? true : false;
578
		$dhcpdconf['nonak'] = ($_POST['nonak']) ? true : false;
579
		$dhcpdconf['ddnsdomain'] = $_POST['ddnsdomain'];
580
		$dhcpdconf['ddnsdomainprimary'] = $_POST['ddnsdomainprimary'];
581
		$dhcpdconf['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname'];
582
		$dhcpdconf['ddnsdomainkeyalgorithm'] = $_POST['ddnsdomainkeyalgorithm'];
583
		$dhcpdconf['ddnsdomainkey'] = $_POST['ddnsdomainkey'];
584
		$dhcpdconf['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false;
585
		$dhcpdconf['ddnsforcehostname'] = ($_POST['ddnsforcehostname']) ? true : false;
586
		$dhcpdconf['mac_allow'] = $_POST['mac_allow'];
587
		$dhcpdconf['mac_deny'] = $_POST['mac_deny'];
588

    
589
		unset($dhcpdconf['ntpserver']);
590
		if ($_POST['ntp1']) {
591
			$dhcpdconf['ntpserver'][] = $_POST['ntp1'];
592
		}
593
		if ($_POST['ntp2']) {
594
			$dhcpdconf['ntpserver'][] = $_POST['ntp2'];
595
		}
596

    
597
		$dhcpdconf['tftp'] = $_POST['tftp'];
598
		$dhcpdconf['ldap'] = $_POST['ldap'];
599
		$dhcpdconf['netboot'] = ($_POST['netboot']) ? true : false;
600
		$dhcpdconf['nextserver'] = $_POST['nextserver'];
601
		$dhcpdconf['filename'] = $_POST['filename'];
602
		$dhcpdconf['filename32'] = $_POST['filename32'];
603
		$dhcpdconf['filename64'] = $_POST['filename64'];
604
		$dhcpdconf['rootpath'] = $_POST['rootpath'];
605
		unset($dhcpdconf['statsgraph']);
606
		if ($_POST['statsgraph']) {
607
			$dhcpdconf['statsgraph'] = $_POST['statsgraph'];
608
			enable_rrd_graphing();
609
		}
610

    
611
		// Handle the custom options rowhelper
612
		if (isset($dhcpdconf['numberoptions']['item'])) {
613
			unset($dhcpdconf['numberoptions']['item']);
614
		}
615

    
616
		$dhcpdconf['numberoptions'] = $numberoptions;
617

    
618
		if (is_numeric($pool) && is_array($a_pools[$pool])) {
619
			$a_pools[$pool] = $dhcpdconf;
620
		} elseif ($act == "newpool") {
621
			$a_pools[] = $dhcpdconf;
622
		} else {
623
			$config['dhcpd'][$if] = $dhcpdconf;
624
		}
625

    
626
		write_config();
627
	}
628
}
629

    
630
if ((isset($_POST['save']) || isset($_POST['apply'])) && (!$input_errors)) {
631
	$changes_applied = true;
632
	$retval = 0;
633
	$retvaldhcp = 0;
634
	$retvaldns = 0;
635
	/* dnsmasq_configure calls dhcpd_configure */
636
	/* no need to restart dhcpd twice */
637
	if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic']))	{
638
		$retvaldns |= services_dnsmasq_configure();
639
		if ($retvaldns == 0) {
640
			clear_subsystem_dirty('hosts');
641
			clear_subsystem_dirty('staticmaps');
642
		}
643
	} else if (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcpstatic'])) {
644
		$retvaldns |= services_unbound_configure();
645
		if ($retvaldns == 0) {
646
			clear_subsystem_dirty('unbound');
647
			clear_subsystem_dirty('hosts');
648
			clear_subsystem_dirty('staticmaps');
649
		}
650
	} else {
651
		$retvaldhcp |= services_dhcpd_configure();
652
		if ($retvaldhcp == 0) {
653
			clear_subsystem_dirty('staticmaps');
654
		}
655
	}
656
	/* BIND package - Bug #3710 */
657
	if (!function_exists('is_package_installed')) {
658
		require_once('pkg-utils.inc');
659
	}
660
	if (is_package_installed('pfSense-pkg-bind') && isset($config['installedpackages']['bind']['config'][0]['enable_bind'])) {
661
		$reloadbind = false;
662
		if (is_array($config['installedpackages']['bindzone'])) {
663
			$bindzone = $config['installedpackages']['bindzone']['config'];
664
		} else {
665
			$bindzone = array();
666
		}
667
		for ($x = 0; $x < sizeof($bindzone); $x++) {
668
			$zone = $bindzone[$x];
669
			if ($zone['regdhcpstatic'] == 'on') {
670
				$reloadbind = true;
671
				break;
672
			}
673
		}
674
		if ($reloadbind === true) {
675
			if (file_exists("/usr/local/pkg/bind.inc")) {
676
				require_once("/usr/local/pkg/bind.inc");
677
				bind_sync();
678
			}
679
		}
680
	}
681
	if ($dhcpd_enable_changed) {
682
		$retvalfc |= filter_configure();
683
	}
684

    
685
	if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) {
686
		$retval = 1;
687
	}
688
}
689

    
690
if ($act == "delpool") {
691
	if ($a_pools[$_POST['id']]) {
692
		unset($a_pools[$_POST['id']]);
693
		write_config();
694
		header("Location: services_dhcp.php?if={$if}");
695
		exit;
696
	}
697
}
698

    
699
if ($act == "del") {
700
	if (isset($a_maps[$_POST['id']])) {
701
		/* Remove static ARP entry, if necessary */
702
		if (isset($a_maps[$_POST['id']]['arp_table_static_entry'])) {
703
			mwexec("/usr/sbin/arp -d " . escapeshellarg($a_maps[$_POST['id']]['ipaddr']));
704
		}
705
		unset($a_maps[$_POST['id']]);
706
		write_config();
707
		if (isset($config['dhcpd'][$if]['enable'])) {
708
			mark_subsystem_dirty('staticmaps');
709
			if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic'])) {
710
				mark_subsystem_dirty('hosts');
711
			}
712
		}
713

    
714
		header("Location: services_dhcp.php?if={$if}");
715
		exit;
716
	}
717
}
718

    
719
// Build an HTML table that can be inserted into a Form_StaticText element
720
function build_pooltable() {
721
	global $a_pools, $if;
722

    
723
	$pooltbl =	'<div class="table-responsive">';
724
	$pooltbl .=		'<table class="table table-striped table-hover table-condensed">';
725
	$pooltbl .=			'<thead>';
726
	$pooltbl .=				'<tr>';
727
	$pooltbl .=					'<th>' . gettext("Pool Start") . '</th>';
728
	$pooltbl .=					'<th>' . gettext("Pool End") . '</th>';
729
	$pooltbl .=					'<th>' . gettext("Description") . '</th>';
730
	$pooltbl .=					'<th>' . gettext("Actions") . '</th>';
731
	$pooltbl .=				'</tr>';
732
	$pooltbl .=			'</thead>';
733
	$pooltbl .=			'<tbody>';
734

    
735
	if (is_array($a_pools)) {
736
		$i = 0;
737
		foreach ($a_pools as $poolent) {
738
			if (!empty($poolent['range']['from']) && !empty($poolent['range']['to'])) {
739
				$pooltbl .= '<tr>';
740
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
741
							htmlspecialchars($poolent['range']['from']) . '</td>';
742

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

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

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

    
751
				$pooltbl .= ' <a class="fa fa-trash" title="'. gettext("Delete pool") . '" href="services_dhcp.php?if=' . htmlspecialchars($if) . '&act=delpool&id=' . $i . '" usepost></a></td>';
752
				$pooltbl .= '</tr>';
753
			}
754
		$i++;
755
		}
756
	}
757

    
758
	$pooltbl .=			'</tbody>';
759
	$pooltbl .=		'</table>';
760
	$pooltbl .= '</div>';
761

    
762
	return($pooltbl);
763
}
764

    
765
$pgtitle = array(gettext("Services"), gettext("DHCP Server"));
766
$pglinks = array("", "services_dhcp.php");
767

    
768
if (!empty($if) && isset($iflist[$if])) {
769
	$pgtitle[] = $iflist[$if];
770
	$pglinks[] = "@self";
771
}
772
$shortcut_section = "dhcp";
773

    
774
include("head.inc");
775

    
776
if ($input_errors) {
777
	print_input_errors($input_errors);
778
}
779

    
780
if ($changes_applied) {
781
	print_apply_result_box($retval);
782
}
783

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

    
788
/* active tabs */
789
$tab_array = array();
790
$tabscounter = 0;
791
$i = 0;
792
$have_small_subnet = false;
793

    
794
foreach ($iflist as $ifent => $ifname) {
795
	$oc = $config['interfaces'][$ifent];
796

    
797
	/* Not static IPv4 or subnet >= 31 */
798
	if ($oc['subnet'] >= 31) {
799
		$have_small_subnet = true;
800
		$example_name = $ifname;
801
		$example_cidr = $oc['subnet'];
802
		continue;
803
	}
804
	if (!is_ipaddrv4($oc['ipaddr']) || empty($oc['subnet'])) {
805
		continue;
806
	}
807

    
808
	if ($ifent == $if) {
809
		$active = true;
810
	} else {
811
		$active = false;
812
	}
813

    
814
	$tab_array[] = array($ifname, $active, "services_dhcp.php?if={$ifent}");
815
	$tabscounter++;
816
}
817

    
818
if ($tabscounter == 0) {
819
	if ($have_small_subnet) {
820
		$sentence2 = sprintf(gettext('%1$s has a CIDR mask of %2$s, which does not contain enough addresses.'), htmlspecialchars($example_name), htmlspecialchars($example_cidr));
821
	} else {
822
		$sentence2 = gettext("This system has no interfaces configured with a static IPv4 address.");
823
	}
824
	print_info_box(gettext("The DHCP Server requires a static IPv4 subnet large enough to serve addresses to clients.") . " " . $sentence2);
825
	include("foot.inc");
826
	exit;
827
}
828

    
829
display_top_tabs($tab_array);
830

    
831
$form = new Form();
832

    
833
$section = new Form_Section('General Options');
834

    
835
if (!is_numeric($pool) && !($act == "newpool")) {
836
	if (isset($config['dhcrelay']['enable'])) {
837
		$section->addInput(new Form_Checkbox(
838
			'enable',
839
			'Enable',
840
			gettext("DHCP Relay is currently enabled. DHCP Server canot be enabled while the DHCP Relay is enabled on any interface."),
841
			$pconfig['enable']
842
		))->setAttribute('disabled', true);
843
	} else {
844
		$section->addInput(new Form_Checkbox(
845
			'enable',
846
			'Enable',
847
			sprintf(gettext("Enable DHCP server on %s interface"), htmlspecialchars($iflist[$if])),
848
			$pconfig['enable']
849
		));
850
	}
851
} else {
852
	print_info_box(gettext('Editing pool-specific options. To return to the Interface, click its tab above.'), 'info', false);
853
}
854

    
855
$section->addInput(new Form_Checkbox(
856
	'ignorebootp',
857
	'BOOTP',
858
	'Ignore BOOTP queries',
859
	$pconfig['ignorebootp']
860
));
861

    
862
$section->addInput(new Form_Checkbox(
863
	'denyunknown',
864
	'Deny unknown clients',
865
	'Only the clients defined below will get DHCP leases from this server.',
866
	$pconfig['denyunknown']
867
));
868

    
869
$section->addInput(new Form_Checkbox(
870
	'nonak',
871
	'Ignore denied clients',
872
	'Denied clients will be ignored rather than rejected.',
873
	$pconfig['nonak']
874
))->setHelp("This option is not compatible with failover and cannot be enabled when a Failover Peer IP address is configured.");
875

    
876
$section->addInput(new Form_Checkbox(
877
	'ignoreclientuids',
878
	'Ignore client identifiers',
879
	'If a client includes a unique identifier in its DHCP request, that UID will not be recorded in its lease.',
880
	$pconfig['ignoreclientuids']
881
))->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.");
882

    
883

    
884
if (is_numeric($pool) || ($act == "newpool")) {
885
	$section->addInput(new Form_Input(
886
		'descr',
887
		'Pool Description',
888
		'text',
889
		$pconfig['descr']
890
	));
891
}
892

    
893
$section->addInput(new Form_StaticText(
894
	'Subnet',
895
	gen_subnet($ifcfgip, $ifcfgsn)
896
));
897

    
898
$section->addInput(new Form_StaticText(
899
	'Subnet mask',
900
	gen_subnet_mask($ifcfgsn)
901
));
902

    
903
// Compose a string to display the required address ranges
904
$rangestr = ip_after($subnet_start) . ' - ' . ip_before($subnet_end);
905

    
906
if (is_numeric($pool) || ($act == "newpool")) {
907
	$rangestr .= '<br />' . gettext('In-use DHCP Pool Ranges:');
908
	if (is_array($config['dhcpd'][$if]['range'])) {
909
		$rangestr .= '<br />' . $config['dhcpd'][$if]['range']['from'] . ' - ' . $config['dhcpd'][$if]['range']['to'];
910
	}
911

    
912
	foreach ($a_pools as $p) {
913
		if (is_array($p['range'])) {
914
			$rangestr .= '<br />' . $p['range']['from'] . ' - ' . $p['range']['to'];
915
		}
916
	}
917
}
918

    
919
$section->addInput(new Form_StaticText(
920
	'Available range',
921
	$rangestr
922
));
923

    
924
if ($is_olsr_enabled) {
925
	$section->addInput(new Form_Select(
926
		'netmask',
927
		'Subnet mask',
928
		$pconfig['netmask'],
929
		array_combine(range(32, 1, -1), range(32, 1, -1))
930
	));
931
}
932

    
933
$group = new Form_Group('*Range');
934

    
935
$group->add(new Form_IpAddress(
936
	'range_from',
937
	null,
938
	$pconfig['range_from'],
939
	'V4'
940
))->setHelp('From');
941

    
942
$group->add(new Form_IpAddress(
943
	'range_to',
944
	null,
945
	$pconfig['range_to'],
946
	'V4'
947
))->setHelp('To');
948

    
949
$section->add($group);
950

    
951
$form->add($section);
952

    
953
if (!is_numeric($pool) && !($act == "newpool")) {
954
	$section = new Form_Section('Additional Pools');
955

    
956
	$btnaddpool = new Form_Button(
957
		'btnaddpool',
958
		'Add pool',
959
		'services_dhcp.php?if=' . htmlspecialchars($if) . '&act=newpool',
960
		'fa-plus'
961
	);
962
	$btnaddpool->addClass('btn-success');
963

    
964
	$section->addInput(new Form_StaticText(
965
		'Add',
966
		$btnaddpool
967
	))->setHelp('If additional pools of addresses are needed inside of this subnet outside the above Range, they may be specified here.');
968

    
969
	if (is_array($a_pools)) {
970
		$section->addInput(new Form_StaticText(
971
			null,
972
			build_pooltable()
973
		));
974
	}
975

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

    
979
$section = new Form_Section('Servers');
980

    
981
$section->addInput(new Form_IpAddress(
982
	'wins1',
983
	'WINS servers',
984
	$pconfig['wins1'],
985
	'V4'
986
))->setAttribute('placeholder', 'WINS Server 1');
987

    
988
$section->addInput(new Form_IpAddress(
989
	'wins2',
990
	null,
991
	$pconfig['wins2'],
992
	'V4'
993
))->setAttribute('placeholder', 'WINS Server 2');
994

    
995
for ($idx=1; $idx<=4; $idx++) {
996
	$section->addInput(new Form_IpAddress(
997
		'dns' . $idx,
998
		($idx == 1) ? 'DNS servers':null,
999
		$pconfig['dns' . $idx],
1000
		'V4'
1001
	))->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.':'');
1002
}
1003

    
1004
$form->add($section);
1005

    
1006
$section = new Form_Section('Other Options');
1007

    
1008
$section->addInput(new Form_IpAddress(
1009
	'gateway',
1010
	'Gateway',
1011
	$pconfig['gateway'],
1012
	'V4'
1013
))->setPattern('[.a-zA-Z0-9_]+')
1014
  ->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.');
1015

    
1016
$section->addInput(new Form_Input(
1017
	'domain',
1018
	'Domain name',
1019
	'text',
1020
	$pconfig['domain']
1021
))->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.');
1022

    
1023
$section->addInput(new Form_Input(
1024
	'domainsearchlist',
1025
	'Domain search list',
1026
	'text',
1027
	$pconfig['domainsearchlist']
1028
))->setHelp('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator.');
1029

    
1030
$section->addInput(new Form_Input(
1031
	'deftime',
1032
	'Default lease time',
1033
	'number',
1034
	$pconfig['deftime']
1035
))->setHelp('This is used for clients that do not ask for a specific expiration time. The default is 7200 seconds.');
1036

    
1037
$section->addInput(new Form_Input(
1038
	'maxtime',
1039
	'Maximum lease time',
1040
	'number',
1041
	$pconfig['maxtime']
1042
))->setHelp('This is the maximum lease time for clients that ask for a specific expiration time. The default is 86400 seconds.');
1043

    
1044
if (!is_numeric($pool) && !($act == "newpool")) {
1045
	$section->addInput(new Form_IpAddress(
1046
		'failover_peerip',
1047
		'Failover peer IP',
1048
		$pconfig['failover_peerip'],
1049
		'V4'
1050
	))->setHelp('Leave blank to disable. Enter the interface IP address of the other machine. Machines must be using CARP. ' .
1051
				'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).');
1052
}
1053

    
1054
if (!is_numeric($pool) && !($act == "newpool")) {
1055
	$section->addInput(new Form_Checkbox(
1056
		'staticarp',
1057
		'Static ARP',
1058
		'Enable Static ARP entries',
1059
		$pconfig['staticarp']
1060
	))->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.');
1061

    
1062
	$section->addInput(new Form_Checkbox(
1063
		'dhcpleaseinlocaltime',
1064
		'Time format change',
1065
		'Change DHCP display lease time from UTC to local time',
1066
		$pconfig['dhcpleaseinlocaltime']
1067
	))->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.' .
1068
				' This will be used for all DHCP interfaces lease time.');
1069
	$section->addInput(new Form_Checkbox(
1070
		'statsgraph',
1071
		'Statistics graphs',
1072
		'Enable RRD statistics graphs',
1073
		$pconfig['statsgraph']
1074
	))->setHelp('Enable this to add DHCP leases statistics to the RRD graphs. Disabled by default.');
1075
}
1076

    
1077
// DDNS
1078
$btnadv = new Form_Button(
1079
	'btnadvdns',
1080
	'Display Advanced',
1081
	null,
1082
	'fa-cog'
1083
);
1084

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

    
1087
$section->addInput(new Form_StaticText(
1088
	'Dynamic DNS',
1089
	$btnadv
1090
));
1091

    
1092
$section->addInput(new Form_Checkbox(
1093
	'ddnsupdate',
1094
	null,
1095
	'Enable registration of DHCP client names in DNS',
1096
	$pconfig['ddnsupdate']
1097
));
1098

    
1099
$section->addInput(new Form_Input(
1100
	'ddnsdomain',
1101
	'DDNS Domain',
1102
	'text',
1103
	$pconfig['ddnsdomain']
1104
))->setHelp('Enter the dynamic DNS domain which will be used to register client names in the DNS server.');
1105

    
1106
$section->addInput(new Form_Checkbox(
1107
	'ddnsforcehostname',
1108
	'DDNS Hostnames',
1109
	'Force dynamic DNS hostname to be the same as configured hostname for Static Mappings',
1110
	$pconfig['ddnsforcehostname']
1111
))->setHelp('Default registers host name option supplied by DHCP client.');
1112

    
1113
$section->addInput(new Form_IpAddress(
1114
	'ddnsdomainprimary',
1115
	'Primary DDNS address',
1116
	$pconfig['ddnsdomainprimary'],
1117
	'V4'
1118
))->setHelp('Primary domain name server IP address for the dynamic domain name.');
1119

    
1120
$section->addInput(new Form_Input(
1121
	'ddnsdomainkeyname',
1122
	'DNS Domain key',
1123
	'text',
1124
	$pconfig['ddnsdomainkeyname']
1125
))->setHelp('Dynamic DNS domain key name which will be used to register client names in the DNS server.');
1126

    
1127
$section->addInput(new Form_Select(
1128
	'ddnsdomainkeyalgorithm',
1129
	'Key algorithm',
1130
	$pconfig['ddnsdomainkeyalgorithm'],
1131
	array(
1132
		'hmac-md5' => 'HMAC-MD5 (legacy default)',
1133
		'hmac-sha1' => 'HMAC-SHA1',
1134
		'hmac-sha224' => 'HMAC-SHA224',
1135
		'hmac-sha256' => 'HMAC-SHA256 (current bind9 default)',
1136
		'hmac-sha384' => 'HMAC-SHA384',
1137
		'hmac-sha512' => 'HMAC-SHA512 (most secure)',
1138
	)
1139
));
1140

    
1141
$section->addInput(new Form_Input(
1142
	'ddnsdomainkey',
1143
	'DNS Domain key secret',
1144
	'text',
1145
	$pconfig['ddnsdomainkey']
1146
))->setHelp('Dynamic DNS domain key secret which will be used to register client names in the DNS server.');
1147

    
1148
// Advanced MAC
1149
$btnadv = new Form_Button(
1150
	'btnadvmac',
1151
	'Display Advanced',
1152
	null,
1153
	'fa-cog'
1154
);
1155

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

    
1158
$section->addInput(new Form_StaticText(
1159
	'MAC address control',
1160
	$btnadv
1161
));
1162

    
1163
$section->addInput(new Form_Input(
1164
	'mac_allow',
1165
	'MAC Allow',
1166
	'text',
1167
	$pconfig['mac_allow']
1168
))->setHelp('List of partial MAC addresses to allow, comma separated, no spaces, e.g.: 00:00:00,01:E5:FF');
1169

    
1170
$section->addInput(new Form_Input(
1171
	'mac_deny',
1172
	'MAC Deny',
1173
	'text',
1174
	$pconfig['mac_deny']
1175
))->setHelp('List of partial MAC addresses to deny access, comma separated, no spaces, e.g.: 00:00:00,01:E5:FF');
1176

    
1177
// Advanced NTP
1178
$btnadv = new Form_Button(
1179
	'btnadvntp',
1180
	'Display Advanced',
1181
	null,
1182
	'fa-cog'
1183
);
1184

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

    
1187
$section->addInput(new Form_StaticText(
1188
	'NTP',
1189
	$btnadv
1190
));
1191

    
1192
$section->addInput(new Form_IpAddress(
1193
	'ntp1',
1194
	'NTP Server 1',
1195
	$pconfig['ntp1'],
1196
	'HOSTV4'
1197
));
1198

    
1199
$section->addInput(new Form_IpAddress(
1200
	'ntp2',
1201
	'NTP Server 2',
1202
	$pconfig['ntp2'],
1203
	'HOSTV4'
1204
));
1205

    
1206
// Advanced TFTP
1207
$btnadv = new Form_Button(
1208
	'btnadvtftp',
1209
	'Display Advanced',
1210
	null,
1211
	'fa-cog'
1212
);
1213

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

    
1216
$section->addInput(new Form_StaticText(
1217
	'TFTP',
1218
	$btnadv
1219
));
1220

    
1221
$section->addInput(new Form_Input(
1222
	'tftp',
1223
	'TFTP Server',
1224
	'text',
1225
	$pconfig['tftp']
1226
))->setHelp('Leave blank to disable. Enter a valid IP address, hostname or URL for the TFTP server.');
1227

    
1228
// Advanced LDAP
1229
$btnadv = new Form_Button(
1230
	'btnadvldap',
1231
	'Display Advanced',
1232
	null,
1233
	'fa-cog'
1234
);
1235

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

    
1238
$section->addInput(new Form_StaticText(
1239
	'LDAP',
1240
	$btnadv
1241
));
1242

    
1243
$section->addInput(new Form_Input(
1244
	'ldap',
1245
	'LDAP Server URI',
1246
	'text',
1247
	$pconfig['ldap']
1248
))->setHelp('Leave blank to disable. Enter a full URI for the LDAP server in the form ldap://ldap.example.com/dc=example,dc=com ');
1249

    
1250
// Advanced Network Booting options
1251
$btnadv = new Form_Button(
1252
	'btnadvnwkboot',
1253
	'Display Advanced',
1254
	null,
1255
	'fa-cog'
1256
);
1257

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

    
1260
$section->addInput(new Form_StaticText(
1261
	'Network Booting',
1262
	$btnadv
1263
));
1264

    
1265
$section->addInput(new Form_Checkbox(
1266
	'netboot',
1267
	'Enable',
1268
	'Enables network booting',
1269
	$pconfig['netboot']
1270
));
1271

    
1272
$section->addInput(new Form_IpAddress(
1273
	'nextserver',
1274
	'Next Server',
1275
	$pconfig['nextserver'],
1276
	'V4'
1277
))->setHelp('Enter the IP address of the next server');
1278

    
1279
$section->addInput(new Form_Input(
1280
	'filename',
1281
	'Default BIOS file name',
1282
	'text',
1283
	$pconfig['filename']
1284
));
1285

    
1286
$section->addInput(new Form_Input(
1287
	'filename32',
1288
	'UEFI 32 bit file name',
1289
	'text',
1290
	$pconfig['filename32']
1291
));
1292

    
1293
$section->addInput(new Form_Input(
1294
	'filename64',
1295
	'UEFI 64 bit file name',
1296
	'text',
1297
	$pconfig['filename64']
1298
))->setHelp('Both a filename and a boot server must be configured for this to work! ' .
1299
			'All three filenames and a configured boot server are necessary for UEFI to work! ');
1300

    
1301
$section->addInput(new Form_Input(
1302
	'rootpath',
1303
	'Root path',
1304
	'text',
1305
	$pconfig['rootpath']
1306
))->setHelp('string-format: iscsi:(servername):(protocol):(port):(LUN):targetname ');
1307

    
1308
// Advanced Additional options
1309
$btnadv = new Form_Button(
1310
	'btnadvopts',
1311
	'Display Advanced',
1312
	null,
1313
	'fa-cog'
1314
);
1315

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

    
1318
$section->addInput(new Form_StaticText(
1319
	'Additional BOOTP/DHCP Options',
1320
	$btnadv
1321
));
1322

    
1323
$form->add($section);
1324

    
1325
$section = new Form_Section('Additional BOOTP/DHCP Options');
1326
$section->addClass('adnlopts');
1327

    
1328
$section->addInput(new Form_StaticText(
1329
	null,
1330
	'<div class="alert alert-info"> ' . gettext('Enter the DHCP option number and the value for each item to include in the DHCP lease information.') . ' ' .
1331
	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>')
1332
));
1333

    
1334
if (!$pconfig['numberoptions']) {
1335
	$pconfig['numberoptions']['item']  = array(array('number' => '', 'type' => 'text', 'value' => ''));
1336
}
1337

    
1338
$customitemtypes = array(
1339
	'text' => gettext('Text'), 'string' => gettext('String'), 'boolean' => gettext('Boolean'),
1340
	'unsigned integer 8' => gettext('Unsigned 8-bit integer'), 'unsigned integer 16' => gettext('Unsigned 16-bit integer'), 'unsigned integer 32' => gettext('Unsigned 32-bit integer'),
1341
	'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')
1342
);
1343

    
1344
$numrows = count($item) -1;
1345
$counter = 0;
1346

    
1347
$numrows = count($pconfig['numberoptions']['item']) -1;
1348

    
1349
foreach ($pconfig['numberoptions']['item'] as $item) {
1350
	$number = $item['number'];
1351
	$itemtype = $item['type'];
1352
	$value = base64_decode($item['value']);
1353

    
1354
	$group = new Form_Group(($counter == 0) ? 'Option':null);
1355
	$group->addClass('repeatable');
1356

    
1357
	$group->add(new Form_Input(
1358
		'number' . $counter,
1359
		null,
1360
		'text',
1361
		$number
1362
	))->setHelp($numrows == $counter ? 'Number':null);
1363

    
1364

    
1365
	$group->add(new Form_Select(
1366
		'itemtype' . $counter,
1367
		null,
1368
		$itemtype,
1369
		$customitemtypes
1370
	))->setWidth(3)->setHelp($numrows == $counter ? 'Type':null);
1371

    
1372
	$group->add(new Form_Input(
1373
		'value' . $counter,
1374
		null,
1375
		'text',
1376
		$value
1377
	))->setHelp($numrows == $counter ? 'Value':null);
1378

    
1379
	$group->add(new Form_Button(
1380
		'deleterow' . $counter,
1381
		'Delete',
1382
		null,
1383
		'fa-trash'
1384
	))->addClass('btn-warning');
1385

    
1386
	$section->add($group);
1387

    
1388
	$counter++;
1389
}
1390

    
1391
$section->addInput(new Form_Button(
1392
	'addrow',
1393
	'Add',
1394
	null,
1395
	'fa-plus'
1396
))->addClass('btn-success');
1397

    
1398
$form->add($section);
1399

    
1400
if ($act == "newpool") {
1401
	$form->addGlobal(new Form_Input(
1402
		'act',
1403
		null,
1404
		'hidden',
1405
		'newpool'
1406
	));
1407
}
1408

    
1409
if (is_numeric($pool)) {
1410
	$form->addGlobal(new Form_Input(
1411
		'pool',
1412
		null,
1413
		'hidden',
1414
		$pool
1415
	));
1416
}
1417

    
1418
$form->addGlobal(new Form_Input(
1419
	'if',
1420
	null,
1421
	'hidden',
1422
	$if
1423
));
1424

    
1425
print($form);
1426

    
1427
// DHCP Static Mappings table
1428

    
1429
if (!is_numeric($pool) && !($act == "newpool")) {
1430

    
1431
	// Decide whether display of the Client Id column is needed.
1432
	$got_cid = false;
1433
	if (is_array($a_maps)) {
1434
		foreach ($a_maps as $map) {
1435
			if (!empty($map['cid'])) {
1436
				$got_cid = true;
1437
				break;
1438
			}
1439
		}
1440
	}
1441
?>
1442

    
1443
<div class="panel panel-default">
1444
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("DHCP Static Mappings for this Interface")?></h2></div>
1445
	<div class="table-responsive">
1446
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
1447
				<thead>
1448
					<tr>
1449
						<th><?=gettext("Static ARP")?></th>
1450
						<th><?=gettext("MAC address")?></th>
1451
<?php
1452
	if ($got_cid):
1453
?>
1454
						<th><?=gettext("Client Id")?></th>
1455
<?php
1456
	endif;
1457
?>
1458
						<th><?=gettext("IP address")?></th>
1459
						<th><?=gettext("Hostname")?></th>
1460
						<th><?=gettext("Description")?></th>
1461
						<th></th>
1462
					</tr>
1463
				</thead>
1464
<?php
1465
	if (is_array($a_maps)) {
1466
		$i = 0;
1467
?>
1468
				<tbody>
1469
<?php
1470
		foreach ($a_maps as $mapent) {
1471
?>
1472
					<tr>
1473
						<td class="text-center" ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1474
							<?php if (isset($mapent['arp_table_static_entry'])): ?>
1475
								<i class="fa fa-check"></i>
1476
							<?php endif; ?>
1477
						</td>
1478
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1479
							<?=htmlspecialchars($mapent['mac'])?>
1480
						</td>
1481
<?php
1482
			if ($got_cid):
1483
?>
1484
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1485
							<?=htmlspecialchars($mapent['cid'])?>
1486
						</td>
1487
<?php
1488
			endif;
1489
?>
1490
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1491
							<?=htmlspecialchars($mapent['ipaddr'])?>
1492
						</td>
1493
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1494
							<?=htmlspecialchars($mapent['hostname'])?>
1495
						</td>
1496
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1497
							<?=htmlspecialchars($mapent['descr'])?>
1498
						</td>
1499
						<td>
1500
							<a class="fa fa-pencil"	title="<?=gettext('Edit static mapping')?>"	href="services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>"></a>
1501
							<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>
1502
						</td>
1503
					</tr>
1504
<?php
1505
		$i++;
1506
		}
1507
?>
1508
				</tbody>
1509
<?php
1510
	}
1511
?>
1512
		</table>
1513
	</div>
1514
</div>
1515

    
1516
<nav class="action-buttons">
1517
	<a href="services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>" class="btn btn-sm btn-success">
1518
		<i class="fa fa-plus icon-embed-btn"></i>
1519
		<?=gettext("Add")?>
1520
	</a>
1521
</nav>
1522
<?php
1523
}
1524
?>
1525

    
1526
<script type="text/javascript">
1527
//<![CDATA[
1528
events.push(function() {
1529

    
1530
	// Show advanced DNS options ======================================================================================
1531
	var showadvdns = false;
1532

    
1533
	function show_advdns(ispageload) {
1534
		var text;
1535
		// On page load decide the initial state based on the data.
1536
		if (ispageload) {
1537
<?php
1538
			if (!$pconfig['ddnsupdate'] && !$pconfig['ddnsforcehostname'] && empty($pconfig['ddnsdomain']) && empty($pconfig['ddnsdomainprimary']) &&
1539
			    empty($pconfig['ddnsdomainkeyname']) && empty($pconfig['ddnsdomainkeyalgorithm']) && empty($pconfig['ddnsdomainkey'])) {
1540
				$showadv = false;
1541
			} else {
1542
				$showadv = true;
1543
			}
1544
?>
1545
			showadvdns = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1546
		} else {
1547
			// It was a click, swap the state.
1548
			showadvdns = !showadvdns;
1549
		}
1550

    
1551
		hideCheckbox('ddnsupdate', !showadvdns);
1552
		hideInput('ddnsdomain', !showadvdns);
1553
		hideCheckbox('ddnsforcehostname', !showadvdns);
1554
		hideInput('ddnsdomainprimary', !showadvdns);
1555
		hideInput('ddnsdomainkeyname', !showadvdns);
1556
		hideInput('ddnsdomainkeyalgorithm', !showadvdns);
1557
		hideInput('ddnsdomainkey', !showadvdns);
1558

    
1559
		if (showadvdns) {
1560
			text = "<?=gettext('Hide Advanced');?>";
1561
		} else {
1562
			text = "<?=gettext('Display Advanced');?>";
1563
		}
1564
		$('#btnadvdns').html('<i class="fa fa-cog"></i> ' + text);
1565
	}
1566

    
1567
	$('#btnadvdns').click(function(event) {
1568
		show_advdns();
1569
	});
1570

    
1571
	// Show advanced MAC options ======================================================================================
1572
	var showadvmac = false;
1573

    
1574
	function show_advmac(ispageload) {
1575
		var text;
1576
		// On page load decide the initial state based on the data.
1577
		if (ispageload) {
1578
<?php
1579
			if (empty($pconfig['mac_allow']) && empty($pconfig['mac_deny'])) {
1580
				$showadv = false;
1581
			} else {
1582
				$showadv = true;
1583
			}
1584
?>
1585
			showadvmac = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1586
		} else {
1587
			// It was a click, swap the state.
1588
			showadvmac = !showadvmac;
1589
		}
1590

    
1591
		hideInput('mac_allow', !showadvmac);
1592
		hideInput('mac_deny', !showadvmac);
1593

    
1594
		if (showadvmac) {
1595
			text = "<?=gettext('Hide Advanced');?>";
1596
		} else {
1597
			text = "<?=gettext('Display Advanced');?>";
1598
		}
1599
		$('#btnadvmac').html('<i class="fa fa-cog"></i> ' + text);
1600
	}
1601

    
1602
	$('#btnadvmac').click(function(event) {
1603
		show_advmac();
1604
	});
1605

    
1606
	// Show advanced NTP options ======================================================================================
1607
	var showadvntp = false;
1608

    
1609
	function show_advntp(ispageload) {
1610
		var text;
1611
		// On page load decide the initial state based on the data.
1612
		if (ispageload) {
1613
<?php
1614
			if (empty($pconfig['ntp1']) && empty($pconfig['ntp2'])) {
1615
				$showadv = false;
1616
			} else {
1617
				$showadv = true;
1618
			}
1619
?>
1620
			showadvntp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1621
		} else {
1622
			// It was a click, swap the state.
1623
			showadvntp = !showadvntp;
1624
		}
1625

    
1626
		hideInput('ntp1', !showadvntp);
1627
		hideInput('ntp2', !showadvntp);
1628

    
1629
		if (showadvntp) {
1630
			text = "<?=gettext('Hide Advanced');?>";
1631
		} else {
1632
			text = "<?=gettext('Display Advanced');?>";
1633
		}
1634
		$('#btnadvntp').html('<i class="fa fa-cog"></i> ' + text);
1635
	}
1636

    
1637
	$('#btnadvntp').click(function(event) {
1638
		show_advntp();
1639
	});
1640

    
1641
	// Show advanced TFTP options ======================================================================================
1642
	var showadvtftp = false;
1643

    
1644
	function show_advtftp(ispageload) {
1645
		var text;
1646
		// On page load decide the initial state based on the data.
1647
		if (ispageload) {
1648
<?php
1649
			if (empty($pconfig['tftp'])) {
1650
				$showadv = false;
1651
			} else {
1652
				$showadv = true;
1653
			}
1654
?>
1655
			showadvtftp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1656
		} else {
1657
			// It was a click, swap the state.
1658
			showadvtftp = !showadvtftp;
1659
		}
1660

    
1661
		hideInput('tftp', !showadvtftp);
1662

    
1663
		if (showadvtftp) {
1664
			text = "<?=gettext('Hide Advanced');?>";
1665
		} else {
1666
			text = "<?=gettext('Display Advanced');?>";
1667
		}
1668
		$('#btnadvtftp').html('<i class="fa fa-cog"></i> ' + text);
1669
	}
1670

    
1671
	$('#btnadvtftp').click(function(event) {
1672
		show_advtftp();
1673
	});
1674

    
1675
	// Show advanced LDAP options ======================================================================================
1676
	var showadvldap = false;
1677

    
1678
	function show_advldap(ispageload) {
1679
		var text;
1680
		// On page load decide the initial state based on the data.
1681
		if (ispageload) {
1682
<?php
1683
			if (empty($pconfig['ldap'])) {
1684
				$showadv = false;
1685
			} else {
1686
				$showadv = true;
1687
			}
1688
?>
1689
			showadvldap = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1690
		} else {
1691
			// It was a click, swap the state.
1692
			showadvldap = !showadvldap;
1693
		}
1694

    
1695
		hideInput('ldap', !showadvldap);
1696

    
1697
		if (showadvldap) {
1698
			text = "<?=gettext('Hide Advanced');?>";
1699
		} else {
1700
			text = "<?=gettext('Display Advanced');?>";
1701
		}
1702
		$('#btnadvldap').html('<i class="fa fa-cog"></i> ' + text);
1703
	}
1704

    
1705
	$('#btnadvldap').click(function(event) {
1706
		show_advldap();
1707
	});
1708

    
1709
	// Show advanced additional opts options ===========================================================================
1710
	var showadvopts = false;
1711

    
1712
	function show_advopts(ispageload) {
1713
		var text;
1714
		// On page load decide the initial state based on the data.
1715
		if (ispageload) {
1716
<?php
1717
			if (empty($pconfig['numberoptions']) ||
1718
			    (empty($pconfig['numberoptions']['item'][0]['number']) && (empty($pconfig['numberoptions']['item'][0]['value'])))) {
1719
				$showadv = false;
1720
			} else {
1721
				$showadv = true;
1722
			}
1723
?>
1724
			showadvopts = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1725
		} else {
1726
			// It was a click, swap the state.
1727
			showadvopts = !showadvopts;
1728
		}
1729

    
1730
		hideClass('adnlopts', !showadvopts);
1731

    
1732
		if (showadvopts) {
1733
			text = "<?=gettext('Hide Advanced');?>";
1734
		} else {
1735
			text = "<?=gettext('Display Advanced');?>";
1736
		}
1737
		$('#btnadvopts').html('<i class="fa fa-cog"></i> ' + text);
1738
	}
1739

    
1740
	$('#btnadvopts').click(function(event) {
1741
		show_advopts();
1742
	});
1743

    
1744
	// Show advanced Network Booting options ===========================================================================
1745
	var showadvnwkboot = false;
1746

    
1747
	function show_advnwkboot(ispageload) {
1748
		var text;
1749
		// On page load decide the initial state based on the data.
1750
		if (ispageload) {
1751
<?php
1752
			if (empty($pconfig['netboot'])) {
1753
				$showadv = false;
1754
			} else {
1755
				$showadv = true;
1756
			}
1757
?>
1758
			showadvnwkboot = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1759
		} else {
1760
			// It was a click, swap the state.
1761
			showadvnwkboot = !showadvnwkboot;
1762
		}
1763

    
1764
		hideCheckbox('netboot', !showadvnwkboot);
1765
		hideInput('nextserver', !showadvnwkboot);
1766
		hideInput('filename', !showadvnwkboot);
1767
		hideInput('filename32', !showadvnwkboot);
1768
		hideInput('filename64', !showadvnwkboot);
1769
		hideInput('rootpath', !showadvnwkboot);
1770

    
1771
		if (showadvnwkboot) {
1772
			text = "<?=gettext('Hide Advanced');?>";
1773
		} else {
1774
			text = "<?=gettext('Display Advanced');?>";
1775
		}
1776
		$('#btnadvnwkboot').html('<i class="fa fa-cog"></i> ' + text);
1777
	}
1778

    
1779
	$('#btnadvnwkboot').click(function(event) {
1780
		show_advnwkboot();
1781
	});
1782

    
1783
	// ---------- On initial page load ------------------------------------------------------------
1784

    
1785
	show_advdns(true);
1786
	show_advmac(true);
1787
	show_advntp(true);
1788
	show_advtftp(true);
1789
	show_advldap(true);
1790
	show_advopts(true);
1791
	show_advnwkboot(true);
1792

    
1793
	// Suppress "Delete row" button if there are fewer than two rows
1794
	checkLastRow();
1795
});
1796
//]]>
1797
</script>
1798

    
1799
<?php include("foot.inc");
(123-123/232)