Project

General

Profile

Download (52.4 KB) Statistics
| Branch: | Tag: | Revision:
1 e9f147c8 Scott Ullrich
<?php
2 5b237745 Scott Ullrich
/*
3 c5d81585 Renato Botelho
 * services_dhcp.php
4 919d91f9 Phil Davis
 *
5 c5d81585 Renato Botelho
 * part of pfSense (https://www.pfsense.org)
6 81299b5c Renato Botelho
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
7 c5d81585 Renato Botelho
 * All rights reserved.
8 b5f6e690 Stephen Beaver
 *
9 c5d81585 Renato Botelho
 * originally based on m0n0wall (http://m0n0.ch/wall)
10
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
11
 * All rights reserved.
12 b5f6e690 Stephen Beaver
 *
13 b12ea3fb Renato Botelho
 * 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 b5f6e690 Stephen Beaver
 *
17 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
18 b5f6e690 Stephen Beaver
 *
19 b12ea3fb Renato Botelho
 * 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 b5f6e690 Stephen Beaver
 */
25 5b237745 Scott Ullrich
26 6b07c15a Matthew Grooms
##|+PRIV
27
##|*IDENT=page-services-dhcpserver
28 9599211d jim-p
##|*NAME=Services: DHCP Server
29
##|*DESCR=Allow access to the 'Services: DHCP Server' page.
30 6b07c15a Matthew Grooms
##|*MATCH=services_dhcp.php*
31
##|-PRIV
32
33 c81ef6e2 Phil Davis
require_once("guiconfig.inc");
34 6c124212 Phil Davis
require_once("filter.inc");
35 6303601e heper
require_once('rrd.inc');
36
require_once("shaper.inc");
37 5b237745 Scott Ullrich
38 8f8682f7 Phil Davis
if (!$g['services_dhcp_server_enable']) {
39 6f3d2063 Renato Botelho
	header("Location: /");
40 2ee0410f Scott Ullrich
	exit;
41
}
42
43 5b237745 Scott Ullrich
$if = $_GET['if'];
44 8f8682f7 Phil Davis
if (!empty($_POST['if'])) {
45 5b237745 Scott Ullrich
	$if = $_POST['if'];
46 8f8682f7 Phil Davis
}
47 e9f147c8 Scott Ullrich
48 11bc553c Scott Ullrich
/* if OLSRD is enabled, allow WAN to house DHCP. */
49 8f8682f7 Phil Davis
if ($config['installedpackages']['olsrd']) {
50
	foreach ($config['installedpackages']['olsrd']['config'] as $olsrd) {
51
		if ($olsrd['enable']) {
52
			$is_olsr_enabled = true;
53
			break;
54
		}
55 a3b466b5 Scott Ullrich
	}
56 8f8682f7 Phil Davis
}
57 5b237745 Scott Ullrich
58 934240ef Ermal Luçi
$iflist = get_configured_interface_with_descr();
59 5b237745 Scott Ullrich
60 1c451b06 Scott Ullrich
/* set the starting interface */
61 f19651d1 Ermal
if (!$if || !isset($iflist[$if])) {
62 cde97f1c Phil Davis
	$found_starting_if = false;
63
	// First look for an interface with DHCP already enabled.
64 01fdb2d3 Erik Fonnesbeck
	foreach ($iflist as $ifent => $ifname) {
65 de792e62 jim-p
		$oc = $config['interfaces'][$ifent];
66 403dad2a Renato Botelho
		if (is_array($config['dhcpd'][$ifent]) &&
67
		    isset($config['dhcpd'][$ifent]['enable']) &&
68
		    is_ipaddrv4($oc['ipaddr']) && $oc['subnet'] < 31) {
69 cde97f1c Phil Davis
			$if = $ifent;
70
			$found_starting_if = true;
71
			break;
72 8f8682f7 Phil Davis
		}
73 cde97f1c Phil Davis
	}
74
75 403dad2a Renato Botelho
	/*
76
	 * If there is no DHCP-enabled interface and LAN is a candidate,
77
	 * then choose LAN.
78
	 */
79
	if (!$found_starting_if && isset($iflist['lan']) &&
80
	    is_ipaddrv4($config['interfaces']['lan']['ipaddr']) &&
81
	    $config['interfaces']['lan']['subnet'] < 31) {
82 cde97f1c Phil Davis
		$if = 'lan';
83
		$found_starting_if = true;
84
	}
85 b5f6e690 Stephen Beaver
86 cde97f1c Phil Davis
	// At the last select whatever can be found.
87
	if (!$found_starting_if) {
88
		foreach ($iflist as $ifent => $ifname) {
89
			$oc = $config['interfaces'][$ifent];
90 403dad2a Renato Botelho
91
			/* Not static IPv4 or subnet >= 31 */
92
			if (!is_ipaddrv4($oc['ipaddr']) ||
93
			    empty($oc['subnet']) || $oc['subnet'] < 31) {
94
				continue;
95
			}
96
97
			if (!is_array($config['dhcpd'][$ifent]) ||
98
			    !isset($config['dhcpd'][$ifent]['enable'])) {
99 cde97f1c Phil Davis
				continue;
100
			}
101
102
			$if = $ifent;
103
			break;
104
		}
105 01fdb2d3 Erik Fonnesbeck
	}
106 f19651d1 Ermal
}
107 0a2c6a5b Scott Ullrich
108 cba980f6 jim-p
$act = $_GET['act'];
109 8f8682f7 Phil Davis
if (!empty($_POST['act'])) {
110 cba980f6 jim-p
	$act = $_POST['act'];
111 8f8682f7 Phil Davis
}
112 cba980f6 jim-p
113 cc6052f0 Renato Botelho
$a_pools = array();
114 cba980f6 jim-p
115 8f8682f7 Phil Davis
if (is_array($config['dhcpd'][$if])) {
116 cba980f6 jim-p
	$pool = $_GET['pool'];
117 8f8682f7 Phil Davis
	if (is_numeric($_POST['pool'])) {
118 cba980f6 jim-p
		$pool = $_POST['pool'];
119 8f8682f7 Phil Davis
	}
120 cba980f6 jim-p
121
	// If we have a pool but no interface name, that's not valid. Redirect away.
122
	if (is_numeric($pool) && empty($if)) {
123
		header("Location: services_dhcp.php");
124
		exit;
125 de792e62 jim-p
	}
126 cba980f6 jim-p
127 8f8682f7 Phil Davis
	if (!is_array($config['dhcpd'][$if]['pool'])) {
128 cba980f6 jim-p
		$config['dhcpd'][$if]['pool'] = array();
129 8f8682f7 Phil Davis
	}
130 b5f6e690 Stephen Beaver
131 cba980f6 jim-p
	$a_pools = &$config['dhcpd'][$if]['pool'];
132
133 8f8682f7 Phil Davis
	if (is_numeric($pool) && $a_pools[$pool]) {
134 cba980f6 jim-p
		$dhcpdconf = &$a_pools[$pool];
135 8f8682f7 Phil Davis
	} elseif ($act == "newpool") {
136 cba980f6 jim-p
		$dhcpdconf = array();
137 8f8682f7 Phil Davis
	} else {
138 cba980f6 jim-p
		$dhcpdconf = &$config['dhcpd'][$if];
139 8f8682f7 Phil Davis
	}
140 e7940d2e Phil Davis
141
	if (!is_array($config['dhcpd'][$if]['staticmap'])) {
142
		$dhcpdconf['staticmap'] = array();
143
	}
144
145
	$a_maps = &$config['dhcpd'][$if]['staticmap'];
146 cba980f6 jim-p
}
147
if (is_array($dhcpdconf)) {
148
	// Global Options
149
	if (!is_numeric($pool) && !($act == "newpool")) {
150
		$pconfig['enable'] = isset($dhcpdconf['enable']);
151
		$pconfig['staticarp'] = isset($dhcpdconf['staticarp']);
152
		// No reason to specify this per-pool, per the dhcpd.conf man page it needs to be in every
153 b5f6e690 Stephen Beaver
		//	 pool and should be specified in every pool both nodes share, so we'll treat it as global
154 cba980f6 jim-p
		$pconfig['failover_peerip'] = $dhcpdconf['failover_peerip'];
155 466aae83 Phil Davis
156
		// dhcpleaseinlocaltime is global to all interfaces. So if it is selected on any interface,
157
		// then show it true/checked.
158
		foreach ($config['dhcpd'] as $dhcpdifitem) {
159
			$dhcpleaseinlocaltime = $dhcpdifitem['dhcpleaseinlocaltime'];
160 8f8682f7 Phil Davis
			if ($dhcpleaseinlocaltime) {
161 466aae83 Phil Davis
				break;
162 8f8682f7 Phil Davis
			}
163 466aae83 Phil Davis
		}
164
165
		$pconfig['dhcpleaseinlocaltime'] = $dhcpleaseinlocaltime;
166 ee1fb205 jim-p
	} else {
167
		// Options that exist only in pools
168
		$pconfig['descr'] = $dhcpdconf['descr'];
169 cba980f6 jim-p
	}
170
171
	// Options that can be global or per-pool.
172
	if (is_array($dhcpdconf['range'])) {
173
		$pconfig['range_from'] = $dhcpdconf['range']['from'];
174
		$pconfig['range_to'] = $dhcpdconf['range']['to'];
175
	}
176 b5f6e690 Stephen Beaver
177 cba980f6 jim-p
	$pconfig['deftime'] = $dhcpdconf['defaultleasetime'];
178
	$pconfig['maxtime'] = $dhcpdconf['maxleasetime'];
179
	$pconfig['gateway'] = $dhcpdconf['gateway'];
180
	$pconfig['domain'] = $dhcpdconf['domain'];
181
	$pconfig['domainsearchlist'] = $dhcpdconf['domainsearchlist'];
182 8f8682f7 Phil Davis
	list($pconfig['wins1'], $pconfig['wins2']) = $dhcpdconf['winsserver'];
183
	list($pconfig['dns1'], $pconfig['dns2'], $pconfig['dns3'], $pconfig['dns4']) = $dhcpdconf['dnsserver'];
184 6d53301b Jose Luis Duran
	$pconfig['ignorebootp'] = isset($dhcpdconf['ignorebootp']);
185 cba980f6 jim-p
	$pconfig['denyunknown'] = isset($dhcpdconf['denyunknown']);
186 11ee0c6d Brett Keller
	$pconfig['ignoreclientuids'] = isset($dhcpdconf['ignoreclientuids']);
187 3475eb04 Andrew Pilloud
	$pconfig['nonak'] = isset($dhcpdconf['nonak']);
188 cba980f6 jim-p
	$pconfig['ddnsdomain'] = $dhcpdconf['ddnsdomain'];
189 87019fc4 Andres Petralli
	$pconfig['ddnsdomainprimary'] = $dhcpdconf['ddnsdomainprimary'];
190
	$pconfig['ddnsdomainkeyname'] = $dhcpdconf['ddnsdomainkeyname'];
191
	$pconfig['ddnsdomainkey'] = $dhcpdconf['ddnsdomainkey'];
192 cba980f6 jim-p
	$pconfig['ddnsupdate'] = isset($dhcpdconf['ddnsupdate']);
193 cf15bcb4 Ross Williams
	$pconfig['ddnsforcehostname'] = isset($dhcpdconf['ddnsforcehostname']);
194 cba980f6 jim-p
	$pconfig['mac_allow'] = $dhcpdconf['mac_allow'];
195
	$pconfig['mac_deny'] = $dhcpdconf['mac_deny'];
196 8f8682f7 Phil Davis
	list($pconfig['ntp1'], $pconfig['ntp2']) = $dhcpdconf['ntpserver'];
197 cba980f6 jim-p
	$pconfig['tftp'] = $dhcpdconf['tftp'];
198
	$pconfig['ldap'] = $dhcpdconf['ldap'];
199
	$pconfig['netboot'] = isset($dhcpdconf['netboot']);
200
	$pconfig['nextserver'] = $dhcpdconf['nextserver'];
201
	$pconfig['filename'] = $dhcpdconf['filename'];
202 7023c602 Charlie Root
	$pconfig['filename32'] = $dhcpdconf['filename32'];
203
	$pconfig['filename64'] = $dhcpdconf['filename64'];
204 cba980f6 jim-p
	$pconfig['rootpath'] = $dhcpdconf['rootpath'];
205
	$pconfig['netmask'] = $dhcpdconf['netmask'];
206
	$pconfig['numberoptions'] = $dhcpdconf['numberoptions'];
207 18d316a5 heper
	$pconfig['statsgraph'] = $dhcpdconf['statsgraph'];
208 89019922 Ermal Luçi
}
209 31c59d0d Scott Ullrich
210 51cd7a1e Evgeny Yurchenko
$ifcfgip = $config['interfaces'][$if]['ipaddr'];
211
$ifcfgsn = $config['interfaces'][$if]['subnet'];
212 5b237745 Scott Ullrich
213 b90d635e Renato Botelho
$subnet_start = gen_subnetv4($ifcfgip, $ifcfgsn);
214
$subnet_end = gen_subnetv4_max($ifcfgip, $ifcfgsn);
215
216 1f1a08c8 jim-p
function validate_partial_mac_list($maclist) {
217
	$macs = explode(',', $maclist);
218
219
	// Loop through and look for invalid MACs.
220 8f8682f7 Phil Davis
	foreach ($macs as $mac) {
221
		if (!is_macaddr($mac, true)) {
222 1f1a08c8 jim-p
			return false;
223 8f8682f7 Phil Davis
		}
224
	}
225 b5f6e690 Stephen Beaver
226 1f1a08c8 jim-p
	return true;
227
}
228
229 141d8913 jim-p
if (isset($_POST['save'])) {
230 5b237745 Scott Ullrich
231
	unset($input_errors);
232 b7597d4e Bill Marquette
233 5b237745 Scott Ullrich
	$pconfig = $_POST;
234
235 6d1af0e9 jim-p
	$numberoptions = array();
236 6c07db48 Phil Davis
	for ($x = 0; $x < 99; $x++) {
237 8f8682f7 Phil Davis
		if (isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) {
238 6d1af0e9 jim-p
			$numbervalue = array();
239
			$numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]);
240 678dfd0f Erik Fonnesbeck
			$numbervalue['type'] = htmlspecialchars($_POST["itemtype{$x}"]);
241 65cce9d7 Renato Botelho
			$numbervalue['value'] = base64_encode($_POST["value{$x}"]);
242 6d1af0e9 jim-p
			$numberoptions['item'][] = $numbervalue;
243
		}
