Project

General

Profile

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