Project

General

Profile

Download (50.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	firewall_rules_edit.php
5
	part of pfSense (https://www.pfsense.org)
6
	Copyright (C) 2005 Scott Ullrich (sullrich@gmail.com)
7
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
8

    
9
	originally part of m0n0wall (http://m0n0.ch/wall)
10
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
11
	All rights reserved.
12

    
13
	Redistribution and use in source and binary forms, with or without
14
	modification, are permitted provided that the following conditions are met:
15

    
16
	1. Redistributions of source code must retain the above copyright notice,
17
	   this list of conditions and the following disclaimer.
18

    
19
	2. Redistributions in binary form must reproduce the above copyright
20
	   notice, this list of conditions and the following disclaimer in the
21
	   documentation and/or other materials provided with the distribution.
22

    
23
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
	POSSIBILITY OF SUCH DAMAGE.
33
*/
34
/*
35
	pfSense_MODULE:	filter
36
*/
37

    
38
##|+PRIV
39
##|*IDENT=page-firewall-rules-edit
40
##|*NAME=Firewall: Rules: Edit page
41
##|*DESCR=Allow access to the 'Firewall: Rules: Edit' page.
42
##|*MATCH=firewall_rules_edit.php*
43
##|-PRIV
44

    
45
require("guiconfig.inc");
46
require_once("filter.inc");
47
require("shaper.inc");
48

    
49
$referer = (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/firewall_rules.php');
50

    
51
function is_posnumericint($arg) {
52
	// Note that to be safe we do not allow any leading zero - "01", "007"
53
	return (is_numericint($arg) && $arg[0] != '0' && $arg > 0);
54
}
55

    
56
function is_aoadv_used($rule_config) {
57
	// Note that the user could set "tag" or "tagged" to the string "0", which is valid but empty().
58
	// And if the user enters "0" in other fields, we want to present an error message, and keep the Advanced Options section open.
59
	if ((isset($rule_config['allowopts'])) ||
60
		(isset($rule_config['disablereplyto'])) ||
61
		($rule_config['tag'] != "") ||
62
		($rule_config['tagged'] != "") ||
63
		($rule_config['max'] != "") ||
64
		($rule_config['max-src-nodes'] != "") ||
65
		($rule_config['max-src-conn'] != "") ||
66
		($rule_config['max-src-states'] != "") ||
67
		($rule_config['max-src-conn-rate'] != "") ||
68
		($rule_config['max-src-conn-rates'] != "") ||
69
		($rule_config['statetimeout'] != ""))
70
		return true;
71
	return false;
72
}
73

    
74
$ostypes = array();
75
exec('/sbin/pfctl -s osfp | /usr/bin/tr \'\t\' \' \'', $ostypes);
76

    
77
if (count($ostypes) > 2) {
78
	// Remove header rows from pfctl output
79
	array_shift($ostypes);
80
	array_shift($ostypes);
81
} else {
82
	// Fall back to a default list
83
	$ostypes = array(
84
		"AIX",
85
		"Linux",
86
		"FreeBSD",
87
		"NetBSD",
88
		"OpenBSD",
89
		"Solaris",
90
		"MacOS",
91
		"Windows",
92
		"Novell",
93
		"NMAP"
94
	);
95
}
96

    
97
$specialsrcdst = explode(" ", "any (self) pptp pppoe l2tp openvpn");
98
$ifdisp = get_configured_interface_with_descr();
99
foreach ($ifdisp as $kif => $kdescr) {
100
	$specialsrcdst[] = "{$kif}";
101
	$specialsrcdst[] = "{$kif}ip";
102
}
103

    
104
if (!is_array($config['filter']['rule'])) {
105
	$config['filter']['rule'] = array();
106
}
107
filter_rules_sort();
108
$a_filter = &$config['filter']['rule'];
109

    
110
if (is_numericint($_GET['id']))
111
	$id = $_GET['id'];
112
if (isset($_POST['id']) && is_numericint($_POST['id']))
113
	$id = $_POST['id'];
114

    
115
if (is_numericint($_GET['after']) || $_GET['after'] == "-1")
116
	$after = $_GET['after'];
117
if (isset($_POST['after']) && (is_numericint($_POST['after']) || $_POST['after'] == "-1"))
118
	$after = $_POST['after'];
119

    
120
if (isset($_GET['dup']) && is_numericint($_GET['dup'])) {
121
		$id = $_GET['dup'];
122
		$after = $_GET['dup'];
123
}
124

    
125
if (isset($id) && $a_filter[$id]) {
126
	$pconfig['interface'] = $a_filter[$id]['interface'];
127

    
128
	if (isset($a_filter[$id]['id']))
129
		$pconfig['ruleid'] = $a_filter[$id]['id'];
130

    
131
	if ( isset($a_filter[$id]['created']) && is_array($a_filter[$id]['created']) )
132
		$pconfig['created'] = $a_filter[$id]['created'];
133

    
134
	if ( isset($a_filter[$id]['updated']) && is_array($a_filter[$id]['updated']) )
135
		$pconfig['updated'] = $a_filter[$id]['updated'];
136

    
137
	if (!isset($a_filter[$id]['type']))
138
		$pconfig['type'] = "pass";
139
	else
140
		$pconfig['type'] = $a_filter[$id]['type'];
141

    
142
	if (isset($a_filter[$id]['floating']) || $if == "FloatingRules") {
143
		$pconfig['floating'] = $a_filter[$id]['floating'];
144
		if (isset($a_filter[$id]['interface']) && $a_filter[$id]['interface'] != "")
145
			$pconfig['interface'] = $a_filter[$id]['interface'];
146
	}
147

    
148
	if (isset($a_filter['floating']))
149
		$pconfig['floating'] = "yes";
150

    
151
	if (isset($a_filter[$id]['direction']))
152
		$pconfig['direction'] = $a_filter[$id]['direction'];
153

    
154
	if (isset($a_filter[$id]['ipprotocol']))
155
		$pconfig['ipprotocol'] = $a_filter[$id]['ipprotocol'];
156

    
157
	if (isset($a_filter[$id]['protocol']))
158
		$pconfig['proto'] = $a_filter[$id]['protocol'];
159
	else
160
		$pconfig['proto'] = "any";
161

    
162
	if ($a_filter[$id]['protocol'] == "icmp")
163
		$pconfig['icmptype'] = $a_filter[$id]['icmptype'];
164

    
165
	address_to_pconfig($a_filter[$id]['source'], $pconfig['src'],
166
		$pconfig['srcmask'], $pconfig['srcnot'],
167
		$pconfig['srcbeginport'], $pconfig['srcendport']);
168

    
169
	if($a_filter[$id]['os'] != "")
170
		$pconfig['os'] = $a_filter[$id]['os'];
171

    
172
	address_to_pconfig($a_filter[$id]['destination'], $pconfig['dst'],
173
		$pconfig['dstmask'], $pconfig['dstnot'],
174
		$pconfig['dstbeginport'], $pconfig['dstendport']);
175

    
176
	if ($a_filter[$id]['dscp'] != "")
177
		$pconfig['dscp'] = $a_filter[$id]['dscp'];
178

    
179
	$pconfig['disabled'] = isset($a_filter[$id]['disabled']);
180
	$pconfig['log'] = isset($a_filter[$id]['log']);
181
	$pconfig['descr'] = $a_filter[$id]['descr'];
182

    
183
	if (isset($a_filter[$id]['tcpflags_any']))
184
		$pconfig['tcpflags_any'] = true;
185
	else {
186
		if (isset($a_filter[$id]['tcpflags1']) && $a_filter[$id]['tcpflags1'] != "")
187
			$pconfig['tcpflags1'] = $a_filter[$id]['tcpflags1'];
188
		if (isset($a_filter[$id]['tcpflags2']) && $a_filter[$id]['tcpflags2'] != "")
189
			$pconfig['tcpflags2'] = $a_filter[$id]['tcpflags2'];
190
	}
191

    
192
	if (isset($a_filter[$id]['tag']) && $a_filter[$id]['tag'] != "")
193
		$pconfig['tag'] = $a_filter[$id]['tag'];
194
	if (isset($a_filter[$id]['tagged']) && $a_filter[$id]['tagged'] != "")
195
		$pconfig['tagged'] = $a_filter[$id]['tagged'];
196
	if (isset($a_filter[$id]['quick']) && $a_filter[$id]['quick'])
197
		$pconfig['quick'] = $a_filter[$id]['quick'];
198
	if (isset($a_filter[$id]['allowopts']))
199
		$pconfig['allowopts'] = true;
200
	if (isset($a_filter[$id]['disablereplyto']))
201
		$pconfig['disablereplyto'] = true;
202

    
203
	/* advanced */
204
	$pconfig['max'] = $a_filter[$id]['max'];
205
	$pconfig['max-src-nodes'] = $a_filter[$id]['max-src-nodes'];
206
	$pconfig['max-src-conn'] = $a_filter[$id]['max-src-conn'];
207
	$pconfig['max-src-states'] = $a_filter[$id]['max-src-states'];
208
	$pconfig['statetype'] = $a_filter[$id]['statetype'];
209
	$pconfig['statetimeout'] = $a_filter[$id]['statetimeout'];
210
	$pconfig['nopfsync'] = isset($a_filter[$id]['nopfsync']);
211

    
212
	/* advanced - nosync */
213
	$pconfig['nosync'] = isset($a_filter[$id]['nosync']);
214

    
215
	/* advanced - new connection per second banning*/
216
	$pconfig['max-src-conn-rate'] = $a_filter[$id]['max-src-conn-rate'];
217
	$pconfig['max-src-conn-rates'] = $a_filter[$id]['max-src-conn-rates'];
218

    
219
	/* Multi-WAN next-hop support */
220
	$pconfig['gateway'] = $a_filter[$id]['gateway'];
221

    
222
	/* Shaper support */
223
	$pconfig['defaultqueue'] = (($a_filter[$id]['ackqueue'] == "none") ? '' : $a_filter[$id]['defaultqueue']);
224
	$pconfig['ackqueue'] = (($a_filter[$id]['ackqueue'] == "none") ? '' : $a_filter[$id]['ackqueue']);
225
	$pconfig['dnpipe'] = (($a_filter[$id]['dnpipe'] == "none") ? '' : $a_filter[$id]['dnpipe']);
226
	$pconfig['pdnpipe'] = (($a_filter[$id]['pdnpipe'] == "none") ? '' : $a_filter[$id]['pdnpipe']);
227
	$pconfig['l7container'] = (($a_filter[$id]['l7container'] == "none") ? '' : $a_filter[$id]['l7container']);
228

    
229
	//schedule support
230
	$pconfig['sched'] = (($a_filter[$id]['sched'] == "none") ? '' : $a_filter[$id]['sched']);
231
	$pconfig['vlanprio'] = (($a_filter[$id]['vlanprio'] == "none") ? '' : $a_filter[$id]['vlanprio']);
232
	$pconfig['vlanprioset'] = (($a_filter[$id]['vlanprioset'] == "none") ? '' : $a_filter[$id]['vlanprioset']);
233
	if (!isset($_GET['dup']) || !is_numericint($_GET['dup']))
234
		$pconfig['associated-rule-id'] = $a_filter[$id]['associated-rule-id'];
235

    
236
	$pconfig['tracker'] = $a_filter[$id]['tracker'];
237

    
238
} else {
239
	/* defaults */
240
	if ($_GET['if'])
241
		$pconfig['interface'] = $_GET['if'];
242
	$pconfig['type'] = "pass";
243
	$pconfig['src'] = "any";
244
	$pconfig['dst'] = "any";
245
}
246
/* Allow the FloatingRules to work */
247
$if = $pconfig['interface'];
248

    
249
if (isset($_GET['dup']) && is_numericint($_GET['dup']))
250
	unset($id);
251

    
252
read_altq_config(); /* XXX: */
253
$qlist =& get_unique_queue_list();
254
read_dummynet_config(); /* XXX: */
255
$dnqlist =& get_unique_dnqueue_list();
256
read_layer7_config();
257
$l7clist =& get_l7_unique_list();
258
$a_gatewaygroups = return_gateway_groups_array();
259

    
260
if ($_POST) {
261
	unset($input_errors);
262

    
263
	if( isset($a_filter[$id]['associated-rule-id']) ) {
264
		$_POST['proto'] = $pconfig['proto'];
265
		if ($pconfig['proto'] == "icmp")
266
			$_POST['icmptype'] = $pconfig['icmptype'];
267
	}
268

    
269
	if (($_POST['ipprotocol'] != "") && ($_POST['gateway'] != "")) {
270
		if(is_array($config['gateways']['gateway_group'])) {
271
			foreach($config['gateways']['gateway_group'] as $gw_group) {
272
				if($gw_group['name'] == $_POST['gateway']) {
273
					$family = $a_gatewaygroups[$_POST['gateway']]['ipprotocol'];
274
					if($_POST['ipprotocol'] == $family) {
275
						continue;
276
					}
277
					if(($_POST['ipprotocol'] == "inet46") && ($_POST['ipprotocol'] != $family)) {
278
						$input_errors[] = gettext("You can not assign a gateway to a rule that applies to IPv4 and IPv6");
279
					}
280
					if(($_POST['ipprotocol'] == "inet6") && ($_POST['ipprotocol'] != $family)) {
281
						$input_errors[] = gettext("You can not assign an IPv4 gateway group on IPv6 Address Family rule");
282
					}
283
					if(($_POST['ipprotocol'] == "inet") && ($_POST['ipprotocol'] != $family)) {
284
						$input_errors[] = gettext("You can not assign an IPv6 gateway group on IPv4 Address Family rule");
285
					}
286
				}
287
			}
288
		}
289
	}
290
	if (($_POST['ipprotocol'] != "") && ($_POST['gateway'] != "") && (is_ipaddr(lookup_gateway_ip_by_name($_POST['gateway'])))) {
291
		if(($_POST['ipprotocol'] == "inet46") && ($_POST['gateway'] != "")) {
292
			$input_errors[] = gettext("You can not assign a gateway to a rule that applies to IPv4 and IPv6");
293
		}
294
		if(($_POST['ipprotocol'] == "inet6") && (!is_ipaddrv6(lookup_gateway_ip_by_name($_POST['gateway'])))) {
295
			$input_errors[] = gettext("You can not assign an IPv4 Gateway to an IPv6 Filter rule");
296
		}
297
		if(($_POST['ipprotocol'] == "inet") && (!is_ipaddrv4(lookup_gateway_ip_by_name($_POST['gateway'])))) {
298
			$input_errors[] = gettext("You can not assign an IPv6 Gateway to an IPv4 Filter rule");
299
		}
300
	}
301

    
302
	if (($_POST['proto'] != "tcp") && ($_POST['proto'] != "udp") && ($_POST['proto'] != "tcp/udp") && ($_POST['proto'] != "icmp")) {
303
		if($_POST['ipprotocol'] == "inet46")
304
			$input_errors[] =  gettext("You can not assign a protocol other than ICMP, TCP, UDP or TCP/UDP to a rule that applies to IPv4 and IPv6");
305
	}
306
	if (($_POST['proto'] == "icmp") && ($_POST['icmptype'] != "")){
307
		if($_POST['ipprotocol'] == "inet46")
308
			$input_errors[] =  gettext("You can not assign a ICMP type to a rule that applies to IPv4 and IPv6");
309
	}
310

    
311
	if (($_POST['proto'] != "tcp") && ($_POST['proto'] != "udp") && ($_POST['proto'] != "tcp/udp")) {
312
		$_POST['srcbeginport'] = 0;
313
		$_POST['srcendport'] = 0;
314
		$_POST['dstbeginport'] = 0;
315
		$_POST['dstendport'] = 0;
316
	} else {
317
		if ($_POST['srcbeginport_cust'] && !$_POST['srcbeginport'])
318
			$_POST['srcbeginport'] = trim($_POST['srcbeginport_cust']);
319
		if ($_POST['srcendport_cust'] && !$_POST['srcendport'])
320
			$_POST['srcendport'] = trim($_POST['srcendport_cust']);
321
		if ($_POST['srcbeginport'] == "any") {
322
			$_POST['srcbeginport'] = 0;
323
			$_POST['srcendport'] = 0;
324
		} else {
325
			if (!$_POST['srcendport'])
326
				$_POST['srcendport'] = $_POST['srcbeginport'];
327
		}
328
		if ($_POST['srcendport'] == "any")
329
			$_POST['srcendport'] = $_POST['srcbeginport'];
330

    
331
		if ($_POST['dstbeginport_cust'] && !$_POST['dstbeginport'])
332
			$_POST['dstbeginport'] = trim($_POST['dstbeginport_cust']);
333
		if ($_POST['dstendport_cust'] && !$_POST['dstendport'])
334
			$_POST['dstendport'] = trim($_POST['dstendport_cust']);
335

    
336
		if ($_POST['dstbeginport'] == "any") {
337
			$_POST['dstbeginport'] = 0;
338
			$_POST['dstendport'] = 0;
339
		} else {
340
			if (!$_POST['dstendport'])
341
				$_POST['dstendport'] = $_POST['dstbeginport'];
342
		}
343
		if ($_POST['dstendport'] == "any")
344
			$_POST['dstendport'] = $_POST['dstbeginport'];
345
	}
346

    
347
	if (is_specialnet($_POST['srctype'])) {
348
		$_POST['src'] = $_POST['srctype'];
349
		$_POST['srcmask'] = 0;
350
	} else if ($_POST['srctype'] == "single") {
351
		if (is_ipaddrv6($_POST['src']))
352
			$_POST['srcmask'] = 128;
353
		else
354
			$_POST['srcmask'] = 32;
355
	}
356
	if (is_specialnet($_POST['dsttype'])) {
357
		$_POST['dst'] = $_POST['dsttype'];
358
		$_POST['dstmask'] = 0;
359
	}  else if ($_POST['dsttype'] == "single") {
360
		if (is_ipaddrv6($_POST['dst']))
361
			$_POST['dstmask'] = 128;
362
		else
363
			$_POST['dstmask'] = 32;
364
	}
365

    
366
	$pconfig = $_POST;
367

    
368
	/* input validation */
369
	$reqdfields = explode(" ", "type proto");
370
	if ( isset($a_filter[$id]['associated-rule-id'])===false ) {
371
		$reqdfields[] = "src";
372
		$reqdfields[] = "dst";
373
	}
374
	$reqdfieldsn = explode(",", "Type,Protocol");
375
	if ( isset($a_filter[$id]['associated-rule-id'])===false ) {
376
		$reqdfieldsn[] = "Source";
377
		$reqdfieldsn[] = "Destination";
378
	}
379

    
380
	if($_POST['statetype'] == "modulate state" or $_POST['statetype'] == "synproxy state") {
381
		if( $_POST['proto'] != "tcp" )
382
			$input_errors[] = sprintf(gettext("%s is only valid with protocol TCP."),$_POST['statetype']);
383
		if(($_POST['statetype'] == "synproxy state") && ($_POST['gateway'] != ""))
384
			$input_errors[] = sprintf(gettext("%s is only valid if the gateway is set to 'default'."),$_POST['statetype']);
385
	}
386

    
387
	if ( isset($a_filter[$id]['associated-rule-id'])===false &&
388
	(!(is_specialnet($_POST['srctype']) || ($_POST['srctype'] == "single"))) ) {
389
		$reqdfields[] = "srcmask";
390
		$reqdfieldsn[] = "Source bit count";
391
	}
392
	if ( isset($a_filter[$id]['associated-rule-id'])===false &&
393
	(!(is_specialnet($_POST['dsttype']) || ($_POST['dsttype'] == "single"))) ) {
394
		$reqdfields[] = "dstmask";
395
		$reqdfieldsn[] = gettext("Destination bit count");
396
	}
397

    
398
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
399

    
400
	if (!$_POST['srcbeginport']) {
401
		$_POST['srcbeginport'] = 0;
402
		$_POST['srcendport'] = 0;
403
	}
404
	if (!$_POST['dstbeginport']) {
405
		$_POST['dstbeginport'] = 0;
406
		$_POST['dstendport'] = 0;
407
	}
408

    
409
	if ($_POST['srcbeginport'] && !is_portoralias($_POST['srcbeginport']))
410
		$input_errors[] = sprintf(gettext("%s is not a valid start source port. It must be a port alias or integer between 1 and 65535."),$_POST['srcbeginposrt']);
411
	if ($_POST['srcendport'] && !is_portoralias($_POST['srcendport']))
412
			$input_errors[] = sprintf(gettext("%s  is not a valid end source port. It must be a port alias or integer between 1 and 65535."),$_POST['srcendport']);
413
	if ($_POST['dstbeginport'] && !is_portoralias($_POST['dstbeginport']))
414
			$input_errors[] = sprintf(gettext("%s is not a valid start destination port. It must be a port alias or integer between 1 and 65535."),$_POST['dstbeginport']);
415
	if ($_POST['dstendport'] && !is_portoralias($_POST['dstendport']))
416
			$input_errors[] = sprintf(gettext("%s is not a valid end destination port. It must be a port alias or integer between 1 and 65535."),$_POST['dstendport']);
417
	if ( !$_POST['srcbeginport_cust'] && $_POST['srcendport_cust'])
418
		if (is_alias($_POST['srcendport_cust']))
419
			$input_errors[] = 'If you put port alias in Source port range to: field you must put the same port alias in from: field';
420
	if ( $_POST['srcbeginport_cust'] && $_POST['srcendport_cust']){
421
		if (is_alias($_POST['srcendport_cust']) && is_alias($_POST['srcendport_cust']) && $_POST['srcbeginport_cust'] != $_POST['srcendport_cust'])
422
			$input_errors[] = 'The same port alias must be used in Source port range from: and to: fields';
423
		if ((is_alias($_POST['srcbeginport_cust']) && (!is_alias($_POST['srcendport_cust']) && $_POST['srcendport_cust']!='')) ||
424
			((!is_alias($_POST['srcbeginport_cust']) && $_POST['srcbeginport_cust']!='') && is_alias($_POST['srcendport_cust'])))
425
			$input_errors[] = 'You cannot specify numbers and port aliases at the same time in Source port range from: and to: field';
426
	}
427
	if ( !$_POST['dstbeginport_cust'] && $_POST['dstendport_cust'])
428
		if (is_alias($_POST['dstendport_cust']))
429
			$input_errors[] = 'If you put port alias in Destination port range to: field you must put the same port alias in from: field';
430
	if ( $_POST['dstbeginport_cust'] && $_POST['dstendport_cust']){
431
		if (is_alias($_POST['dstendport_cust']) && is_alias($_POST['dstendport_cust']) && $_POST['dstbeginport_cust'] != $_POST['dstendport_cust'])
432
			$input_errors[] = 'The same port alias must be used in Destination port range from: and to: fields';
433
		if ((is_alias($_POST['dstbeginport_cust']) && (!is_alias($_POST['dstendport_cust']) && $_POST['dstendport_cust']!='')) ||
434
			((!is_alias($_POST['dstbeginport_cust']) && $_POST['dstbeginport_cust']!='') && is_alias($_POST['dstendport_cust'])))
435
			$input_errors[] = 'You cannot specify numbers and port aliases at the same time in Destination port range from: and to: field';
436
	}
437

    
438
	if ($_POST['src'])
439
		$_POST['src'] = trim($_POST['src']);
440
	if ($_POST['dst'])
441
		$_POST['dst'] = trim($_POST['dst']);
442

    
443
	/* if user enters an alias and selects "network" then disallow. */
444
	if($_POST['srctype'] == "network") {
445
		if(is_alias($_POST['src']))
446
			$input_errors[] = gettext("You must specify single host or alias for alias entries.");
447
	}
448
	if($_POST['dsttype'] == "network") {
449
		if(is_alias($_POST['dst']))
450
			$input_errors[] = gettext("You must specify single host or alias for alias entries.");
451
	}
452

    
453
	if (!is_specialnet($_POST['srctype'])) {
454
		if (($_POST['src'] && !is_ipaddroralias($_POST['src']))) {
455
			$input_errors[] = sprintf(gettext("%s is not a valid source IP address or alias."),$_POST['src']);
456
		}
457
		if (($_POST['srcmask'] && !is_numericint($_POST['srcmask']))) {
458
			$input_errors[] = gettext("A valid source bit count must be specified.");
459
		}
460
	}
461
	if (!is_specialnet($_POST['dsttype'])) {
462
		if (($_POST['dst'] && !is_ipaddroralias($_POST['dst']))) {
463
			$input_errors[] = sprintf(gettext("%s is not a valid destination IP address or alias."),$_POST['dst']);
464
		}
465
		if (($_POST['dstmask'] && !is_numericint($_POST['dstmask']))) {
466
			$input_errors[] = gettext("A valid destination bit count must be specified.");
467
		}
468
	}
469
	if((is_ipaddr($_POST['src']) && is_ipaddr($_POST['dst']))) {
470
		if(!validate_address_family($_POST['src'], $_POST['dst']))
471
			$input_errors[] = sprintf(gettext("The Source IP address %s Address Family differs from the destination %s."), $_POST['src'], $_POST['dst']);
472
		if((is_ipaddrv6($_POST['src']) || is_ipaddrv6($_POST['dst'])) && ($_POST['ipprotocol'] == "inet"))
473
			$input_errors[] = gettext("You can not use IPv6 addresses in IPv4 rules.");
474
		if((is_ipaddrv4($_POST['src']) || is_ipaddrv4($_POST['dst'])) && ($_POST['ipprotocol'] == "inet6"))
475
			$input_errors[] = gettext("You can not use IPv4 addresses in IPv6 rules.");
476
	}
477

    
478
	if((is_ipaddr($_POST['src']) || is_ipaddr($_POST['dst'])) && ($_POST['ipprotocol'] == "inet46"))
479
		$input_errors[] = gettext("You can not use a IPv4 or IPv6 address in combined IPv4 + IPv6 rules.");
480

    
481
	if ($_POST['srcbeginport'] > $_POST['srcendport']) {
482
		/* swap */
483
		$tmp = $_POST['srcendport'];
484
		$_POST['srcendport'] = $_POST['srcbeginport'];
485
		$_POST['srcbeginport'] = $tmp;
486
	}
487
	if ($_POST['dstbeginport'] > $_POST['dstendport']) {
488
		/* swap */
489
		$tmp = $_POST['dstendport'];
490
		$_POST['dstendport'] = $_POST['dstbeginport'];
491
		$_POST['dstbeginport'] = $tmp;
492
	}
493
	if ($_POST['os']) {
494
		if( $_POST['proto'] != "tcp" )
495
			$input_errors[] = gettext("OS detection is only valid with protocol TCP.");
496
		if (!in_array($_POST['os'], $ostypes))
497
			$input_errors[] = gettext("Invalid OS detection selection. Please select a valid OS.");
498
	}
499

    
500
	if ($_POST['ackqueue'] != "") {
501
		if ($_POST['defaultqueue'] == "" )
502
			$input_errors[] = gettext("You have to select a queue when you select an acknowledge queue too.");
503
		else if ($_POST['ackqueue'] == $_POST['defaultqueue'])
504
			$input_errors[] = gettext("Acknowledge queue and Queue cannot be the same.");
505
	}
506
	if (isset($_POST['floating']) && $_POST['pdnpipe'] != "" && (empty($_POST['direction']) || $_POST['direction'] == "any"))
507
		$input_errors[] = gettext("You can not use limiters in Floating rules without choosing a direction.");
508
	if (isset($_POST['floating']) && $_POST['gateway'] != "" && (empty($_POST['direction']) || $_POST['direction'] == "any"))
509
		$input_errors[] = gettext("You can not use gateways in Floating rules without choosing a direction.");
510
	if ($_POST['pdnpipe'] && $_POST['pdnpipe'] != "") {
511
		if ($_POST['dnpipe'] == "" )
512
			$input_errors[] = gettext("You must select a queue for the In direction before selecting one for Out too.");
513
		else if ($_POST['pdnpipe'] == $_POST['dnpipe'])
514
			$input_errors[] = gettext("In and Out Queue cannot be the same.");
515
		else if ($dnqlist[$_POST['pdnpipe']][0] == "?" && $dnqlist[$_POST['dnpipe']][0] != "?")
516
			$input_errors[] = gettext("You cannot select one queue and one virtual interface for IN and Out. Both must be from the same type.");
517
		else if ($dnqlist[$_POST['dnpipe']][0] == "?" && $dnqlist[$_POST['pdnpipe']][0] != "?")
518
			$input_errors[] = gettext("You cannot select one queue and one virtual interface for IN and Out. Both must be from the same type.");
519
		if ($_POST['direction'] == "out" && empty($_POST['gateway']))
520
			$input_errors[] = gettext("Please select a gateway, normally the interface selected gateway, so the limiters work correctly");
521
	}
522
	if( !empty($_POST['ruleid']) && !ctype_digit($_POST['ruleid']))
523
		$input_errors[] = gettext('ID must be an integer');
524
	if($_POST['l7container'] && $_POST['l7container'] != "") {
525
		if(!($_POST['proto'] == "tcp" || $_POST['proto'] == "udp" || $_POST['proto'] == "tcp/udp"))
526
			$input_errors[] = gettext("You can only select a layer7 container for TCP and/or UDP protocols");
527
		if ($_POST['type'] != "pass")
528
			$input_errors[] = gettext("You can only select a layer7 container for Pass type rules.");
529
	}
530

    
531
	if (!in_array($_POST['proto'], array("tcp","tcp/udp"))) {
532
		if (!empty($_POST['max-src-conn']))
533
			$input_errors[] = gettext("You can only specify the maximum number of established connections per host (advanced option) for TCP protocol.");
534
		if (!empty($_POST['max-src-conn-rate']) || !empty($_POST['max-src-conn-rates']))
535
			$input_errors[] = gettext("You can only specify the maximum new connections per host / per second(s) (advanced option) for TCP protocol.");
536
		if (!empty($_POST['statetimeout']))
537
			$input_errors[] = gettext("You can only specify the state timeout (advanced option) for TCP protocol.");
538
	}
539

    
540
	if ($_POST['type'] != "pass") {
541
		if (!empty($_POST['max']))
542
			$input_errors[] = gettext("You can only specify the maximum state entries (advanced option) for Pass type rules.");
543
		if (!empty($_POST['max-src-nodes']))
544
			$input_errors[] = gettext("You can only specify the maximum number of unique source hosts (advanced option) for Pass type rules.");
545
		if (!empty($_POST['max-src-conn']))
546
			$input_errors[] = gettext("You can only specify the maximum number of established connections per host (advanced option) for Pass type rules.");
547
		if (!empty($_POST['max-src-states']))
548
			$input_errors[] = gettext("You can only specify the maximum state entries per host (advanced option) for Pass type rules.");
549
		if (!empty($_POST['max-src-conn-rate']) || !empty($_POST['max-src-conn-rates']))
550
			$input_errors[] = gettext("You can only specify the maximum new connections per host / per second(s) (advanced option) for Pass type rules.");
551
		if (!empty($_POST['statetimeout']))
552
			$input_errors[] = gettext("You can only specify the state timeout (advanced option) for Pass type rules.");
553
	}
554

    
555
	if (($_POST['statetype'] == "none") && (empty($_POST['l7container']))) {
556
		if (!empty($_POST['max']))
557
			$input_errors[] = gettext("You cannot specify the maximum state entries (advanced option) if statetype is none and no L7 container is selected.");
558
		if (!empty($_POST['max-src-nodes']))
559
			$input_errors[] = gettext("You cannot specify the maximum number of unique source hosts (advanced option) if statetype is none and no L7 container is selected.");
560
		if (!empty($_POST['max-src-conn']))
561
			$input_errors[] = gettext("You cannot specify the maximum number of established connections per host (advanced option) if statetype is none and no L7 container is selected.");
562
		if (!empty($_POST['max-src-states']))
563
			$input_errors[] = gettext("You cannot specify the maximum state entries per host (advanced option) if statetype is none and no L7 container is selected.");
564
		if (!empty($_POST['max-src-conn-rate']) || !empty($_POST['max-src-conn-rates']))
565
			$input_errors[] = gettext("You cannot specify the maximum new connections per host / per second(s) (advanced option) if statetype is none and no L7 container is selected.");
566
		if (!empty($_POST['statetimeout']))
567
			$input_errors[] = gettext("You cannot specify the state timeout (advanced option) if statetype is none and no L7 container is selected.");
568
	}
569

    
570
	if (($_POST['max'] != "") && !is_posnumericint($_POST['max']))
571
		$input_errors[] = gettext("Maximum state entries (advanced option) must be a positive integer");
572

    
573
	if (($_POST['max-src-nodes'] != "") && !is_posnumericint($_POST['max-src-nodes']))
574
		$input_errors[] = gettext("Maximum number of unique source hosts (advanced option) must be a positive integer");
575

    
576
	if (($_POST['max-src-conn'] != "") && !is_posnumericint($_POST['max-src-conn']))
577
		$input_errors[] = gettext("Maximum number of established connections per host (advanced option) must be a positive integer");
578

    
579
	if (($_POST['max-src-states'] != "") && !is_posnumericint($_POST['max-src-states']))
580
		$input_errors[] = gettext("Maximum state entries per host (advanced option) must be a positive integer");
581

    
582
	if (($_POST['max-src-conn-rate'] != "") && !is_posnumericint($_POST['max-src-conn-rate']))
583
		$input_errors[] = gettext("Maximum new connections per host / per second(s) (advanced option) must be a positive integer");
584

    
585
	if (($_POST['statetimeout'] != "") && !is_posnumericint($_POST['statetimeout']))
586
		$input_errors[] = gettext("State timeout (advanced option) must be a positive integer");
587

    
588
	if ((($_POST['max-src-conn-rate'] != "" and $_POST['max-src-conn-rates'] == "")) ||
589
		(($_POST['max-src-conn-rate'] == "" and $_POST['max-src-conn-rates'] != "")))
590
		$input_errors[] = gettext("Both maximum new connections per host and the interval (per second(s)) must be specified");
591

    
592
	if (!$_POST['tcpflags_any']) {
593
		$settcpflags = array();
594
		$outoftcpflags = array();
595
		foreach ($tcpflags as $tcpflag) {
596
			if ($_POST['tcpflags1_' . $tcpflag] == "on")
597
				$settcpflags[] = $tcpflag;
598
			if ($_POST['tcpflags2_' . $tcpflag] == "on")
599
				$outoftcpflags[] = $tcpflag;
600
		}
601
		if (empty($outoftcpflags) && !empty($settcpflags))
602
			$input_errors[] = gettext("If you specify TCP flags that should be set you should specify out of which flags as well.");
603
	}
604

    
605
	// Allow extending of the firewall edit page and include custom input validation
606
	pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/input_validation");
607

    
608
	if (!$input_errors) {
609
		$filterent = array();
610
		$filterent['id'] = $_POST['ruleid']>0?$_POST['ruleid']:'';
611

    
612
		$filterent['tracker'] = empty($_POST['tracker']) ? (int)microtime(true) : $_POST['tracker'];
613

    
614
		$filterent['type'] = $_POST['type'];
615
		if (isset($_POST['interface'] ))
616
			$filterent['interface'] = $_POST['interface'];
617

    
618
		if (isset($_POST['ipprotocol'] ))
619
			$filterent['ipprotocol'] = $_POST['ipprotocol'];
620

    
621
		if ($_POST['tcpflags_any']) {
622
			$filterent['tcpflags_any'] = true;
623
		} else {
624
			$settcpflags = array();
625
			$outoftcpflags = array();
626
			foreach ($tcpflags as $tcpflag) {
627
				if ($_POST['tcpflags1_' . $tcpflag] == "on")
628
					$settcpflags[] = $tcpflag;
629
				if ($_POST['tcpflags2_' . $tcpflag] == "on")
630
					$outoftcpflags[] = $tcpflag;
631
			}
632
			if (!empty($outoftcpflags)) {
633
				$filterent['tcpflags2'] = join(",", $outoftcpflags);
634
				if (!empty($settcpflags))
635
					$filterent['tcpflags1'] = join(",", $settcpflags);
636
			}
637
		}
638

    
639
		if (isset($_POST['tag']))
640
			$filterent['tag'] = $_POST['tag'];
641
		if (isset($_POST['tagged']))
642
			$filterent['tagged'] = $_POST['tagged'];
643
		if ($if == "FloatingRules" || isset($_POST['floating'])) {
644
			$filterent['direction'] = $_POST['direction'];
645
			if (isset($_POST['quick']) && $_POST['quick'] != "")
646
				$filterent['quick'] = $_POST['quick'];
647
			$filterent['floating'] = "yes";
648
			if (isset($_POST['interface']) && count($_POST['interface']) > 0)  {
649
				$filterent['interface'] = implode(",", $_POST['interface']);
650
			}
651
		}
652

    
653
		/* Advanced options */
654
		if ($_POST['allowopts'] == "yes")
655
			$filterent['allowopts'] = true;
656
		else
657
			unset($filterent['allowopts']);
658
		if ($_POST['disablereplyto'] == "yes")
659
			$filterent['disablereplyto'] = true;
660
		else
661
			unset($filterent['disablereplyto']);
662
		$filterent['max'] = $_POST['max'];
663
		$filterent['max-src-nodes'] = $_POST['max-src-nodes'];
664
		$filterent['max-src-conn'] = $_POST['max-src-conn'];
665
		$filterent['max-src-states'] = $_POST['max-src-states'];
666
		$filterent['statetimeout'] = $_POST['statetimeout'];
667
		$filterent['statetype'] = $_POST['statetype'];
668
		$filterent['os'] = $_POST['os'];
669
		if($_POST['nopfsync'] != "")
670
			$filterent['nopfsync'] = true;
671
		else
672
			unset($filterent['nopfsync']);
673

    
674
		/* Nosync directive - do not xmlrpc sync this item */
675
		if($_POST['nosync'] != "")
676
			$filterent['nosync'] = true;
677
		else
678
			unset($filterent['nosync']);
679

    
680
		/* unless both values are provided, unset the values - ticket #650 */
681
		if($_POST['max-src-conn-rate'] != "" and $_POST['max-src-conn-rates'] != "") {
682
			$filterent['max-src-conn-rate'] = $_POST['max-src-conn-rate'];
683
			$filterent['max-src-conn-rates'] = $_POST['max-src-conn-rates'];
684
		} else {
685
			unset($filterent['max-src-conn-rate']);
686
			unset($filterent['max-src-conn-rates']);
687
		}
688

    
689
		if ($_POST['proto'] != "any")
690
			$filterent['protocol'] = $_POST['proto'];
691
		else
692
			unset($filterent['protocol']);
693

    
694
		if ($_POST['proto'] == "icmp") {
695
			if ($filterent['ipprotocol'] == 'inet6' && $_POST['icmp6type'])
696
				$filterent['icmptype'] = $_POST['icmp6type'];
697
			else if ($filterent['ipprotocol'] != 'inet6' && $_POST['icmptype'])
698
				$filterent['icmptype'] = $_POST['icmptype'];
699
			else
700
				unset($filterent['icmptype']);
701
		} else
702
			unset($filterent['icmptype']);
703

    
704
		pconfig_to_address($filterent['source'], $_POST['src'],
705
			$_POST['srcmask'], $_POST['srcnot'],
706
			$_POST['srcbeginport'], $_POST['srcendport']);
707

    
708
		pconfig_to_address($filterent['destination'], $_POST['dst'],
709
			$_POST['dstmask'], $_POST['dstnot'],
710
			$_POST['dstbeginport'], $_POST['dstendport']);
711

    
712
		if ($_POST['disabled'])
713
			$filterent['disabled'] = true;
714
		else
715
			unset($filterent['disabled']);
716

    
717
		if ($_POST['dscp'])
718
			$filterent['dscp'] = $_POST['dscp'];
719

    
720
		if ($_POST['log'])
721
			$filterent['log'] = true;
722
		else
723
			unset($filterent['log']);
724
		strncpy($filterent['descr'], $_POST['descr'], 52);
725

    
726
		if ($_POST['gateway'] != "") {
727
			$filterent['gateway'] = $_POST['gateway'];
728
		}
729

    
730
		if ($_POST['defaultqueue'] != "") {
731
			$filterent['defaultqueue'] = $_POST['defaultqueue'];
732
			if ($_POST['ackqueue'] != "")
733
				$filterent['ackqueue'] = $_POST['ackqueue'];
734
		}
735

    
736
		if ($_POST['dnpipe'] != "") {
737
			$filterent['dnpipe'] = $_POST['dnpipe'];
738
			if ($_POST['pdnpipe'] != "")
739
				$filterent['pdnpipe'] = $_POST['pdnpipe'];
740
		}
741

    
742
		if ($_POST['l7container'] != "") {
743
			$filterent['l7container'] = $_POST['l7container'];
744
		}
745

    
746
		if ($_POST['sched'] != "") {
747
			$filterent['sched'] = $_POST['sched'];
748
		}
749

    
750
		if ($_POST['vlanprio'] != "") {
751
			$filterent['vlanprio'] = $_POST['vlanprio'];
752
		}
753
		if ($_POST['vlanprioset'] != "") {
754
			$filterent['vlanprioset'] = $_POST['vlanprioset'];
755
		}
756

    
757
		// If we have an associated nat rule, make sure the source and destination doesn't change
758
		if( isset($a_filter[$id]['associated-rule-id']) ) {
759
			$filterent['interface'] = $a_filter[$id]['interface'];
760
			if (isset($a_filter[$id]['protocol']))
761
				$filterent['protocol'] = $a_filter[$id]['protocol'];
762
			else if (isset($filterent['protocol']))
763
				unset($filterent['protocol']);
764
			if ($a_filter[$id]['protocol'] == "icmp" && $a_filter[$id]['icmptype'])
765
				$filterent['icmptype'] = $a_filter[$id]['icmptype'];
766
			else if (isset($filterent['icmptype']))
767
				unset($filterent['icmptype']);
768

    
769
			$filterent['source'] = $a_filter[$id]['source'];
770
			$filterent['destination'] = $a_filter[$id]['destination'];
771
			$filterent['associated-rule-id'] = $a_filter[$id]['associated-rule-id'];
772
		}
773

    
774
		if ( isset($a_filter[$id]['created']) && is_array($a_filter[$id]['created']) )
775
			$filterent['created'] = $a_filter[$id]['created'];
776

    
777
		$filterent['updated'] = make_config_revision_entry();
778

    
779
		// Allow extending of the firewall edit page and include custom input validation
780
		pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/pre_write_config");
781

    
782
		if (isset($id) && $a_filter[$id])
783
			$a_filter[$id] = $filterent;
784
		else {
785
			$filterent['created'] = make_config_revision_entry();
786
			if (is_numeric($after))
787
				array_splice($a_filter, $after+1, 0, array($filterent));
788
			else
789
				$a_filter[] = $filterent;
790
		}
791

    
792
		filter_rules_sort();
793

    
794
		if (write_config())
795
			mark_subsystem_dirty('filter');
796

    
797
		if (isset($_POST['floating']))
798
			header("Location: firewall_rules.php?if=FloatingRules");
799
		else
800
			header("Location: firewall_rules.php?if=" . htmlspecialchars($_POST['interface']));
801
		exit;
802
	}
803
}
804

    
805
$pgtitle = array(gettext("Firewall"),gettext("Rules"),gettext("Edit"));
806
$shortcut_section = "firewall";
807

    
808
$closehead = false;
809

    
810
$page_filename = "firewall_rules_edit.php";
811
include("head.inc");
812

    
813
if ($input_errors)
814
	print_input_errors($input_errors);
815

    
816
require('classes/Form.class.php');
817
$form = new Form;
818
$section = new Form_Section('Edit Firewall rule');
819

    
820
if (isset($id))
821
{
822
	$form->addGlobal(new Form_Input(
823
		'id',
824
		'ID',
825
		'hidden',
826
		$id
827
	));
828
}
829

    
830
if (isset($a_filter[$id]))
831
{
832
	$form->addGlobal(new Form_Input(
833
		'tracker',
834
		'Tracker',
835
		'hidden',
836
		$pconfig['tracker']
837
	));
838
}
839

    
840
$form->addGlobal(new Form_Input(
841
	'after',
842
	'After',
843
	'hidden',
844
	$after
845
));
846

    
847
$form->addGlobal(new Form_Input(
848
	'ruleid',
849
	'Ruleid',
850
	'hidden',
851
	$pconfig['ruleid']
852
));
853

    
854
// Allow extending of the firewall edit page and include custom input validation
855
pfSense_handle_custom_code("/usr/local/pkg/firewall_rules/htmlphpearly");
856

    
857
$values = array(
858
	'pass' => 'Pass',
859
	'block' => 'Block',
860
	'reject' => 'Reject',
861
);
862

    
863
if ($if == "FloatingRules" || isset($pconfig['floating']))
864
	$values['match'] = 'Match';
865

    
866
$section->addInput(new Form_Select(
867
	'type',
868
	'Action',
869
	$pconfig['type'],
870
	$values
871
))->setHelp('Choose what to do with packets that match the criteria specified '.
872
	'below.<br/>Hint: the difference between block and reject is that with '.
873
	'reject, a packet (TCP RST or ICMP port unreachable for UDP) is returned '.
874
	'to the sender, whereas with block the packet is dropped silently. In '.
875
	'either case, the original packet is discarded.');
876

    
877
$section->addInput(new Form_Checkbox(
878
	'disabled',
879
	'Disabled',
880
	'Disable this rule',
881
	$pconfig['disabled']
882
))->setHelp('Set this option to disable this rule without removing it from the '.
883
	'list.');
884

    
885
if ($if == "FloatingRules" || isset($pconfig['floating']))
886
{
887
	$section->addInput(new Form_Checkbox(
888
		'floating',
889
		'Quick',
890
		'Apply the action immediately on match.',
891
		$pconfig['quick']
892
	))->setHelp('Set this option if you need to apply this action to traffic that '.
893
		'matches this rule immediately.');
894
}
895

    
896
$edit_disabled = isset($pconfig['associated-rule-id']);
897

    
898
if ($edit_disabled)
899
{
900
	$extra = '';
901
	foreach( $config['nat']['rule'] as $index => $nat_rule )
902
	{
903
		if ($nat_rule['associated-rule-id'] === $pconfig['associated-rule-id'] )
904
			$extra = '<br/><a href="firewall_nat_edit.php?id='. $index .'">'. gettext('View the NAT rule') .'</a>';
905
	}
906

    
907
	$section->add(new Form_Group(
908
		'Associated filter rule'
909
	))->setHelp('Note: This is associated to a NAT rule.<br/>You cannot edit '.
910
		'the interface, protocol, source, or destination of associated filter '.
911
		'rules.'. $extra);
912

    
913
	$section->addGlobal(new Form_Input(
914
		'associated-rule-id',
915
		'Associated Rule ID',
916
		'hidden',
917
		$pconfig['associated-rule-id']
918
	));
919

    
920
	if (!empty($pconfig['interface']))
921
	{
922
		$section->addInput(new Form_Input(
923
			'interface',
924
			'Interface',
925
			'hidden',
926
			$pconfig['interface']
927
		));
928
	}
929
}
930

    
931
$interfaces = array();
932

    
933
/* add group interfaces */
934
if (is_array($config['ifgroups']['ifgroupentry']))
935
	foreach ($config['ifgroups']['ifgroupentry'] as $ifgen)
936
		if (have_ruleint_access($ifgen['ifname']))
937
			$interfaces[$ifgen['ifname']] = $ifgen['ifname'];
938

    
939
foreach (get_configured_interface_with_descr() as $ifent => $ifdesc)
940
{
941
	if (have_ruleint_access($ifent))
942
		$interfaces[$ifent] = $ifdesc;
943
}
944

    
945
if ($config['l2tp']['mode'] == "server" && have_ruleint_access("l2tp"))
946
	$interfaces['l2tp'] = 'L2TP VPN';
947

    
948
if ($config['pptpd']['mode'] == "server" && have_ruleint_access("pptp"))
949
	$interfaces['pptp'] = 'PPTP VPN';
950

    
951
if (is_pppoe_server_enabled() && have_ruleint_access("pppoe"))
952
	$interfaces['pppoe'] = "PPPoE Server";
953

    
954
/* add ipsec interfaces */
955
if (isset($config['ipsec']['enable']) || isset($config['ipsec']['client']['enable']) && have_ruleint_access("enc0"))
956
	$interfaces["enc0"] = "IPsec";
957

    
958
/* add openvpn/tun interfaces */
959
if  ($config['openvpn']["openvpn-server"] || $config['openvpn']["openvpn-client"])
960
	$interfaces["openvpn"] = "OpenVPN";
961

    
962
$section->addInput($input = new Form_Select(
963
	'interface',
964
	'Interface',
965
	$pconfig['interface'],
966
	$interfaces,
967
	($if == "FloatingRules" || isset($pconfig['floating']))
968
))->setHelp('Choose on which interface packets must come in to match this '.
969
	'rule.');
970

    
971
if ($if == "FloatingRules" || isset($pconfig['floating']))
972
	$input->setHelp('Choose the interface(s) for this rule.');
973

    
974
if ($if == "FloatingRules" || isset($pconfig['floating']))
975
{
976
	$section->addInput(new Form_Select(
977
		'direction',
978
		'Direction',
979
		$pconfig['direction'],
980
		array(
981
			'any' => 'any',
982
			'in' => 'in',
983
			'out' => 'out',
984
		)
985
	));
986

    
987
	$section->addInput(new Form_Input(
988
		'floating',
989
		'Floating',
990
		'hidden',
991
		'floating'
992
	));
993
}
994

    
995
$section->addInput(new Form_Select(
996
	'ipprotocol',
997
	'TCP/IP Version',
998
	$pconfig['ipprotocol'],
999
	array(
1000
		'inet' => 'IPv4',
1001
		'inet6' => 'IPv6',
1002
		'inet46' => 'IPv4+IPv6',
1003
	)
1004
))->setHelp('Select the Internet Protocol version this rule applies to');
1005

    
1006
$section->addInput(new Form_Select(
1007
	'proto',
1008
	'Protocol',
1009
	$pconfig['ipprotocol'],
1010
	array(
1011
		'tcp' => 'TCP',
1012
		'udp' => 'UDP',
1013
		'tcp/udp' => 'TCP/UDP',
1014
		'icmp' => 'ICMP',
1015
		'esp' => 'ESP',
1016
		'ah' => 'AH',
1017
		'gre' => 'GRE',
1018
		'ipv6' => 'IPV6',
1019
		'igmp' => 'IGMP',
1020
		'pim' => 'PIM',
1021
		'ospf' => 'OSPF',
1022
		'any' => 'any',
1023
		'carp' => 'CARP',
1024
		'pfsync' => 'PFSYNC',
1025
	)
1026
))->setHelp('Select the Internet Protocol version this rule applies to');
1027

    
1028
$section->addInput(new Form_Select(
1029
	'icmptype',
1030
	'ICMP type',
1031
	$pconfig['icmptype'],
1032
	$icmptypes
1033
))->setHelp('If you selected ICMP for the protocol above, you may specify an ICMP type here.');
1034

    
1035
$section->addInput(new Form_Select(
1036
	'icmp6type',
1037
	'ICMPv6 type',
1038
	$pconfig['icmptype'],
1039
	$icmp6types
1040
))->setHelp('If you selected ICMP for the protocol above, you may specify an ICMP type here.');
1041

    
1042
$form->add($section);
1043

    
1044
// Source and destination share a lot of logic. Loop over the two
1045
foreach (['src' => 'Source', 'dst' => 'Destination'] as $type => $name)
1046
{
1047
	$section = new Form_Section($name .' details');
1048

    
1049
	$group = new Form_Group($name);
1050
	$group->add(new Form_Checkbox(
1051
		$type .'not',
1052
		$name .' not',
1053
		'Invert the sense of the match.',
1054
		$pconfig[$type.'not']
1055
	));
1056

    
1057
	$ruleType = $pconfig[$type];
1058
	if (is_specialnet($pconfig[$type]))
1059
		$ruleType = 'network';
1060
	elseif ((is_ipaddrv6($pconfig[$type]) && $pconfig[$type.'mask'] == 128) ||
1061
			(is_ipaddrv4($pconfig[$type]) && $pconfig[$type.'mask'] == 32) ||
1062
			(is_alias($pconfig[$type])))
1063
		$ruleType = 'single';
1064

    
1065
	$ruleValues = array(
1066
		'any' => 'any',
1067
		'single' => 'Single host or alias',
1068
		'network' => 'Network',
1069
	);
1070
	if (isset($a_filter[$id]['floating']) || $if == "FloatingRules")
1071
		$ruleValues['(self)'] = 'This Firewall (self)';
1072
	if (have_ruleint_access("pptp"))
1073
		$ruleValues['pptp'] = 'PPTP clients';
1074
	if (have_ruleint_access("pppoe"))
1075
		$ruleValues['pppoe'] = 'PPoE clients';
1076
	if (have_ruleint_access("l2tp"))
1077
		$ruleValues['l2tp'] = 'L2TP clients';
1078

    
1079
	foreach ($ifdisp as $ifent => $ifdesc)
1080
	{
1081
		if (!have_ruleint_access($ifent))
1082
			continue;
1083

    
1084
		$ruleValues[$ifent] = $ifdesc.' net';
1085
		$ruleValues[$ifent.'ip'] = $ifdesc.' address';
1086
	}
1087

    
1088
	$group->add(new Form_Select(
1089
		$type . 'type',
1090
		$name .' Type',
1091
		$ruleType,
1092
		$ruleValues
1093
	));
1094

    
1095
	$group->add(new Form_IpAddress(
1096
		$type,
1097
		$name .' Address',
1098
		$pconfig[$type]
1099
	))->addMask($type .'mask', $pconfig[$type.'mask']);
1100

    
1101
	$section->add($group);
1102

    
1103
	$portValues = ['any' => 'any'];
1104
	foreach ($wkports as $port => $portName)
1105
		$portValues[$port] = $portName.' ('. $port .')';
1106

    
1107
	$group = new Form_Group($name .' port range');
1108
	$group->add($input = new Form_Select(
1109
		$type .'beginport',
1110
		$name .' port begin',
1111
		$pconfig[$type .'beginport'],
1112
		$portValues
1113
	));
1114

    
1115
	if ($type == 'src')
1116
		$input->setHelp('Specify the source port or port range for this rule. This is '.
1117
			'usually random and almost never equal to the destination port range (and '.
1118
			'should usually be <b>any</b><br />Hint: you can leave the <i>to</i> field '.
1119
			'empty if you only want to filter a single port.');
1120
	else
1121
		$input->setHelp('Specify the destination port or port range for this rule. <br />'.
1122
			'Hint: you can leave the <i>to</i> field empty if you only want to filter a '.
1123
			'single port.');
1124

    
1125
	$group->add(new Form_Input(
1126
		$type .'beginport_cust',
1127
		$name .' port begin custom',
1128
		'number',
1129
		(isset($portValues[ $pconfig[$type .'beginport'] ]) ? null : $pconfig[$type .'beginport']),
1130
		['min' => 1, 'max' => 65535]
1131
	));
1132

    
1133
	$group->add(new Form_Select(
1134
		$type .'endport',
1135
		$name .' port end',
1136
		$pconfig[$type .'endport'],
1137
		$portValues
1138
	));
1139

    
1140
	$group->add(new Form_Input(
1141
		$type .'endport_cust',
1142
		$name .' port end custom',
1143
		'number',
1144
		(isset($portValues[ $pconfig[$type .'endport'] ]) ? null : $pconfig[$type .'endport']),
1145
		['min' => 1, 'max' => 65535]
1146
	));
1147

    
1148
	$section->add($group);
1149
	$form->add($section);
1150
}
1151

    
1152
$section = new Form_Section('Extra options');
1153
$section->addInput(new Form_Checkbox(
1154
	'log',
1155
	'Log',
1156
	'Log packets that are handled by this rule',
1157
	$pconfig['log']
1158
))->setHelp('Hint: the firewall has limited local log space. Don"t turn on logging '.
1159
	'for everything. If you want to do a lot of logging, consider using a remote '.
1160
	'syslog server (see the <a href="diag_logs_settings.php">Diagnostics: System logs: '.
1161
	'Settings</a> page).');
1162

    
1163
$section->addInput(new Form_Input(
1164
	'descr',
1165
	'Description',
1166
	'text',
1167
	$pconfig['descr']
1168
))->setHelp('You may enter a description here for your reference.');
1169

    
1170
$form->add($section);
1171
$section = new Form_Section('Advanced options');
1172

    
1173
$section->addInput(new Form_Select(
1174
	'os',
1175
	'Source OS',
1176
	$pconfig['os'],
1177
	['' => 'any'] + $ostypes
1178
))->setHelp('Note: this only works for TCP rules. General OS choice matches all subtypes.');
1179

    
1180
$section->addInput(new Form_Select(
1181
	'dscp',
1182
	'Diffserv Code Point',
1183
	$pconfig['dscp'],
1184
	array_combine($firewall_rules_dscp_types, $firewall_rules_dscp_types)
1185
));
1186

    
1187
$section->addInput(new Form_Checkbox(
1188
	'allowopts',
1189
	'Allow IP options',
1190
	'Allow packets with IP options to pass. Otherwise they are blocked by '.
1191
	'default. This is usually only seen with multicast traffic.',
1192
	$pconfig['allowopts']
1193
));
1194

    
1195
$section->addInput(new Form_Checkbox(
1196
	'disablereplyto',
1197
	'Disable reply-to',
1198
	'Disable auto generated reply-to for this rule.',
1199
	$pconfig['disablereplyto']
1200
));
1201

    
1202
$section->addInput(new Form_Input(
1203
	'tag',
1204
	'Tag',
1205
	'text',
1206
	$pconfig['tag']
1207
))->setHelp('You can mark a packet matching this rule and use this mark to match '.
1208
	'on other NAT/filter rules. It is called <b>Policy filtering</b>.');
1209

    
1210
$section->addInput(new Form_Input(
1211
	'tagged',
1212
	'Tagged',
1213
	'text',
1214
	$pconfig['tagged']
1215
))->setHelp('You can match packet on a mark placed before on another rule.');
1216

    
1217
$section->addInput(new Form_Input(
1218
	'max',
1219
	'Max. states',
1220
	'number',
1221
	$pconfig['max']
1222
))->setHelp('Maximum state entries this rule can create.');
1223

    
1224
$section->addInput(new Form_Input(
1225
	'max-src-nodes',
1226
	'Max. src nodes',
1227
	'number',
1228
	$pconfig['max-src-nodes']
1229
))->setHelp('Maximum number of unique source hosts.');
1230

    
1231
$section->addInput(new Form_Input(
1232
	'max-src-conn',
1233
	'Max. connections',
1234
	'number',
1235
	$pconfig['max-src-conn']
1236
))->setHelp('Maximum number of established connections per host (TCP only).');
1237

    
1238
$section->addInput(new Form_Input(
1239
	'max-src-states',
1240
	'Max. src. states',
1241
	'number',
1242
	$pconfig['max-src-states']
1243
))->setHelp('Maximum state entries per host.');
1244

    
1245
$section->addInput(new Form_Input(
1246
	'max-src-conn-rate',
1247
	'Max. src. conn. Rate',
1248
	'number',
1249
	$pconfig['max-src-conn-rate']
1250
))->setHelp('Maximum state entries per host');
1251

    
1252
$section->addInput(new Form_Input(
1253
	'max-src-conn-rates',
1254
	'Max. src. conn. Rates',
1255
	'number',
1256
	$pconfig['max-src-conn-rates'],
1257
	['min' => 1, 'max' => 255]
1258
))->setHelp('Maximum new connections per host / per second(s) (TCP only)');
1259

    
1260
$section->addInput(new Form_Input(
1261
	'statetimeout',
1262
	'State timeout',
1263
	'number',
1264
	$pconfig['statetimeout'],
1265
	['min' => 1, 'max' => 3600]
1266
))->setHelp('State Timeout in seconds (TCP only)');
1267

    
1268
$form->add($section);
1269
$section = new Form_Section('TCP Flags');
1270

    
1271
$setflags = explode(',', $pconfig['tcpflags1']);
1272
$outofflags = explode(',', $pconfig['tcpflags2']);
1273

    
1274
foreach ($tcpflags as $tcpflag)
1275
{
1276
	$section->addInput(new Form_Checkbox(
1277
		'tcpflags1_'. $tcpflag,
1278
		'Set '. strtoupper($tcpflag),
1279
		null,
1280
		(array_search($tcpflag, $setflags) !== false),
1281
		'on'
1282
	));
1283

    
1284
	$section->addInput(new Form_Checkbox(
1285
		'tcpflags2_'. $tcpflag,
1286
		'Out of '. strtoupper($tcpflag),
1287
		null,
1288
		(array_search($tcpflag, $setflags) !== false),
1289
		'on'
1290
	));
1291
}
1292

    
1293
$section->addInput(new Form_Checkbox(
1294
	'tcpflags_any',
1295
	'Any',
1296
	'Any flags',
1297
	$pconfig['tcpflags_any'],
1298
	'on'
1299
))->setHelp('Use this to choose TCP flags that must be set or cleared for this rule to match.');
1300

    
1301
$form->add($section);
1302
$section = new Form_Section('State Type');
1303

    
1304
$section->addInput(new Form_Checkbox(
1305
	'nopfsync',
1306
	'No pfSync',
1307
	'Prevent states created by this rule to be sync\'ed over pfsync.',
1308
	$pconfig['nopfsync']
1309
));
1310

    
1311
$section->addInput(new Form_Select(
1312
	'statetype',
1313
	'State type',
1314
	$pconfig['statetype'],
1315
	array(
1316
		'keep state' => 'Keep: works with all IP protocols',
1317
		'sloppy state' => 'Sloppy: works with all IP protocols',
1318
		'synproxy state' => 'Synproxy: proxies incoming TCP connections to help protect servers from spoofed TCP SYN floods. This option includes the functionality of keep state and modulate state combined',
1319
		'none' => 'None: Do not use state mechanisms to keep track.  This is only useful if you\'re doing advanced queueing in certain situations',
1320
	)
1321
))->setHelp('Select which type of state tracking mechanism you would like to use.  If in doubt, use keep state.');
1322

    
1323
$section->addInput(new Form_Checkbox(
1324
	'nosync',
1325
	'No XMLRPC Sync',
1326
	'Prevent the rule on Master from automatically syncing to other CARP members',
1327
	$pconfig['nosync']
1328
))->setHelp('This does NOT prevent the rule from being overwritten on Slave.');
1329

    
1330
$vlanprio = array("none", "be", "bk", "ee", "ca", "vi", "vo", "ic", "nc");
1331
$section->addInput(new Form_Select(
1332
	'vlanprio',
1333
	'VLAN Prio',
1334
	$pconfig['vlanprio'],
1335
	$vlanprio
1336
))->setHelp('Choose 802.1p priority to match on');
1337

    
1338
$section->addInput(new Form_Select(
1339
	'vlanprioset',
1340
	'VLAN Prio Set',
1341
	$pconfig['vlanprioset'],
1342
	$vlanprio
1343
))->setHelp('Choose 802.1p priority to apply');
1344

    
1345
$schedules = array('none'); //leave none to leave rule enabled all the time
1346
foreach ((array)$config['schedules']['schedule'] as $schedule)
1347
{
1348
	if ($schedule['name'] != "")
1349
		$schedules[] = $schedule['name'];
1350
}
1351

    
1352
$section->addInput(new Form_Select(
1353
	'sched',
1354
	'Schedule',
1355
	$pconfig['sched'],
1356
	$schedules
1357
))->setHelp('Leave as \'none\' to leave the rule enabled all the time');
1358

    
1359
$gateways = array('default' => 'default');
1360
foreach (return_gateways_array() as $gwname => $gw)
1361
{
1362
	if (($pconfig['ipprotocol'] == "inet46"))
1363
		continue;
1364
	if (($pconfig['ipprotocol'] == "inet6") && !(($gw['ipprotocol'] == "inet6") || (is_ipaddrv6($gw['gateway']))))
1365
		continue;
1366
	if (($pconfig['ipprotocol'] == "inet") && !(($gw['ipprotocol'] == "inet") || (is_ipaddrv4($gw['gateway']))))
1367
		continue;
1368
	if ($gw == "")
1369
		continue;
1370

    
1371
	$gateways[ $gwname ] = $gw['name'] . (empty($gw['gateway'])? '' : ' - '. $gateway_addr_str);
1372
}
1373

    
1374
foreach ((array)$a_gatewaygroups as $gwg_name => $gwg_data)
1375
{
1376
	if ((empty($pconfig['ipprotocol'])) || ($pconfig['ipprotocol'] == $gwg_data['ipprotocol']))
1377
		$gateways[ $gwg_name ] = $gwg_name;
1378
}
1379

    
1380
$section->addInput(new Form_Select(
1381
	'gateway',
1382
	'Gateway',
1383
	$pconfig['gateway'],
1384
	$gateways
1385
))->setHelp('Leave as \'default\' to use the system routing table. Or choose a '.
1386
	'gateway to utilize policy based routing.');
1387

    
1388
$group = new Form_Group('In / Out pipe');
1389

    
1390
$group->add(new Form_Select(
1391
	'dnpipe',
1392
	'DNpipe',
1393
	$pconfig['dnpipe'],
1394
	array('' => 'none') + array_keys($dnqlist)
1395
));
1396

    
1397
$group->add(new Form_Select(
1398
	'pdnpipe',
1399
	'PDNpipe',
1400
	$pconfig['pdnpipe'],
1401
	array('' => 'none') + array_keys($dnqlist)
1402
));
1403

    
1404
$section->add($group)->setHelp('Choose the Out queue/Virtual interface only if '.
1405
	'you have also selected In. The Out selection is applied to traffic leaving '.
1406
	'the interface where the rule is created, In is applied to traffic coming '.
1407
	'into the chosen interface.<br />If you are creating a floating rule, if the '.
1408
	'direction is In then the same rules apply, if the direction is out the '.
1409
	'selections are reverted Out is for incoming and In is for outgoing.'
1410
);
1411

    
1412
$group = new Form_Group('Ackqueue / Queue');
1413

    
1414
$qlist = array_keys($qlist);
1415
foreach ($qlist as $idx => $q)
1416
{
1417
	if (isset($ifdisp[$q]))
1418
		$qlist[$idx] = $ifdisp[$q];
1419
}
1420

    
1421
$group->add(new Form_Select(
1422
	'ackqueue',
1423
	'Ackqueue',
1424
	$pconfig['ackqueue'],
1425
	$qlist
1426
));
1427

    
1428
$group->add(new Form_Select(
1429
	'defaultqueue',
1430
	'Default Queue',
1431
	$pconfig['defaultqueue'],
1432
	$qlist
1433
));
1434

    
1435
$section->add($group)->setHelp('Choose the Acknowledge Queue only if you have '.
1436
	'selected Queue.'
1437
);
1438

    
1439
$section->addInput(new Form_Select(
1440
	'l7container',
1441
	'Layer7',
1442
	$pconfig['l7container'],
1443
	array_keys($l7clist)
1444
))->setHelp('Choose a Layer7 container to apply application protocol inspection '.
1445
	'rules. These are valid for TCP and UDP protocols only.');
1446

    
1447
$has_created_time = (isset($a_filter[$id]['created']) && is_array($a_filter[$id]['created']));
1448
$has_updated_time = (isset($a_filter[$id]['updated']) && is_array($a_filter[$id]['updated']));
1449

    
1450

    
1451
if ($has_created_time || $has_updated_time)
1452
{
1453
	$form->add($section);
1454
	$section = new Form_Section('Rule Information');
1455

    
1456
	if ($has_created_time)
1457
	{
1458
		$section->addInput(new Form_StaticText(
1459
			'Created',
1460
			date('n/j/y H:i:s', $a_filter[$id]['created']['time']) . gettext('by') .'<b>'. $a_filter[$id]['created']['username'] .'</b>'
1461
		));
1462
	}
1463

    
1464
	if ($has_updated_time)
1465
	{
1466
		$section->addInput(new Form_StaticText(
1467
			'Updated',
1468
			date('n/j/y H:i:s', $a_filter[$id]['updated']['time']) . gettext('by') .'<b>'. $a_filter[$id]['updated']['username'] .'</b>'
1469
		));
1470
	}
1471
}
1472

    
1473
$form->add($section);
1474
echo $form;
1475

    
1476
include("foot.inc");
(72-72/252)