244
	}
245 b5f6e690 Stephen Beaver
246 466aae83 Phil Davis
	// Reload the new pconfig variable that the form uses.
247 6d1af0e9 jim-p
	$pconfig['numberoptions'] = $numberoptions;
248
249 5b237745 Scott Ullrich
	/* input validation */
250 48614394 Phil Davis
251
	// Note: if DHCP Server is not enabled, then it is OK to adjust other parameters without specifying range from-to.
252 cba980f6 jim-p
	if ($_POST['enable'] || is_numeric($pool) || $act == "newpool") {
253 5b237745 Scott Ullrich
		$reqdfields = explode(" ", "range_from range_to");
254 8f8682f7 Phil Davis
		$reqdfieldsn = array(gettext("Range begin"), gettext("Range end"));
255 e9f147c8 Scott Ullrich
256 507628d5 Renato Botelho
		do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
257 48614394 Phil Davis
	}
258 de792e62 jim-p
259 48614394 Phil Davis
	if (($_POST['nonak']) && !empty($_POST['failover_peerip'])) {
260
		$input_errors[] = gettext("Ignore Denied Clients may not be used when a Failover Peer IP is defined.");
261
	}
262 8209517d jim-p
263 48614394 Phil Davis
	if ($_POST['range_from'] && !is_ipaddrv4($_POST['range_from'])) {
264
		$input_errors[] = gettext("A valid IPv4 address must be specified for range from.");
265
	}
266
	if ($_POST['range_to'] && !is_ipaddrv4($_POST['range_to'])) {
267
		$input_errors[] = gettext("A valid IPv4 address must be specified for range to.");
268
	}
269
	if (($_POST['range_from'] && !$_POST['range_to']) || ($_POST['range_to'] && !$_POST['range_from'])) {
270
		$input_errors[] = gettext("Range From and Range To must both be entered.");
271
	}
272
	if (($_POST['gateway'] && $_POST['gateway'] != "none" && !is_ipaddrv4($_POST['gateway']))) {
273
		$input_errors[] = gettext("A valid IP address must be specified for the gateway.");
274
	}
275
	if (($_POST['wins1'] && !is_ipaddrv4($_POST['wins1'])) || ($_POST['wins2'] && !is_ipaddrv4($_POST['wins2']))) {
276
		$input_errors[] = gettext("A valid IP address must be specified for the primary/secondary WINS servers.");
277
	}
278
	$parent_ip = get_interface_ip($_POST['if']);
279
	if (is_ipaddrv4($parent_ip) && $_POST['gateway'] && $_POST['gateway'] != "none") {
280
		$parent_sn = get_interface_subnet($_POST['if']);
281
		if (!ip_in_subnet($_POST['gateway'], gen_subnet($parent_ip, $parent_sn) . "/" . $parent_sn) && !ip_in_interface_alias_subnet($_POST['if'], $_POST['gateway'])) {
282
			$input_errors[] = sprintf(gettext("The gateway address %s does not lie within the chosen interface's subnet."), $_POST['gateway']);
283 45d1024d Scott Ullrich
		}
284 48614394 Phil Davis
	}
285 b5f6e690 Stephen Beaver
286 48614394 Phil Davis
	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']))) {
287
		$input_errors[] = gettext("A valid IP address must be specified for each of the DNS servers.");
288
	}
289
290
	if ($_POST['deftime'] && (!is_numeric($_POST['deftime']) || ($_POST['deftime'] < 60))) {
291
		$input_errors[] = gettext("The default lease time must be at least 60 seconds.");
292
	}
293 26e3ca70 sullrich
294 48614394 Phil Davis
	if (isset($config['captiveportal']) && is_array($config['captiveportal'])) {
295
		$deftime = 7200; // Default value if it's empty
296
		if (is_numeric($_POST['deftime'])) {
297
			$deftime = $_POST['deftime'];
298 8f8682f7 Phil Davis
		}
299 e680b2f9 Renato Botelho
300 48614394 Phil Davis
		foreach ($config['captiveportal'] as $cpZone => $cpdata) {
301
			if (!isset($cpdata['enable'])) {
302
				continue;
303 8f8682f7 Phil Davis
			}
304 48614394 Phil Davis
			if (!isset($cpdata['timeout']) || !is_numeric($cpdata['timeout'])) {
305
				continue;
306
			}
307
			$cp_ifs = explode(',', $cpdata['interface']);
308
			if (!in_array($if, $cp_ifs)) {
309
				continue;
310
			}
311
			if ($cpdata['timeout'] > $deftime) {
312
				$input_errors[] = sprintf(gettext(
313
					'The Captive Portal zone (%1$s) has Hard Timeout parameter set to a value bigger than Default lease time (%2$s).'), $cpZone, $deftime);
314 e680b2f9 Renato Botelho
			}
315
		}
316 48614394 Phil Davis
	}
317 e680b2f9 Renato Botelho
318 48614394 Phil Davis
	if ($_POST['maxtime'] && (!is_numeric($_POST['maxtime']) || ($_POST['maxtime'] < 60) || ($_POST['maxtime'] <= $_POST['deftime']))) {
319
		$input_errors[] = gettext("The maximum lease time must be at least 60 seconds and higher than the default lease time.");
320
	}
321
	if (($_POST['ddnsdomain'] && !is_domain($_POST['ddnsdomain']))) {
322
		$input_errors[] = gettext("A valid domain name must be specified for the dynamic DNS registration.");
323
	}
324
	if (($_POST['ddnsdomain'] && !is_ipaddrv4($_POST['ddnsdomainprimary']))) {
325
		$input_errors[] = gettext("A valid primary domain name server IP address must be specified for the dynamic domain name.");
326
	}
327
	if (($_POST['ddnsdomainkey'] && !$_POST['ddnsdomainkeyname']) ||
328
		($_POST['ddnsdomainkeyname'] && !$_POST['ddnsdomainkey'])) {
329
		$input_errors[] = gettext("Both a valid domain key and key name 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 42a3cbab Pierre POMES
			}
338
		}
339 48614394 Phil Davis
	}
340 1f1a08c8 jim-p
341 48614394 Phil Davis
	// 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 1f1a08c8 jim-p
349 48614394 Phil Davis
	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 2c75b451 sullrich
362 48614394 Phil Davis
	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 e9f147c8 Scott Ullrich
369 48614394 Phil Davis
	// 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 8f8682f7 Phil Davis
				}
376 7dfa60fa Ermal Lu?i
			}
377 2c75b451 sullrich
		}
378 48614394 Phil Davis
	}
379 2c75b451 sullrich
380 48614394 Phil Davis
	$noip = false;
381
	if (is_array($a_maps)) {
382
		foreach ($a_maps as $map) {
383
			if (empty($map['ipaddr'])) {
384
				$noip = true;
385 8f8682f7 Phil Davis
			}
386
		}
387 48614394 Phil Davis
	}
388 b5f6e690 Stephen Beaver
389 48614394 Phil Davis
	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 678dfd0f Erik Fonnesbeck
			}
417
		}
418 48614394 Phil Davis
	}
419 678dfd0f Erik Fonnesbeck
420 48614394 Phil Davis
	/* If enabling DHCP Server, make sure that the DHCP Relay isn't enabled on this interface */
421
	if ($_POST['enable'] && isset($config['dhcrelay']['enable']) && (stristr($config['dhcrelay']['interface'], $if) !== false)) {
422
		$input_errors[] = sprintf(gettext("The DHCP relay on the %s interface must be disabled before enabling the DHCP server."), $iflist[$if]);
423
	}
424
425
	// 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.
426
	if (!$input_errors && $_POST['range_from'] && $_POST['range_to']) {
427
		/* make sure the range lies within the current subnet */
428
		if (ip_greater_than($_POST['range_from'], $_POST['range_to'])) {
429
			$input_errors[] = gettext("The range is invalid (first element higher than second element).");
430
		}
431
432
		if (!is_inrange_v4($_POST['range_from'], $subnet_start, $subnet_end) ||
433
			!is_inrange_v4($_POST['range_to'], $subnet_start, $subnet_end)) {
434
			$input_errors[] = gettext("The specified range lies outside of the current subnet.");
435
		}
436
437
		if (is_numeric($pool) || ($act == "newpool")) {
438
			if (is_inrange_v4($_POST['range_from'],
439
				$config['dhcpd'][$if]['range']['from'],
440
				$config['dhcpd'][$if]['range']['to']) ||
441
				is_inrange_v4($_POST['range_to'],
442
				$config['dhcpd'][$if]['range']['from'],
443
				$config['dhcpd'][$if]['range']['to'])) {
444
				$input_errors[] = gettext("The specified range must not be within the DHCP range for this interface.");
445 8f8682f7 Phil Davis
			}
446 48614394 Phil Davis
		}
447 e9f147c8 Scott Ullrich
448 48614394 Phil Davis
		foreach ($a_pools as $id => $p) {
449
			if (is_numeric($pool) && ($id == $pool)) {
450
				continue;
451 ec513fa9 stilez
			}
452
453 48614394 Phil Davis
			if (is_inrange_v4($_POST['range_from'],
454
				$p['range']['from'], $p['range']['to']) ||
455
				is_inrange_v4($_POST['range_to'],
456
				$p['range']['from'], $p['range']['to'])) {
457
				$input_errors[] = gettext("The specified range must not be within the range configured on a DHCP pool for this interface.");
458
				break;
459 f657f5e1 Renato Botelho
			}
460 48614394 Phil Davis
		}
461 f657f5e1 Renato Botelho
462 48614394 Phil Davis
		if (is_array($a_maps)) {
463
			foreach ($a_maps as $map) {
464
				if (empty($map['ipaddr'])) {
465 f657f5e1 Renato Botelho
					continue;
466 8f8682f7 Phil Davis
				}
467 48614394 Phil Davis
				if (is_inrange_v4($map['ipaddr'], $_POST['range_from'], $_POST['range_to'])) {
468
					$input_errors[] = sprintf(gettext("The DHCP range cannot overlap any static DHCP mappings."));
469 f657f5e1 Renato Botelho
					break;
470
				}
471
			}
472 5b237745 Scott Ullrich
		}
473
	}
474
475
	if (!$input_errors) {
476 cba980f6 jim-p
		if (!is_numeric($pool)) {
477
			if ($act == "newpool") {
478
				$dhcpdconf = array();
479
			} else {
480 8f8682f7 Phil Davis
				if (!is_array($config['dhcpd'][$if])) {
481 cba980f6 jim-p
					$config['dhcpd'][$if] = array();
482 8f8682f7 Phil Davis
				}
483 cba980f6 jim-p
				$dhcpdconf = $config['dhcpd'][$if];
484
			}
485
		} else {
486
			if (is_array($a_pools[$pool])) {
487
				$dhcpdconf = $a_pools[$pool];
488
			} else {
489
				// Someone specified a pool but it doesn't exist. Punt.
490
				header("Location: services_dhcp.php");
491
				exit;
492
			}
493
		}
494 8f8682f7 Phil Davis
		if (!is_array($dhcpdconf['range'])) {
495 cba980f6 jim-p
			$dhcpdconf['range'] = array();
496 8f8682f7 Phil Davis
		}
497 cba980f6 jim-p
498 6c124212 Phil Davis
		$dhcpd_enable_changed = false;
499
500 cba980f6 jim-p
		// Global Options
501
		if (!is_numeric($pool) && !($act == "newpool")) {
502 6c124212 Phil Davis
			$old_dhcpd_enable = isset($dhcpdconf['enable']);
503
			$new_dhcpd_enable = ($_POST['enable']) ? true : false;
504
			if ($old_dhcpd_enable != $new_dhcpd_enable) {
505
				/* DHCP has been enabled or disabled. The pf ruleset will need to be rebuilt to allow or disallow DHCP. */
506
				$dhcpd_enable_changed = true;
507
			}
508 b5f6e690 Stephen Beaver
509 6c124212 Phil Davis
			$dhcpdconf['enable'] = $new_dhcpd_enable;
510 cba980f6 jim-p
			$dhcpdconf['staticarp'] = ($_POST['staticarp']) ? true : false;
511
			$previous = $dhcpdconf['failover_peerip'];
512 b5f6e690 Stephen Beaver
			if ($previous != $_POST['failover_peerip']) {
513 cba980f6 jim-p
				mwexec("/bin/rm -rf /var/dhcpd/var/db/*");
514 8f8682f7 Phil Davis
			}
515 b5f6e690 Stephen Beaver
516 cba980f6 jim-p
			$dhcpdconf['failover_peerip'] = $_POST['failover_peerip'];
517 466aae83 Phil Davis
			// dhcpleaseinlocaltime is global to all interfaces. So update the setting on all interfaces.
518
			foreach ($config['dhcpd'] as &$dhcpdifitem) {
519
				$dhcpdifitem['dhcpleaseinlocaltime'] = $_POST['dhcpleaseinlocaltime'];
520
			}
521 ee1fb205 jim-p
		} else {
522
			// Options that exist only in pools
523
			$dhcpdconf['descr'] = $_POST['descr'];
524 cba980f6 jim-p
		}
525
526
		// Options that can be global or per-pool.
527
		$dhcpdconf['range']['from'] = $_POST['range_from'];
528
		$dhcpdconf['range']['to'] = $_POST['range_to'];
529
		$dhcpdconf['defaultleasetime'] = $_POST['deftime'];
530
		$dhcpdconf['maxleasetime'] = $_POST['maxtime'];
531
		$dhcpdconf['netmask'] = $_POST['netmask'];
532
533
		unset($dhcpdconf['winsserver']);
534 8f8682f7 Phil Davis
		if ($_POST['wins1']) {
535 cba980f6 jim-p
			$dhcpdconf['winsserver'][] = $_POST['wins1'];
536 8f8682f7 Phil Davis
		}
537
		if ($_POST['wins2']) {
538 cba980f6 jim-p
			$dhcpdconf['winsserver'][] = $_POST['wins2'];
539 8f8682f7 Phil Davis
		}
540 4cab31d0 Scott Ullrich
541 cba980f6 jim-p
		unset($dhcpdconf['dnsserver']);
542 8f8682f7 Phil Davis
		if ($_POST['dns1']) {
543 cba980f6 jim-p
			$dhcpdconf['dnsserver'][] = $_POST['dns1'];
544 8f8682f7 Phil Davis
		}
545
		if ($_POST['dns2']) {
546 cba980f6 jim-p
			$dhcpdconf['dnsserver'][] = $_POST['dns2'];
547 8f8682f7 Phil Davis
		}
548
		if ($_POST['dns3']) {
549 3b5707db Phil Davis
			$dhcpdconf['dnsserver'][] = $_POST['dns3'];
550 8f8682f7 Phil Davis
		}
551
		if ($_POST['dns4']) {
552 3b5707db Phil Davis
			$dhcpdconf['dnsserver'][] = $_POST['dns4'];
553 8f8682f7 Phil Davis
		}
554 cba980f6 jim-p
555
		$dhcpdconf['gateway'] = $_POST['gateway'];
556
		$dhcpdconf['domain'] = $_POST['domain'];
557
		$dhcpdconf['domainsearchlist'] = $_POST['domainsearchlist'];
558 6d53301b Jose Luis Duran
		$dhcpdconf['ignorebootp'] = ($_POST['ignorebootp']) ? true : false;
559 cba980f6 jim-p
		$dhcpdconf['denyunknown'] = ($_POST['denyunknown']) ? true : false;
560 11ee0c6d Brett Keller
		$dhcpdconf['ignoreclientuids'] = ($_POST['ignoreclientuids']) ? true : false;
561 3475eb04 Andrew Pilloud
		$dhcpdconf['nonak'] = ($_POST['nonak']) ? true : false;
562 cba980f6 jim-p
		$dhcpdconf['ddnsdomain'] = $_POST['ddnsdomain'];
563 87019fc4 Andres Petralli
		$dhcpdconf['ddnsdomainprimary'] = $_POST['ddnsdomainprimary'];
564
		$dhcpdconf['ddnsdomainkeyname'] = $_POST['ddnsdomainkeyname'];
565
		$dhcpdconf['ddnsdomainkey'] = $_POST['ddnsdomainkey'];
566 cba980f6 jim-p
		$dhcpdconf['ddnsupdate'] = ($_POST['ddnsupdate']) ? true : false;
567 cf15bcb4 Ross Williams
		$dhcpdconf['ddnsforcehostname'] = ($_POST['ddnsforcehostname']) ? true : false;
568 cba980f6 jim-p
		$dhcpdconf['mac_allow'] = $_POST['mac_allow'];
569
		$dhcpdconf['mac_deny'] = $_POST['mac_deny'];
570
571
		unset($dhcpdconf['ntpserver']);
572 8f8682f7 Phil Davis
		if ($_POST['ntp1']) {
573 cba980f6 jim-p
			$dhcpdconf['ntpserver'][] = $_POST['ntp1'];
574 8f8682f7 Phil Davis
		}
575
		if ($_POST['ntp2']) {
576 cba980f6 jim-p
			$dhcpdconf['ntpserver'][] = $_POST['ntp2'];
577 8f8682f7 Phil Davis
		}
578 ad171999 Seth Mos
579 cba980f6 jim-p
		$dhcpdconf['tftp'] = $_POST['tftp'];
580
		$dhcpdconf['ldap'] = $_POST['ldap'];
581
		$dhcpdconf['netboot'] = ($_POST['netboot']) ? true : false;
582
		$dhcpdconf['nextserver'] = $_POST['nextserver'];
583
		$dhcpdconf['filename'] = $_POST['filename'];
584 7023c602 Charlie Root
		$dhcpdconf['filename32'] = $_POST['filename32'];
585
		$dhcpdconf['filename64'] = $_POST['filename64'];
586 cba980f6 jim-p
		$dhcpdconf['rootpath'] = $_POST['rootpath'];
587 18d316a5 heper
		unset($dhcpdconf['statsgraph']);
588
		if ($_POST['statsgraph']) {
589
			$dhcpdconf['statsgraph'] = $_POST['statsgraph'];
590 6303601e heper
			enable_rrd_graphing();
591 18d316a5 heper
		}
592 9c748b70 Scott Ullrich
593 d72b4114 Scott Ullrich
		// Handle the custom options rowhelper
594 8f8682f7 Phil Davis
		if (isset($dhcpdconf['numberoptions']['item'])) {
595 cba980f6 jim-p
			unset($dhcpdconf['numberoptions']['item']);
596 8f8682f7 Phil Davis
		}
597 6d1af0e9 jim-p
598 cba980f6 jim-p
		$dhcpdconf['numberoptions'] = $numberoptions;
599
600
		if (is_numeric($pool) && is_array($a_pools[$pool])) {
601
			$a_pools[$pool] = $dhcpdconf;
602
		} elseif ($act == "newpool") {
603
			$a_pools[] = $dhcpdconf;
604
		} else {
605
			$config['dhcpd'][$if] = $dhcpdconf;
606
		}
607 518030b3 Scott Ullrich
608 5b237745 Scott Ullrich
		write_config();
609 565488c9 Renato Botelho
	}
610
}
611 80933129 Bill Marquette
612 141d8913 jim-p
if ((isset($_POST['save']) || isset($_POST['apply'])) && (!$input_errors)) {
613 44c42356 Phil Davis
	$changes_applied = true;
614 565488c9 Renato Botelho
	$retval = 0;
615
	$retvaldhcp = 0;
616
	$retvaldns = 0;
617
	/* dnsmasq_configure calls dhcpd_configure */
618
	/* no need to restart dhcpd twice */
619
	if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic']))	{
620 44c42356 Phil Davis
		$retvaldns |= services_dnsmasq_configure();
621 565488c9 Renato Botelho
		if ($retvaldns == 0) {
622
			clear_subsystem_dirty('hosts');
623
			clear_subsystem_dirty('staticmaps');
624 de792e62 jim-p
		}
625 565488c9 Renato Botelho
	} else if (isset($config['unbound']['enable']) && isset($config['unbound']['regdhcpstatic'])) {
626 44c42356 Phil Davis
		$retvaldns |= services_unbound_configure();
627 4230ad16 Phil Davis
		if ($retvaldns == 0) {
628 565488c9 Renato Botelho
			clear_subsystem_dirty('unbound');
629 d3801fdb Renato Botelho
			clear_subsystem_dirty('hosts');
630
			clear_subsystem_dirty('staticmaps');
631 4230ad16 Phil Davis
		}
632 565488c9 Renato Botelho
	} else {
633 44c42356 Phil Davis
		$retvaldhcp |= services_dhcpd_configure();
634 8f8682f7 Phil Davis
		if ($retvaldhcp == 0) {
635 565488c9 Renato Botelho
			clear_subsystem_dirty('staticmaps');
636 8f8682f7 Phil Davis
		}
637 5b237745 Scott Ullrich
	}
638 8f8682f7 Phil Davis
	if ($dhcpd_enable_changed) {
639 44c42356 Phil Davis
		$retvalfc |= filter_configure();
640 8f8682f7 Phil Davis
	}
641 565488c9 Renato Botelho
642 8f8682f7 Phil Davis
	if ($retvaldhcp == 1 || $retvaldns == 1 || $retvalfc == 1) {
643 565488c9 Renato Botelho
		$retval = 1;
644 8f8682f7 Phil Davis
	}
645 5b237745 Scott Ullrich
}
646
647 cba980f6 jim-p
if ($act == "delpool") {
648
	if ($a_pools[$_GET['id']]) {
649
		unset($a_pools[$_GET['id']]);
650
		write_config();
651
		header("Location: services_dhcp.php?if={$if}");
652
		exit;
653
	}
654
}
655
656
if ($act == "del") {
657 5b237745 Scott Ullrich
	if ($a_maps[$_GET['id']]) {
658 fbb78d6b Phil Davis
		/* Remove static ARP entry, if necessary */
659 632e5f50 jim-p
		if (isset($a_maps[$_GET['id']]['arp_table_static_entry'])) {
660
			mwexec("/usr/sbin/arp -d " . escapeshellarg($a_maps[$_GET['id']]['ipaddr']));
661
		}
662 5b237745 Scott Ullrich
		unset($a_maps[$_GET['id']]);
663
		write_config();
664 8f8682f7 Phil Davis
		if (isset($config['dhcpd'][$if]['enable'])) {
665 a368a026 Ermal Lu?i
			mark_subsystem_dirty('staticmaps');
666 8f8682f7 Phil Davis
			if (isset($config['dnsmasq']['enable']) && isset($config['dnsmasq']['regdhcpstatic'])) {
667 a368a026 Ermal Lu?i
				mark_subsystem_dirty('hosts');
668 8f8682f7 Phil Davis
			}
669 6a01ea44 Bill Marquette
		}
670 b5f6e690 Stephen Beaver
671 5b237745 Scott Ullrich
		header("Location: services_dhcp.php?if={$if}");
672
		exit;
673
	}
674
}
675 4df96eff Scott Ullrich
676 3c9befb9 Chris Buechler
// Build an HTML table that can be inserted into a Form_StaticText element
677 b5f6e690 Stephen Beaver
function build_pooltable() {
678 96ab6943 Chris Buechler
	global $a_pools, $if;
679 b5f6e690 Stephen Beaver
680
	$pooltbl =	'<div class="table-responsive">';
681
	$pooltbl .=		'<table class="table table-striped table-hover table-condensed">';
682
	$pooltbl .=			'<thead>';
683
	$pooltbl .=				'<tr>';
684
	$pooltbl .=					'<th>' . gettext("Pool Start") . '</th>';
685
	$pooltbl .=					'<th>' . gettext("Pool End") . '</th>';
686
	$pooltbl .=					'<th>' . gettext("Description") . '</th>';
687 d7d7820e Phil Davis
	$pooltbl .=					'<th>' . gettext("Actions") . '</th>';
688 b5f6e690 Stephen Beaver
	$pooltbl .=				'</tr>';
689
	$pooltbl .=			'</thead>';
690
	$pooltbl .=			'<tbody>';
691
692
	if (is_array($a_pools)) {
693
		$i = 0;
694
		foreach ($a_pools as $poolent) {
695
			if (!empty($poolent['range']['from']) && !empty($poolent['range']['to'])) {
696
				$pooltbl .= '<tr>';
697
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
698
							htmlspecialchars($poolent['range']['from']) . '</td>';
699
700
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
701
							htmlspecialchars($poolent['range']['to']) . '</td>';
702
703
				$pooltbl .= '<td ondblclick="document.location=\'services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '\';">' .
704
							htmlspecialchars($poolent['descr']) . '</td>';
705
706 d7d7820e Phil Davis
				$pooltbl .= '<td><a class="fa fa-pencil" title="'. gettext("Edit pool") . '" href="services_dhcp.php?if=' . htmlspecialchars($if) . '&pool=' . $i . '"></a>';
707 b5f6e690 Stephen Beaver
708 d7d7820e Phil Davis
				$pooltbl .= ' <a class="fa fa-trash" title="'. gettext("Delete pool") . '" href="services_dhcp.php?if=' . htmlspecialchars($if) . '&act=delpool&id=' . $i . '"></a></td>';
709 b5f6e690 Stephen Beaver
				$pooltbl .= '</tr>';
710
			}
711
		$i++;
712
		}
713
	}
714
715
	$pooltbl .=			'</tbody>';
716
	$pooltbl .=		'</table>';
717
	$pooltbl .= '</div>';
718
719
	return($pooltbl);
720
}
721
722 bf27317d Phil Davis
$pgtitle = array(gettext("Services"), gettext("DHCP Server"));
723 fa94122b k-paulius
724 48614394 Phil Davis
if (!empty($if) && isset($iflist[$if])) {
725 fa94122b k-paulius
	$pgtitle[] = $iflist[$if];
726
}
727 b32dd0a6 jim-p
$shortcut_section = "dhcp";
728 5224b8e7 jim-p
729 4df96eff Scott Ullrich
include("head.inc");
730
731 6e3488e9 Phil Davis
if ($input_errors) {
732 b5f6e690 Stephen Beaver
	print_input_errors($input_errors);
733 6e3488e9 Phil Davis
}
734 4df96eff Scott Ullrich
735 44c42356 Phil Davis
if ($changes_applied) {
736
	print_apply_result_box($retval);
737 6e3488e9 Phil Davis
}
738 678dfd0f Erik Fonnesbeck
739 6e3488e9 Phil Davis
if (is_subsystem_dirty('staticmaps')) {
740 5daef710 NOYB
	print_apply_box(gettext("The static mapping configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
741 6e3488e9 Phil Davis
}
742 b5f6e690 Stephen Beaver
743
/* active tabs */
744
$tab_array = array();
745
$tabscounter = 0;
746
$i = 0;
747 b7090449 Phil Davis
$have_small_subnet = false;
748 8a73f407 Stephen Beaver
749 b5f6e690 Stephen Beaver
foreach ($iflist as $ifent => $ifname) {
750
	$oc = $config['interfaces'][$ifent];
751 403dad2a Renato Botelho
752
	/* Not static IPv4 or subnet >= 31 */
753 b7090449 Phil Davis
	if ($oc['subnet'] >= 31) {
754
		$have_small_subnet = true;
755 12e08722 Phil Davis
		$example_name = $ifname;
756
		$example_cidr = $oc['subnet'];
757 b7090449 Phil Davis
		continue;
758
	}
759
	if (!is_ipaddrv4($oc['ipaddr']) || empty($oc['subnet'])) {
760 b5f6e690 Stephen Beaver
		continue;
761 518030b3 Scott Ullrich
	}
762 4e9cd828 Seth Mos
763 b5f6e690 Stephen Beaver
	if ($ifent == $if) {
764
		$active = true;
765
	} else {
766
		$active = false;
767 b1d132f5 Scott Ullrich
	}
768
769 b5f6e690 Stephen Beaver
	$tab_array[] = array($ifname, $active, "services_dhcp.php?if={$ifent}");
770
	$tabscounter++;
771
}
772 ad171999 Seth Mos
773 b5f6e690 Stephen Beaver
if ($tabscounter == 0) {
774 b7090449 Phil Davis
	if ($have_small_subnet) {
775 12e08722 Phil Davis
		$sentence2 = sprintf(gettext('%1$s has a CIDR mask of %2$s, which does not contain enough addresses.'), htmlspecialchars($example_name), htmlspecialchars($example_cidr));
776 b7090449 Phil Davis
	} else {
777 12e08722 Phil Davis
		$sentence2 = gettext("This system has no interfaces configured with a static IPv4 address.");
778 b7090449 Phil Davis
	}
779 12e08722 Phil Davis
	print_info_box(gettext("The DHCP Server requires a static IPv4 subnet large enough to serve addresses to clients.") . " " . $sentence2);
780 b5f6e690 Stephen Beaver
	include("foot.inc");
781
	exit;
782
}
783 1f1a08c8 jim-p
784 b5f6e690 Stephen Beaver
display_top_tabs($tab_array);
785
786 8f58b51b jim-p
$form = new Form();
787 b5f6e690 Stephen Beaver
788
$section = new Form_Section('General Options');
789
790
if (!is_numeric($pool) && !($act == "newpool")) {
791 48614394 Phil Davis
	if (isset($config['dhcrelay']['enable'])) {
792
		$section->addInput(new Form_Checkbox(
793
			'enable',
794
			'Enable',
795
			gettext("DHCP Relay is currently enabled. DHCP Server canot be enabled while the DHCP Relay is enabled on any interface."),
796
			$pconfig['enable']
797
		))->setAttribute('disabled', true);
798
	} else {
799
		$section->addInput(new Form_Checkbox(
800
			'enable',
801
			'Enable',
802
			sprintf(gettext("Enable DHCP server on %s interface"), htmlspecialchars($iflist[$if])),
803
			$pconfig['enable']
804
		));
805
	}
806 b5f6e690 Stephen Beaver
} else {
807 02342d8c k-paulius
	print_info_box(gettext('Editing pool-specific options. To return to the Interface, click its tab above.'), 'info', false);
808 b5f6e690 Stephen Beaver
}
809 6c23757b Martin Fuchs
810 6d53301b Jose Luis Duran
$section->addInput(new Form_Checkbox(
811
	'ignorebootp',
812
	'BOOTP',
813
	'Ignore BOOTP queries',
814
	$pconfig['ignorebootp']
815
));
816
817 b5f6e690 Stephen Beaver
$section->addInput(new Form_Checkbox(
818
	'denyunknown',
819
	'Deny unknown clients',
820
	'Only the clients defined below will get DHCP leases from this server.',
821
	$pconfig['denyunknown']
822
));
823
824 3475eb04 Andrew Pilloud
$section->addInput(new Form_Checkbox(
825
	'nonak',
826
	'Ignore denied clients',
827
	'Denied clients will be ignored rather than rejected.',
828
	$pconfig['nonak']
829 8209517d jim-p
))->setHelp("This option is not compatible with failover and cannot be enabled when a Failover Peer IP address is configured.");
830 3475eb04 Andrew Pilloud
831 11ee0c6d Brett Keller
$section->addInput(new Form_Checkbox(
832
	'ignoreclientuids',
833
	'Ignore client identifiers',
834
	'If a client includes a unique identifier in its DHCP request, that UID will not be recorded in its lease.',
835
	$pconfig['ignoreclientuids']
836
))->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.");
837
838 3475eb04 Andrew Pilloud
839 b5f6e690 Stephen Beaver
if (is_numeric($pool) || ($act == "newpool")) {
840
	$section->addInput(new Form_Input(
841
		'descr',
842
		'Pool Description',
843
		'text',
844
		$pconfig['descr']
845
	));
846
}
847 6c23757b Martin Fuchs
848 b5f6e690 Stephen Beaver
$section->addInput(new Form_StaticText(
849
	'Subnet',
850
	gen_subnet($ifcfgip, $ifcfgsn)
851
));
852 4e9cd828 Seth Mos
853 b5f6e690 Stephen Beaver
$section->addInput(new Form_StaticText(
854
	'Subnet mask',
855
	gen_subnet_mask($ifcfgsn)
856
));
857 5b237745 Scott Ullrich
858 8a73f407 Stephen Beaver
// Compose a string to display the required address ranges
859 b90d635e Renato Botelho
$rangestr = ip_after($subnet_start) . ' - ' . ip_before($subnet_end);
860 b5f6e690 Stephen Beaver
861
if (is_numeric($pool) || ($act == "newpool")) {
862 4bb7c0d1 bruno
	$rangestr .= '<br />' . gettext('In-use DHCP Pool Ranges:');
863 b5f6e690 Stephen Beaver
	if (is_array($config['dhcpd'][$if]['range'])) {
864
		$rangestr .= '<br />' . $config['dhcpd'][$if]['range']['from'] . ' - ' . $config['dhcpd'][$if]['range']['to'];
865 3d7b7757 Chris Buechler
	}
866 b5f6e690 Stephen Beaver
867
	foreach ($a_pools as $p) {
868
		if (is_array($p['range'])) {
869
			$rangestr .= '<br />' . $p['range']['from'] . ' - ' . $p['range']['to'];
870 8f8682f7 Phil Davis
		}
871 934240ef Ermal Luçi
	}
872 b5f6e690 Stephen Beaver
}
873
874
$section->addInput(new Form_StaticText(
875
	'Available range',
876
	$rangestr
877
));
878
879
if ($is_olsr_enabled) {
880
	$section->addInput(new Form_Select(
881
		'netmask',
882
		'Subnet mask',
883
		$pconfig['netmask'],
884
		array_combine(range(32, 1, -1), range(32, 1, -1))
885
	));
886
}
887
888
$group = new Form_Group('Range');
889
890
$group->add(new Form_IpAddress(
891
	'range_from',
892
	null,
893 eb01f065 Phil Davis
	$pconfig['range_from'],
894
	'V4'
895 b5f6e690 Stephen Beaver
))->setHelp('From');
896
897
$group->add(new Form_IpAddress(
898
	'range_to',
899
	null,
900 eb01f065 Phil Davis
	$pconfig['range_to'],
901
	'V4'
902 b5f6e690 Stephen Beaver
))->setHelp('To');
903
904
$section->add($group);
905
906
$form->add($section);
907
908
if (!is_numeric($pool) && !($act == "newpool")) {
909 5f88f964 k-paulius
	$section = new Form_Section('Additional Pools');
910 b5f6e690 Stephen Beaver
911
	$btnaddpool = new Form_Button(
912
		'btnaddpool',
913 faab522f Renato Botelho
		'Add pool',
914 37676f4e jim-p
		'services_dhcp.php?if=' . htmlspecialchars($if) . '&act=newpool',
915
		'fa-plus'
916 b5f6e690 Stephen Beaver
	);
917 37676f4e jim-p
	$btnaddpool->addClass('btn-success');
918 b5f6e690 Stephen Beaver
919
	$section->addInput(new Form_StaticText(
920
		'Add',
921
		$btnaddpool
922 e78ecb96 NOYB
	))->setHelp('If additional pools of addresses are needed inside of this subnet outside the above Range, they may be specified here.');
923 b5f6e690 Stephen Beaver
924
	if (is_array($a_pools)) {
925
		$section->addInput(new Form_StaticText(
926
			null,
927
			build_pooltable()
928
		));
929 f0cdf141 Scott Ullrich
	}
930 b5f6e690 Stephen Beaver
931
	$form->add($section);
932
}
933
934
$section = new Form_Section('Servers');
935
936
$section->addInput(new Form_IpAddress(
937
	'wins1',
938
	'WINS servers',
939 eb01f065 Phil Davis
	$pconfig['wins1'],
940
	'V4'
941
))->setAttribute('placeholder', 'WINS Server 1');
942 b5f6e690 Stephen Beaver
943
$section->addInput(new Form_IpAddress(
944
	'wins2',
945
	null,
946 eb01f065 Phil Davis
	$pconfig['wins2'],
947
	'V4'
948
))->setAttribute('placeholder', 'WINS Server 2');
949 b5f6e690 Stephen Beaver
950 6e3488e9 Phil Davis
for ($idx=1; $idx<=4; $idx++) {
951 b5f6e690 Stephen Beaver
	$section->addInput(new Form_IpAddress(
952
		'dns' . $idx,
953
		($idx == 1) ? 'DNS servers':null,
954 eb01f065 Phil Davis
		$pconfig['dns' . $idx],
955
		'V4'
956
	))->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.':'');
957 b5f6e690 Stephen Beaver
}
958
959
$form->add($section);
960
961 5f88f964 k-paulius
$section = new Form_Section('Other Options');
962 b5f6e690 Stephen Beaver
963
$section->addInput(new Form_IpAddress(
964
	'gateway',
965
	'Gateway',
966 eb01f065 Phil Davis
	$pconfig['gateway'],
967
	'V4'
968 b5f6e690 Stephen Beaver
))->setPattern('[.a-zA-Z0-9_]+')
969 e78ecb96 NOYB
  ->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.');
970 b5f6e690 Stephen Beaver
971
$section->addInput(new Form_Input(
972
	'domain',
973
	'Domain name',
974
	'text',
975
	$pconfig['domain']
976 e78ecb96 NOYB
))->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.');
977 b5f6e690 Stephen Beaver
978
$section->addInput(new Form_Input(
979
	'domainsearchlist',
980
	'Domain search list',
981
	'text',
982
	$pconfig['domainsearchlist']
983 e78ecb96 NOYB
))->setHelp('The DHCP server can optionally provide a domain search list. Use the semicolon character as separator.');
984 b5f6e690 Stephen Beaver
985
$section->addInput(new Form_Input(
986
	'deftime',
987
	'Default lease time',
988
	'number',
989
	$pconfig['deftime']
990 e78ecb96 NOYB
))->setHelp('This is used for clients that do not ask for a specific expiration time. The default is 7200 seconds.');
991 b5f6e690 Stephen Beaver
992
$section->addInput(new Form_Input(
993
	'maxtime',
994
	'Maximum lease time',
995
	'number',
996
	$pconfig['maxtime']
997 e78ecb96 NOYB
))->setHelp('This is the maximum lease time for clients that ask for a specific expiration time. The default is 86400 seconds.');
998 b5f6e690 Stephen Beaver
999
if (!is_numeric($pool) && !($act == "newpool")) {
1000
	$section->addInput(new Form_IpAddress(
1001
		'failover_peerip',
1002
		'Failover peer IP',
1003 eb01f065 Phil Davis
		$pconfig['failover_peerip'],
1004
		'V4'
1005 af8f79b1 Chris Buechler
	))->setHelp('Leave blank to disable. Enter the interface IP address of the other machine. Machines must be using CARP. ' .
1006 4c1284c6 NOYB
				'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).');
1007 b5f6e690 Stephen Beaver
}
1008
1009
if (!is_numeric($pool) && !($act == "newpool")) {
1010
	$section->addInput(new Form_Checkbox(
1011
		'staticarp',
1012
		'Static ARP',
1013
		'Enable Static ARP entries',
1014
		$pconfig['staticarp']
1015 0c8d2784 Chris Buechler
	))->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.');
1016 b5f6e690 Stephen Beaver
1017
	$section->addInput(new Form_Checkbox(
1018
		'dhcpleaseinlocaltime',
1019
		'Time format change',
1020
		'Change DHCP display lease time from UTC to local time',
1021
		$pconfig['dhcpleaseinlocaltime']
1022
	))->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.' .
1023 e78ecb96 NOYB
				' This will be used for all DHCP interfaces lease time.');
1024 18d316a5 heper
	$section->addInput(new Form_Checkbox(
1025
		'statsgraph',
1026 61237194 Chris Buechler
		'Statistics graphs',
1027
		'Enable RRD statistics graphs',
1028 18d316a5 heper
		$pconfig['statsgraph']
1029 61237194 Chris Buechler
	))->setHelp('Enable this to add DHCP leases statistics to the RRD graphs. Disabled by default.');
1030 b5f6e690 Stephen Beaver
}
1031
1032
// DDNS
1033
$btnadv = new Form_Button(
1034
	'btnadvdns',
1035 afe62c2b Phil Davis
	'Display Advanced',
1036 3314e626 jim-p
	null,
1037
	'fa-cog'
1038 b5f6e690 Stephen Beaver
);
1039
1040 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1041 b5f6e690 Stephen Beaver
1042
$section->addInput(new Form_StaticText(
1043
	'Dynamic DNS',
1044
	$btnadv
1045
));
1046
1047
$section->addInput(new Form_Checkbox(
1048
	'ddnsupdate',
1049
	null,
1050
	'Enable registration of DHCP client names in DNS',
1051
	$pconfig['ddnsupdate']
1052
));
1053
1054
$section->addInput(new Form_Input(
1055
	'ddnsdomain',
1056
	'DDNS Domain',
1057 e8da0bcd Jeremy Porter
	'text',
1058 b5f6e690 Stephen Beaver
	$pconfig['ddnsdomain']
1059
))->setHelp('Leave blank to disable dynamic DNS registration.' . '<br />' .
1060
			'Enter the dynamic DNS domain which will be used to register client names in the DNS server.');
1061
1062 cf15bcb4 Ross Williams
$section->addInput(new Form_Checkbox(
1063
	'ddnsforcehostname',
1064 cfc10a33 Ross Williams
	'DDNS Hostnames',
1065 cf15bcb4 Ross Williams
	'Force dynamic DNS hostname to be the same as configured hostname for Static Mappings',
1066
	$pconfig['ddnsforcehostname']
1067 9ca5d4ab Ross Williams
))->setHelp('Default registers host name option supplied by DHCP client.');
1068 cf15bcb4 Ross Williams
1069 b5f6e690 Stephen Beaver
$section->addInput(new Form_IpAddress(
1070
	'ddnsdomainprimary',
1071
	'Primary DDNS address',
1072 eb01f065 Phil Davis
	$pconfig['ddnsdomainprimary'],
1073
	'V4'
1074 cb6c20a9 NewEraCracker
))->setHelp('Primary domain name server IP address for the dynamic domain name.');
1075 b5f6e690 Stephen Beaver
1076
$section->addInput(new Form_Input(
1077
	'ddnsdomainkeyname',
1078
	'DNS Domain key',
1079
	'text',
1080
	$pconfig['ddnsdomainkeyname']
1081 cb6c20a9 NewEraCracker
))->setHelp('Dynamic DNS domain key name which will be used to register client names in the DNS server.');
1082 b5f6e690 Stephen Beaver
1083
$section->addInput(new Form_Input(
1084
	'ddnsdomainkey',
1085
	'DNS Domain key secret',
1086
	'text',
1087
	$pconfig['ddnsdomainkey']
1088 4d55ef96 Chris Buechler
))->setHelp('Dynamic DNS domain key secret (HMAC-MD5) which will be used to register client names in the DNS server.');
1089 b5f6e690 Stephen Beaver
1090
// Advanced MAC
1091
$btnadv = new Form_Button(
1092
	'btnadvmac',
1093 afe62c2b Phil Davis
	'Display Advanced',
1094 3314e626 jim-p
	null,
1095
	'fa-cog'
1096 b5f6e690 Stephen Beaver
);
1097
1098 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1099 b5f6e690 Stephen Beaver
1100
$section->addInput(new Form_StaticText(
1101
	'MAC address control',
1102
	$btnadv
1103
));
1104
1105
$section->addInput(new Form_Input(
1106
	'mac_allow',
1107 ef2936e6 Stephen Beaver
	'MAC Allow',
1108 b5f6e690 Stephen Beaver
	'text',
1109
	$pconfig['mac_allow']
1110
))->setHelp('List of partial MAC addresses to allow, comma separated, no spaces, e.g.: 00:00:00,01:E5:FF');
1111
1112
$section->addInput(new Form_Input(
1113
	'mac_deny',
1114 ef2936e6 Stephen Beaver
	'MAC Deny',
1115 b5f6e690 Stephen Beaver
	'text',
1116
	$pconfig['mac_deny']
1117
))->setHelp('List of partial MAC addresses to deny access, comma separated, no spaces, e.g.: 00:00:00,01:E5:FF');
1118
1119
// Advanced NTP
1120
$btnadv = new Form_Button(
1121
	'btnadvntp',
1122 afe62c2b Phil Davis
	'Display Advanced',
1123 3314e626 jim-p
	null,
1124
	'fa-cog'
1125 b5f6e690 Stephen Beaver
);
1126
1127 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1128 b5f6e690 Stephen Beaver
1129
$section->addInput(new Form_StaticText(
1130 ff3da1e7 Stephen Beaver
	'NTP',
1131 b5f6e690 Stephen Beaver
	$btnadv
1132
));
1133
1134
$section->addInput(new Form_IpAddress(
1135
	'ntp1',
1136 ff3da1e7 Stephen Beaver
	'NTP Server 1',
1137 eb01f065 Phil Davis
	$pconfig['ntp1'],
1138 45541aae Phil Davis
	'HOSTV4'
1139
));
1140 b5f6e690 Stephen Beaver
1141
$section->addInput(new Form_IpAddress(
1142
	'ntp2',
1143 ff3da1e7 Stephen Beaver
	'NTP Server 2',
1144 eb01f065 Phil Davis
	$pconfig['ntp2'],
1145 45541aae Phil Davis
	'HOSTV4'
1146
));
1147 b5f6e690 Stephen Beaver
1148
// Advanced TFTP
1149
$btnadv = new Form_Button(
1150
	'btnadvtftp',
1151 afe62c2b Phil Davis
	'Display Advanced',
1152 3314e626 jim-p
	null,
1153
	'fa-cog'
1154 b5f6e690 Stephen Beaver
);
1155
1156 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1157 b5f6e690 Stephen Beaver
1158
$section->addInput(new Form_StaticText(
1159 ff3da1e7 Stephen Beaver
	'TFTP',
1160 b5f6e690 Stephen Beaver
	$btnadv
1161
));
1162
1163 c411661a doktornotor
$section->addInput(new Form_Input(
1164 b5f6e690 Stephen Beaver
	'tftp',
1165 ff3da1e7 Stephen Beaver
	'TFTP Server',
1166 9d9736d7 jim-p
	'text',
1167 b5f6e690 Stephen Beaver
	$pconfig['tftp']
1168 c411661a doktornotor
))->setHelp('Leave blank to disable. Enter a valid IP address, hostname or URL for the TFTP server.');
1169 b5f6e690 Stephen Beaver
1170
// Advanced LDAP
1171
$btnadv = new Form_Button(
1172
	'btnadvldap',
1173 afe62c2b Phil Davis
	'Display Advanced',
1174 3314e626 jim-p
	null,
1175
	'fa-cog'
1176 b5f6e690 Stephen Beaver
);
1177
1178 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1179 b5f6e690 Stephen Beaver
1180
$section->addInput(new Form_StaticText(
1181 ff3da1e7 Stephen Beaver
	'LDAP',
1182 b5f6e690 Stephen Beaver
	$btnadv
1183
));
1184
1185
$section->addInput(new Form_Input(
1186
	'ldap',
1187 ff3da1e7 Stephen Beaver
	'LDAP Server URI',
1188 b5f6e690 Stephen Beaver
	'text',
1189
	$pconfig['ldap']
1190
))->setHelp('Leave blank to disable. Enter a full URI for the LDAP server in the form ldap://ldap.example.com/dc=example,dc=com ');
1191
1192 68de2169 Phil Davis
// Advanced Network Booting options
1193
$btnadv = new Form_Button(
1194
	'btnadvnwkboot',
1195
	'Display Advanced',
1196
	null,
1197
	'fa-cog'
1198
);
1199
1200
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1201
1202
$section->addInput(new Form_StaticText(
1203
	'Network Booting',
1204
	$btnadv
1205
));
1206
1207
$section->addInput(new Form_Checkbox(
1208
	'netboot',
1209
	'Enable',
1210
	'Enables network booting',
1211
	$pconfig['netboot']
1212
));
1213
1214
$section->addInput(new Form_IpAddress(
1215
	'nextserver',
1216
	'Next Server',
1217 eb01f065 Phil Davis
	$pconfig['nextserver'],
1218
	'V4'
1219 68de2169 Phil Davis
))->setHelp('Enter the IP address of the next server');
1220
1221
$section->addInput(new Form_Input(
1222
	'filename',
1223
	'Default BIOS file name',
1224
	'text',
1225
	$pconfig['filename']
1226
));
1227
1228
$section->addInput(new Form_Input(
1229
	'filename32',
1230
	'UEFI 32 bit file name',
1231
	'text',
1232
	$pconfig['filename32']
1233
));
1234
1235
$section->addInput(new Form_Input(
1236
	'filename64',
1237
	'UEFI 64 bit file name',
1238
	'text',
1239
	$pconfig['filename64']
1240
))->setHelp('Both a filename and a boot server must be configured for this to work! ' .
1241
			'All three filenames and a configured boot server are necessary for UEFI to work! ');
1242
1243
$section->addInput(new Form_Input(
1244
	'rootpath',
1245
	'Root path',
1246
	'text',
1247
	$pconfig['rootpath']
1248
))->setHelp('string-format: iscsi:(servername):(protocol):(port):(LUN):targetname ');
1249
1250 b5f6e690 Stephen Beaver
// Advanced Additional options
1251
$btnadv = new Form_Button(
1252
	'btnadvopts',
1253 afe62c2b Phil Davis
	'Display Advanced',
1254 3314e626 jim-p
	null,
1255
	'fa-cog'
1256 b5f6e690 Stephen Beaver
);
1257
1258 347c0214 Phil Davis
$btnadv->setAttribute('type','button')->addClass('btn-info btn-sm');
1259 b5f6e690 Stephen Beaver
1260
$section->addInput(new Form_StaticText(
1261
	'Additional BOOTP/DHCP Options',
1262
	$btnadv
1263
));
1264
1265 f8088b00 Phil Davis
$form->add($section);
1266
1267 b5f6e690 Stephen Beaver
$section = new Form_Section('Additional BOOTP/DHCP Options');
1268
$section->addClass('adnlopts');
1269
1270
$section->addInput(new Form_StaticText(
1271
	null,
1272 5daef710 NOYB
	'<div class="alert alert-info"> ' . gettext('Enter the DHCP option number and the value for each item to include in the DHCP lease information.') . ' ' .
1273 e78ecb96 NOYB
	sprintf(gettext('For a list of available options please visit this %1$s URL%2$s'), '<a href="http://www.iana.org/assignments/bootp-dhcp-parameters/" target="_blank">', '</a>.</div>')
1274 b5f6e690 Stephen Beaver
));
1275
1276 6e3488e9 Phil Davis
if (!$pconfig['numberoptions']) {
1277 b5f6e690 Stephen Beaver
	$pconfig['numberoptions']['item']  = array(array('number' => '', 'type' => 'text', 'value' => ''));
1278
}
1279
1280
$customitemtypes = array(
1281
	'text' => gettext('Text'), 'string' => gettext('String'), 'boolean' => gettext('Boolean'),
1282
	'unsigned integer 8' => gettext('Unsigned 8-bit integer'), 'unsigned integer 16' => gettext('Unsigned 16-bit integer'), 'unsigned integer 32' => gettext('Unsigned 32-bit integer'),
1283
	'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')
1284
);
1285
1286
$numrows = count($item) -1;
1287
$counter = 0;
1288
1289
$numrows = count($pconfig['numberoptions']['item']) -1;
1290
1291
foreach ($pconfig['numberoptions']['item'] as $item) {
1292
	$number = $item['number'];
1293
	$itemtype = $item['type'];
1294 65cce9d7 Renato Botelho
	$value = base64_decode($item['value']);
1295 b5f6e690 Stephen Beaver
1296
	$group = new Form_Group(($counter == 0) ? 'Option':null);
1297
	$group->addClass('repeatable');
1298
1299
	$group->add(new Form_Input(
1300
		'number' . $counter,
1301
		null,
1302
		'text',
1303
		$number
1304
	))->setHelp($numrows == $counter ? 'Number':null);
1305
1306
1307
	$group->add(new Form_Select(
1308
		'itemtype' . $counter,
1309
		null,
1310
		$itemtype,
1311
		$customitemtypes
1312 8a73f407 Stephen Beaver
	))->setWidth(3)->setHelp($numrows == $counter ? 'Type':null);
1313 b5f6e690 Stephen Beaver
1314
	$group->add(new Form_Input(
1315
		'value' . $counter,
1316
		null,
1317
		'text',
1318
		$value
1319
	))->setHelp($numrows == $counter ? 'Value':null);
1320
1321
	$group->add(new Form_Button(
1322
		'deleterow' . $counter,
1323 faab522f Renato Botelho
		'Delete',
1324 cd7ddae6 jim-p
		null,
1325
		'fa-trash'
1326
	))->addClass('btn-warning');
1327 b5f6e690 Stephen Beaver
1328
	$section->add($group);
1329
1330
	$counter++;
1331
}
1332
1333
$section->addInput(new Form_Button(
1334
	'addrow',
1335 faab522f Renato Botelho
	'Add',
1336 cd7ddae6 jim-p
	null,
1337
	'fa-plus'
1338
))->addClass('btn-success');
1339 b5f6e690 Stephen Beaver
1340
$form->add($section);
1341
1342
if ($act == "newpool") {
1343
	$form->addGlobal(new Form_Input(
1344
		'act',
1345
		null,
1346
		'hidden',
1347
		'newpool'
1348
	));
1349
}
1350
1351
if (is_numeric($pool)) {
1352
	$form->addGlobal(new Form_Input(
1353
		'pool',
1354
		null,
1355
		'hidden',
1356
		$pool
1357
	));
1358
}
1359
1360
$form->addGlobal(new Form_Input(
1361
	'if',
1362
	null,
1363
	'hidden',
1364
	$if
1365
));
1366
1367
print($form);
1368
1369
// DHCP Static Mappings table
1370
1371
if (!is_numeric($pool) && !($act == "newpool")) {
1372 de792e62 jim-p
?>
1373 b5f6e690 Stephen Beaver
1374
<div class="panel panel-default">
1375 3d7a8696 k-paulius
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("DHCP Static Mappings for this Interface")?></h2></div>
1376 b5f6e690 Stephen Beaver
	<div class="table-responsive">
1377 55f67b5a Stephen Beaver
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" data-sortable>
1378 b5f6e690 Stephen Beaver
				<thead>
1379
					<tr>
1380
						<th><?=gettext("Static ARP")?></th>
1381
						<th><?=gettext("MAC address")?></th>
1382
						<th><?=gettext("IP address")?></th>
1383
						<th><?=gettext("Hostname")?></th>
1384
						<th><?=gettext("Description")?></th>
1385
						<th></th>
1386
					</tr>
1387
				</thead>
1388 8f8682f7 Phil Davis
<?php
1389 b5f6e690 Stephen Beaver
	if (is_array($a_maps)) {
1390
		$i = 0;
1391 8f8682f7 Phil Davis
?>
1392 b5f6e690 Stephen Beaver
				<tbody>
1393 8f8682f7 Phil Davis
<?php
1394 b5f6e690 Stephen Beaver
		foreach ($a_maps as $mapent) {
1395 8f8682f7 Phil Davis
?>
1396 b5f6e690 Stephen Beaver
					<tr>
1397 1d932e0c NOYB
						<td class="text-center" ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1398 b5f6e690 Stephen Beaver
							<?php if (isset($mapent['arp_table_static_entry'])): ?>
1399 1b7379f9 Jared Dillard
								<i class="fa fa-check"></i>
1400 b5f6e690 Stephen Beaver
							<?php endif; ?>
1401
						</td>
1402
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1403
							<?=htmlspecialchars($mapent['mac'])?>
1404
						</td>
1405
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1406
							<?=htmlspecialchars($mapent['ipaddr'])?>
1407
						</td>
1408
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1409
							<?=htmlspecialchars($mapent['hostname'])?>
1410
						</td>
1411
						<td ondblclick="document.location='services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>';">
1412
							<?=htmlspecialchars($mapent['descr'])?>
1413
						</td>
1414
						<td>
1415 9a6a8329 heper
							<a class="fa fa-pencil"	title="<?=gettext('Edit static mapping')?>"	href="services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>&amp;id=<?=$i?>"></a>
1416 33f0b0d5 Stephen Beaver
							<a class="fa fa-trash"	title="<?=gettext('Delete static mapping')?>"	href="services_dhcp.php?if=<?=htmlspecialchars($if)?>&amp;act=del&amp;id=<?=$i?>"></a>
1417 b5f6e690 Stephen Beaver
						</td>
1418
					</tr>
1419 8f8682f7 Phil Davis
<?php
1420 b5f6e690 Stephen Beaver
		$i++;
1421
		}
1422 8f8682f7 Phil Davis
?>
1423 b5f6e690 Stephen Beaver
				</tbody>
1424 8f8682f7 Phil Davis
<?php
1425 b5f6e690 Stephen Beaver
	}
1426 8f8682f7 Phil Davis
?>
1427 82f54a42 Colin Fleming
		</table>
1428 b5f6e690 Stephen Beaver
	</div>
1429
</div>
1430 c9679d8c Stephen Beaver
1431 c10cb196 Stephen Beaver
<nav class="action-buttons">
1432 c9679d8c Stephen Beaver
	<a href="services_dhcp_edit.php?if=<?=htmlspecialchars($if)?>" class="btn btn-sm btn-success">
1433 9d5a20cf heper
		<i class="fa fa-plus icon-embed-btn"></i>
1434 c9679d8c Stephen Beaver
		<?=gettext("Add")?>
1435
	</a>
1436
</nav>
1437 8f8682f7 Phil Davis
<?php
1438 b5f6e690 Stephen Beaver
}
1439 8f8682f7 Phil Davis
?>
1440
1441 8fd9052f Colin Fleming
<script type="text/javascript">
1442 b5f6e690 Stephen Beaver
//<![CDATA[
1443 6e3488e9 Phil Davis
events.push(function() {
1444 b5f6e690 Stephen Beaver
1445
	// Show advanced DNS options ======================================================================================
1446
	var showadvdns = false;
1447
1448 afe62c2b Phil Davis
	function show_advdns(ispageload) {
1449
		var text;
1450
		// On page load decide the initial state based on the data.
1451
		if (ispageload) {
1452 b5f6e690 Stephen Beaver
<?php
1453 cf15bcb4 Ross Williams
			if (!$pconfig['ddnsupdate'] && !$pconfig['ddnsforcehostname'] && empty($pconfig['ddnsdomain']) && empty($pconfig['ddnsdomainprimary']) &&
1454 afe62c2b Phil Davis
			    empty($pconfig['ddnsdomainkeyname']) && empty($pconfig['ddnsdomainkey'])) {
1455
				$showadv = false;
1456
			} else {
1457
				$showadv = true;
1458
			}
1459
?>
1460
			showadvdns = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1461 6e3488e9 Phil Davis
		} else {
1462 afe62c2b Phil Davis
			// It was a click, swap the state.
1463
			showadvdns = !showadvdns;
1464 6e3488e9 Phil Davis
		}
1465 afe62c2b Phil Davis
1466
		hideCheckbox('ddnsupdate', !showadvdns);
1467
		hideInput('ddnsdomain', !showadvdns);
1468 cf15bcb4 Ross Williams
		hideCheckbox('ddnsforcehostname', !showadvdns);
1469 afe62c2b Phil Davis
		hideInput('ddnsdomainprimary', !showadvdns);
1470
		hideInput('ddnsdomainkeyname', !showadvdns);
1471
		hideInput('ddnsdomainkey', !showadvdns);
1472
1473
		if (showadvdns) {
1474
			text = "<?=gettext('Hide Advanced');?>";
1475
		} else {
1476
			text = "<?=gettext('Display Advanced');?>";
1477
		}
1478
		$('#btnadvdns').html('<i class="fa fa-cog"></i> ' + text);
1479 b5f6e690 Stephen Beaver
	}
1480
1481
	$('#btnadvdns').click(function(event) {
1482
		show_advdns();
1483
	});
1484
1485 afe62c2b Phil Davis
	// Show advanced MAC options ======================================================================================
1486 b5f6e690 Stephen Beaver
	var showadvmac = false;
1487
1488 afe62c2b Phil Davis
	function show_advmac(ispageload) {
1489
		var text;
1490
		// On page load decide the initial state based on the data.
1491
		if (ispageload) {
1492 8f8682f7 Phil Davis
<?php
1493 afe62c2b Phil Davis
			if (empty($pconfig['mac_allow']) && empty($pconfig['mac_deny'])) {
1494
				$showadv = false;
1495
			} else {
1496
				$showadv = true;
1497
			}
1498
?>
1499
			showadvmac = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1500 6e3488e9 Phil Davis
		} else {
1501 afe62c2b Phil Davis
			// It was a click, swap the state.
1502
			showadvmac = !showadvmac;
1503 6e3488e9 Phil Davis
		}
1504 b5f6e690 Stephen Beaver
1505 afe62c2b Phil Davis
		hideInput('mac_allow', !showadvmac);
1506
		hideInput('mac_deny', !showadvmac);
1507 b5f6e690 Stephen Beaver
1508 afe62c2b Phil Davis
		if (showadvmac) {
1509
			text = "<?=gettext('Hide Advanced');?>";
1510
		} else {
1511
			text = "<?=gettext('Display Advanced');?>";
1512
		}
1513
		$('#btnadvmac').html('<i class="fa fa-cog"></i> ' + text);
1514 b5f6e690 Stephen Beaver
	}
1515
1516
	$('#btnadvmac').click(function(event) {
1517 afe62c2b Phil Davis
		show_advmac();
1518 b5f6e690 Stephen Beaver
	});
1519
1520 afe62c2b Phil Davis
	// Show advanced NTP options ======================================================================================
1521 b5f6e690 Stephen Beaver
	var showadvntp = false;
1522
1523 afe62c2b Phil Davis
	function show_advntp(ispageload) {
1524
		var text;
1525
		// On page load decide the initial state based on the data.
1526
		if (ispageload) {
1527 8f8682f7 Phil Davis
<?php
1528 afe62c2b Phil Davis
			if (empty($pconfig['ntp1']) && empty($pconfig['ntp2'])) {
1529
				$showadv = false;
1530
			} else {
1531
				$showadv = true;
1532
			}
1533
?>
1534
			showadvntp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1535 6e3488e9 Phil Davis
		} else {
1536 afe62c2b Phil Davis
			// It was a click, swap the state.
1537
			showadvntp = !showadvntp;
1538 6e3488e9 Phil Davis
		}
1539 b5f6e690 Stephen Beaver
1540 afe62c2b Phil Davis
		hideInput('ntp1', !showadvntp);
1541
		hideInput('ntp2', !showadvntp);
1542 b5f6e690 Stephen Beaver
1543 afe62c2b Phil Davis
		if (showadvntp) {
1544
			text = "<?=gettext('Hide Advanced');?>";
1545
		} else {
1546
			text = "<?=gettext('Display Advanced');?>";
1547
		}
1548
		$('#btnadvntp').html('<i class="fa fa-cog"></i> ' + text);
1549 b5f6e690 Stephen Beaver
	}
1550
1551
	$('#btnadvntp').click(function(event) {
1552
		show_advntp();
1553
	});
1554
1555 afe62c2b Phil Davis
	// Show advanced TFTP options ======================================================================================
1556
	var showadvtftp = false;
1557 b5f6e690 Stephen Beaver
1558 afe62c2b Phil Davis
	function show_advtftp(ispageload) {
1559
		var text;
1560
		// On page load decide the initial state based on the data.
1561
		if (ispageload) {
1562 8f8682f7 Phil Davis
<?php
1563 afe62c2b Phil Davis
			if (empty($pconfig['tftp'])) {
1564
				$showadv = false;
1565
			} else {
1566
				$showadv = true;
1567
			}
1568
?>
1569
			showadvtftp = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1570 6e3488e9 Phil Davis
		} else {
1571 afe62c2b Phil Davis
			// It was a click, swap the state.
1572
			showadvtftp = !showadvtftp;
1573 6e3488e9 Phil Davis
		}
1574 b5f6e690 Stephen Beaver
1575 afe62c2b Phil Davis
		hideInput('tftp', !showadvtftp);
1576 b5f6e690 Stephen Beaver
1577 afe62c2b Phil Davis
		if (showadvtftp) {
1578
			text = "<?=gettext('Hide Advanced');?>";
1579
		} else {
1580
			text = "<?=gettext('Display Advanced');?>";
1581
		}
1582
		$('#btnadvtftp').html('<i class="fa fa-cog"></i> ' + text);
1583 b5f6e690 Stephen Beaver
	}
1584
1585
	$('#btnadvtftp').click(function(event) {
1586
		show_advtftp();
1587
	});
1588
1589 afe62c2b Phil Davis
	// Show advanced LDAP options ======================================================================================
1590 b5f6e690 Stephen Beaver
	var showadvldap = false;
1591
1592 afe62c2b Phil Davis
	function show_advldap(ispageload) {
1593
		var text;
1594
		// On page load decide the initial state based on the data.
1595
		if (ispageload) {
1596 8f8682f7 Phil Davis
<?php
1597 afe62c2b Phil Davis
			if (empty($pconfig['ldap'])) {
1598
				$showadv = false;
1599
			} else {
1600
				$showadv = true;
1601
			}
1602
?>
1603
			showadvldap = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1604 6e3488e9 Phil Davis
		} else {
1605 afe62c2b Phil Davis
			// It was a click, swap the state.
1606
			showadvldap = !showadvldap;
1607 6e3488e9 Phil Davis
		}
1608 b5f6e690 Stephen Beaver
1609 afe62c2b Phil Davis
		hideInput('ldap', !showadvldap);
1610 b5f6e690 Stephen Beaver
1611 afe62c2b Phil Davis
		if (showadvldap) {
1612
			text = "<?=gettext('Hide Advanced');?>";
1613
		} else {
1614
			text = "<?=gettext('Display Advanced');?>";
1615
		}
1616
		$('#btnadvldap').html('<i class="fa fa-cog"></i> ' + text);
1617 b5f6e690 Stephen Beaver
	}
1618
1619
	$('#btnadvldap').click(function(event) {
1620
		show_advldap();
1621
	});
1622
1623 eef93144 Jared Dillard
	// Show advanced additional opts options ===========================================================================
1624 b5f6e690 Stephen Beaver
	var showadvopts = false;
1625
1626 afe62c2b Phil Davis
	function show_advopts(ispageload) {
1627
		var text;
1628
		// On page load decide the initial state based on the data.
1629
		if (ispageload) {
1630 8f8682f7 Phil Davis
<?php
1631 afe62c2b Phil Davis
			if (empty($pconfig['numberoptions']) ||
1632
			    (empty($pconfig['numberoptions']['item'][0]['number']) && (empty($pconfig['numberoptions']['item'][0]['value'])))) {
1633
				$showadv = false;
1634
			} else {
1635
				$showadv = true;
1636
			}
1637
?>
1638
			showadvopts = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1639 6e3488e9 Phil Davis
		} else {
1640 afe62c2b Phil Davis
			// It was a click, swap the state.
1641
			showadvopts = !showadvopts;
1642 6e3488e9 Phil Davis
		}
1643 b5f6e690 Stephen Beaver
1644 afe62c2b Phil Davis
		hideClass('adnlopts', !showadvopts);
1645 b5f6e690 Stephen Beaver
1646 afe62c2b Phil Davis
		if (showadvopts) {
1647
			text = "<?=gettext('Hide Advanced');?>";
1648
		} else {
1649
			text = "<?=gettext('Display Advanced');?>";
1650
		}
1651
		$('#btnadvopts').html('<i class="fa fa-cog"></i> ' + text);
1652 b5f6e690 Stephen Beaver
	}
1653
1654
	$('#btnadvopts').click(function(event) {
1655
		show_advopts();
1656
	});
1657
1658 68de2169 Phil Davis
	// Show advanced Network Booting options ===========================================================================
1659
	var showadvnwkboot = false;
1660
1661
	function show_advnwkboot(ispageload) {
1662
		var text;
1663
		// On page load decide the initial state based on the data.
1664
		if (ispageload) {
1665
<?php
1666
			if (empty($pconfig['netboot'])) {
1667
				$showadv = false;
1668
			} else {
1669
				$showadv = true;
1670
			}
1671
?>
1672
			showadvnwkboot = <?php if ($showadv) {echo 'true';} else {echo 'false';} ?>;
1673
		} else {
1674
			// It was a click, swap the state.
1675
			showadvnwkboot = !showadvnwkboot;
1676
		}
1677
1678
		hideCheckbox('netboot', !showadvnwkboot);
1679
		hideInput('nextserver', !showadvnwkboot);
1680
		hideInput('filename', !showadvnwkboot);
1681
		hideInput('filename32', !showadvnwkboot);
1682
		hideInput('filename64', !showadvnwkboot);
1683
		hideInput('rootpath', !showadvnwkboot);
1684
1685
		if (showadvnwkboot) {
1686
			text = "<?=gettext('Hide Advanced');?>";
1687
		} else {
1688
			text = "<?=gettext('Display Advanced');?>";
1689
		}
1690
		$('#btnadvnwkboot').html('<i class="fa fa-cog"></i> ' + text);
1691
	}
1692
1693
	$('#btnadvnwkboot').click(function(event) {
1694
		show_advnwkboot();
1695
	});
1696
1697 eef93144 Jared Dillard
	// ---------- On initial page load ------------------------------------------------------------
1698
1699 afe62c2b Phil Davis
	show_advdns(true);
1700
	show_advmac(true);
1701
	show_advntp(true);
1702
	show_advtftp(true);
1703
	show_advldap(true);
1704
	show_advopts(true);
1705 68de2169 Phil Davis
	show_advnwkboot(true);
1706 0bc61baa Stephen Beaver
1707
	// Suppress "Delete row" button if there are fewer than two rows
1708
	checkLastRow();
1709 b5f6e690 Stephen Beaver
});
1710 180db186 Colin Fleming
//]]>
1711 5b237745 Scott Ullrich
</script>
1712 b5f6e690 Stephen Beaver
1713 3c9befb9 Chris Buechler
<?php include("foot.inc");