Project

General

Profile

Download (15.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	firewall_shaper_layer7.php
5
	Copyright (C) 2008 Helder Pereira, André Ribeiro
6
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
7
	All rights reserved.
8

    
9
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11

    
12
	1. Redistributions of source code must retain the above copyright notice,
13
	   this list of conditions and the following disclaimer.
14

    
15
	2. Redistributions in binary form must reproduce the above copyright
16
	   notice, this list of conditions and the following disclaimer in the
17
	   documentation and/or other materials provided with the distribution.
18

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

    
35
##|+PRIV
36
##|*IDENT=page-firewall-trafficshaper-layer7
37
##|*NAME=Firewall: Traffic Shaper: Layer7 page
38
##|*DESCR=Allow access to the 'Firewall: Traffic Shaper: Layer7' page.
39
##|*MATCH=firewall_shaper_layer7.php*
40
##|-PRIV
41

    
42
require("guiconfig.inc");
43
require('classes/Form.class.php');
44
require_once("functions.inc");
45
require_once("filter.inc");
46
require_once("shaper.inc");
47

    
48
print('POST: '); print_r($_POST); print('<br />');
49
print('GET: '); print_r($_GET); print('<br />');
50

    
51
$dfltmsg = false;
52

    
53
// Variables protocols (dynamic) and structures (static)
54
$avail_protos =& generate_protocols_array();
55
$avail_structures = array("action","queue","limiter");
56

    
57
// Available behaviours
58
$avail_behaviours_action = array("block");
59
read_altq_config();
60
$avail_behaviours_altq = get_altq_name_list();
61
read_dummynet_config();
62
$avail_behaviours_limiter = get_dummynet_name_list();
63
$show_proto_form = false;
64

    
65
//More variables
66
$pgtitle = array(gettext("Firewall"),gettext("Traffic Shaper"), gettext("Layer7"));
67
$shortcut_section = "trafficshaper";
68

    
69
$default_layer7shaper_msg = '<br />' .
70
							gettext('You can add new layer7 protocol patterns by simply uploading the file') .
71
							' <a href="diag_patterns.php">' . gettext('here') . '</a>';
72

    
73
read_layer7_config();
74

    
75
$sform = new Form(false);
76

    
77
if($_GET['reset'] != "") {
78
	// kill all ipfw-classifyd processes
79
	mwexec("killall -9 ipfw-classifyd");
80
	exit;
81
}
82

    
83
if ($_GET) {
84
	if ($_GET['container'])
85
		$name = htmlspecialchars(trim($_GET['container']));
86

    
87
	if ($_GET['action'])
88
		$action = htmlspecialchars($_GET['action']);
89
}
90

    
91
if($_POST) {
92
	if ($_POST['container']) {
93
		$name = htmlspecialchars(trim($_POST['container']));
94
	}
95
}
96

    
97
if ($name) {
98
	//Get the object from the 7rules list
99
	$container = $layer7_rules_list[$name];
100
}
101

    
102
if ($_GET) {
103
	switch ($action) {
104
		case "add":
105
			$show_proto_form = true;
106
			$container = new layer7();
107
			$sform = $container->build_form(); //constructs the graphical interface on the right side
108
			unset($container);
109
		break;
110
		case "show":
111
			$show_proto_form = true;
112
			if($container) {
113
				$sform = $container->build_form();
114
			}
115
			else {
116
				$show_proto_form = false;
117
				$input_errors[] = gettext("Layer7 Rules Container not found!");
118
			}
119
		break;
120
		default:
121
			echo log_error("Get default");
122
			$show_proto_form = false;
123
			$dfltmsg = true;
124
		break;
125
	}
126
}
127

    
128
//add a new l7rules container
129
if ($_POST) {
130
	$show_proto_form = true;
131
	unset($input_errors);
132

    
133
	if($_POST['Submit']) {
134

    
135
		if (isset($layer7_rules_list[$name])) {
136
			$l7r = $layer7_rules_list[$name];
137
			$_POST['divert_port'] = $l7r->GetRPort();
138
		} else {
139
			$l7r =& new layer7();
140
			$_POST['divert_port'] = $l7r->gen_divert_port();
141
		}
142

    
143
		for($i=0; $_POST['protocol'][$i] != ""; $i++) {
144
			$_POST['l7rules'][$i]['protocol'] = $_POST['protocol'][$i];
145
			$_POST['l7rules'][$i]['structure'] = $_POST['structure'][$i];
146
			$_POST['l7rules'][$i]['behaviour'] = $_POST['behaviour'][$i];
147
		}
148

    
149
		$l7r->validate_input($_POST,$input_errors);
150
		$l7r->ReadConfig($_POST['container'], $_POST);
151
		//Before writing the results, we need to test for repeated protocols
152
		$non_dupes = array();
153
		$dupes = array();
154

    
155
		for($j=0; $j<$i; $j++) {
156
			if(!$non_dupes[$_POST['protocol'][$j]])
157
				$non_dupes[$_POST['protocol'][$j]] = true;
158
			else
159
				$dupes[] = $_POST['protocol'][$j];
160
		}
161

    
162
		unset($non_dupes);
163

    
164
		if(sizeof($dupes) == 0 && !$input_errors) {
165
			$l7r->wconfig();
166
			if (write_config())
167
				mark_subsystem_dirty('shaper');
168

    
169
			read_layer7_config();
170
		}
171
		else {
172
			if(sizeof($dupes) > 0) {
173
				$dupe_error = gettext("Found the following repeated protocol definitions") . ": ";
174

    
175
				foreach($dupes as $dupe)
176
					$dupe_error .= "$dupe ";
177

    
178
				$input_errors[] .= $dupe_error;
179
			}
180
		}
181

    
182
		unset($dupes);
183
		unset($dupe_error);
184
		//Even if there are repeated protocols, we won't lose any previous values
185
		//The user will be able to solve the situation
186
		$sform = $l7r->build_form();
187
		//Necessary to correctly build the proto form
188
		$container = $layer7_rules_list[$name];
189

    
190
		if($input_errors)
191
			$container =& $l7r;
192

    
193
	} else if($_POST['apply']) {
194
		write_config();
195

    
196
		$retval = 0;
197
		$retval = filter_configure();
198
		$savemsg = get_std_save_message($retval);
199

    
200
		if(stristr($retval, "error") != true)
201
			$savemsg = get_std_save_message($retval);
202
		else
203
			$savemsg = $retval;
204

    
205
		clear_subsystem_dirty('shaper');
206

    
207
		if($container) {
208
			$sform = $container->build_form();
209
		} else {
210
			$show_proto_form = false;
211
			$dfltmsg = true;
212
		}
213
	} else if ($_POST['delete']) {
214
		$container->delete_l7c();
215

    
216
		if (write_config())
217
			mark_subsystem_dirty('shaper');
218

    
219
		unset($container);
220

    
221
		header("Location: firewall_shaper_layer7.php");
222
		exit;
223
	}
224
	else {
225
		$show_proto_form = false;
226
	}
227
}
228

    
229
if(!$_GET && !$_POST) {
230
	$show_proto_form = false;
231
	$dfltmsg = true;
232
}
233

    
234
// Builds the left tree
235
$tree = "<ul class=\"tree\" >";
236
if (is_array($layer7_rules_list)) {
237
	foreach ($layer7_rules_list as $tmpl7)
238
		$tree .= $tmpl7->build_tree();
239
}
240

    
241
$tree .= "</ul>";
242

    
243
include("head.inc");
244
?>
245

    
246
<link rel="stylesheet" type="text/css" media="all" href="./tree/tree.css" />
247
<script type="text/javascript" src="./tree/tree.js"></script>
248

    
249
<script type="text/javascript">
250
//<![CDATA[
251
var initial_count = new Array();
252
var rows_limit = 0; // Set to 0 to disable limitation
253

    
254
/* Build the behaviours arrays in javascript */
255
var js_behaviours_action = ['block']; //static
256

    
257
var js_behaviours_altq = new Array();
258
js_behaviours_altq = array_altq(js_behaviours_altq);
259

    
260
var js_behaviours_limiter = new Array();
261
js_behaviours_limiter = array_limiter(js_behaviours_limiter);
262

    
263
function array_altq(a_behav) {
264
	var index;
265
	<?php if (!empty($avail_behaviours_altq)) {
266
	  foreach ($avail_behaviours_altq as $key => $queue) { ?>
267
		name = "<?= $queue; ?>";
268
		index = <?= $key; ?>;
269
		a_behav[index] = name;
270
	<?php }
271
	} ?>
272
	return a_behav;
273
}
274

    
275
function array_limiter(a_behav) {
276
	var index;
277
	<?php if (!empty($avail_behaviours_limiter)) {
278
	  foreach ($avail_behaviours_limiter as $key => $limiter) { ?>
279
		name = "<?= $limiter; ?>";
280
		index = <?= $key; ?>;
281
		a_behav[index] = name;
282
	<?php }
283
	} ?>
284
	return a_behav;
285
}
286

    
287
/* Fill the variables with available protocols, structures and behaviours */
288
function fillProtocol() {
289
	var protocol = '<select class="form-control" name="protocol[]">';
290
	var name;
291

    
292
	<?php foreach ($avail_protos as $key => $proto) { ?>
293
		name = "<?= $proto; ?>";
294
		protocol += "<option value=" + name + ">" + name + "<\/option>";
295
	<?php } ?>
296
	protocol += "<\/select>";
297

    
298
	return protocol;
299
}
300

    
301
function fillStructure() {
302
	var structure = '<select class="form-control" name="structure[]" onchange="changeBehaviourValues(this.parentNode.parentNode);">';
303
	var name;
304
	<?php foreach ($avail_structures as $key => $struct) { ?>
305
		name = "<?= $struct; ?>";
306
		if(name == "queue") {
307
		  if(js_behaviours_altq != "") { structure += "<option value=" + name + ">" + name + "<\/option>";}
308
		}
309
		else {
310
		  if(name == "limiter") {
311
			if(js_behaviours_limiter != "") { structure += "<option value=" + name + ">" + name + "<\/option>";}
312
		  }
313
		  else structure += "<option value=" + name + ">" + name + "<\/option>"; //action
314
		}
315
	<?php } ?>
316
	structure += "<\/select>";
317

    
318
	return structure;
319
}
320

    
321
//Used by default to fill the values when inserting a new row.
322
function fillBehaviour() {
323
	var behaviour = '<select class="form-control" name="behaviour[]">';
324
	var name;
325
	<?php foreach ($avail_behaviours_action as $key => $behav) { ?>
326
		name = "<?= $behav; ?>";
327
		behaviour += "<option value=" + name + ">" + name + "<\/option>";
328
	<?php } ?>
329
	behaviour += "<\/select>";
330

    
331
	return behaviour;
332
}
333

    
334
/* Change the values on behaviours select when changing the structure row */
335
function changeBehaviourValues(row) {
336

    
337
	var selectedRow = row.rowIndex - 1; // The header is counted as the first row
338
	var structureSelected = document.getElementsByName("structure[]")[selectedRow].value;
339

    
340
	//Select the behaviours values to array a_behav
341
	var a_behav = new Array();
342

    
343
	if (structureSelected == "action") {
344
		a_behav = js_behaviours_action; //static
345
	}
346
	else {
347
		if (structureSelected == "queue") {
348
			a_behav = js_behaviours_altq;
349
		}
350
		else {
351
			a_behav = js_behaviours_limiter;
352
		}
353
	}
354

    
355

    
356
	//Build the html statement with the array values previously selected
357
	var new_behav;
358
	var name;
359
	for(i=0; i<a_behav.length; i++) {
360
		new_behav += "<option value=" + a_behav[i] + ">" + a_behav[i] + "<\/option>";
361
	}
362

    
363
	document.getElementsByName("behaviour[]")[selectedRow].innerHTML = new_behav;
364
}
365

    
366
/* Add row to the table */
367
function addRow(table_id) {
368
  var tbl = document.getElementById(table_id);
369

    
370
  // counting rows in table
371
  var rows_count = tbl.rows.length;
372
  if (initial_count[table_id] == undefined) {
373
	// if it is first adding in this table setting initial rows count
374
	initial_count[table_id] = rows_count;
375
  }
376
  // determining real count of added fields
377
  var tFielsNum =  rows_count - initial_count[table_id];
378
  if (rows_limit!=0 && tFielsNum >= rows_limit) return false;
379

    
380
  var remove = '<a class="btn  btn-default" onclick="removeRow(\''+table_id+'\',this.parentNode.parentNode)">Remove<\/a>';
381

    
382
  try {
383
	var newRow = tbl.insertRow(rows_count);
384
	var newCell = newRow.insertCell(0);
385
	newCell.innerHTML = fillProtocol();
386
	var newCell = newRow.insertCell(1);
387
	newCell.innerHTML = fillStructure();
388
	var newCell = newRow.insertCell(2);
389
	newCell.innerHTML = fillBehaviour();
390
	var newCell = newRow.insertCell(3);
391
	newCell.innerHTML = remove;
392
  }
393
  catch (ex) {
394
	//if exception occurs
395
	alert(ex);
396
  }
397
}
398

    
399
/* Remove row from the table */
400
function removeRow(tbl,row) {
401
  var table = document.getElementById(tbl);
402
  try {
403
	table.deleteRow(row.rowIndex);
404
  } catch (ex) {
405
	alert(ex);
406
  }
407
}
408
//]]>
409
</script>
410

    
411
<?php
412
// This function creates a table of rule selectors which are then inserted into the form
413
// using a StaticText class. While not pretty this maintains compatibility with all of
414
// the above javascript
415

    
416
function build_l7table() {
417
	global $container, $avail_protos, $avail_structures, $avail_behaviours_altq, $avail_behaviours_limiter,
418
		   $avail_behaviours_action;
419

    
420
	$tbl = '<table id="newtbl" class="table table-hover table-condensed">'; // No stripes for this table
421
	$tbl .= '<thead><tr><th>Protocol</th><th>Structure</th><th>Behavior</th></tr></thead>';
422
	$tbl .= '<tbody>';
423

    
424
	if($container) {
425
		foreach($container->rsets as $l7rule) {
426

    
427
			$tbl .= '<tr><td>';
428
			$tbl .= '<select name="protocol[]" class="form-control">';
429

    
430
			foreach($avail_protos as $proto):
431
				$tbl .= '<option value="' . $proto . '"';
432

    
433
				if ($proto == $l7rule->GetRProtocol())
434
					$tbl .= ' selected="selected"';
435

    
436
				$tbl .= '>' . $proto . '</option>';
437

    
438
			endforeach;
439

    
440
			$tbl .= '</select></td><td>';
441
			$tbl .= '<select name="structure[]" class="form-control" onchange="changeBehaviourValues(this.parentNode.parentNode);">';
442

    
443
			foreach($avail_structures as $struct) {
444
				if($struct == "queue") {
445
					if(!empty($avail_behaviours_altq)) {
446
						$tbl .= '<option value="' . $struct . '"';
447
						if ($struct == $l7rule->GetRStructure())
448
							$tbl .= ' selected="selected"';
449

    
450
						$tbl .= '>' . $struct . '</option>';
451
						}
452
					}
453
					else {
454
						if($struct == "limiter") {
455
							if(!empty($avail_behaviours_limiter)) {
456
								$tbl .= '<option value="' . $struct . '"';
457
								if ($struct == $l7rule->GetRStructure())
458
									$tbl .= ' selected="selected"';
459

    
460
								$tbl .= '>' . $struct . '</option>';
461
							}
462
						}
463
						else {
464
							if($struct == "action") {
465
								$tbl .= '<option value="' . $struct . '"';
466
								if ($struct == $l7rule->GetRStructure())
467
									$tbl .= ' selected="selected"';
468

    
469
								$tbl .= '>' . $struct . '</option>';
470
							}
471
						}
472
					}
473
				}
474

    
475
			$tbl .= '</select></td><td>';
476

    
477
			$tbl .= '<select name="behaviour[]" class="form-control">';
478

    
479
			if($l7rule->GetRStructure() == "action"):
480
				foreach($avail_behaviours_action as $behaviour):
481
					$tbl .= '<option value="' . $behaviour . '"';
482
					if ($behaviour == $l7rule->GetRBehaviour())
483
						$tbl .= ' selected="selected"';
484

    
485
					$tbl .= '>' . $behaviour . '</option>';
486

    
487
				endforeach;
488

    
489
				$tbl .= '</select>';
490

    
491
			endif;
492

    
493
			if($l7rule->GetRStructure() == "queue"):
494
				foreach($avail_behaviours_altq as $behaviour):
495

    
496
					$tbl .= '<option value="' . $behaviour	. '"';
497
					if ($behaviour == $l7rule->GetRBehaviour())
498
						$tbl .= ' selected="selected"';
499

    
500
					$tbl .= '>' . $behaviour . '</option>';
501

    
502
				endforeach;
503

    
504
				$tbl .= '</select>';
505

    
506
			endif;
507

    
508
			if($l7rule->GetRStructure() == "limiter"):
509
				foreach($avail_behaviours_limiter as $behaviour):
510
					$tbl .= '<option value="' . $behaviour . '"';
511
					if ($behaviour == $l7rule->GetRBehaviour())
512
						$tbl .= ' selected="selected"';
513

    
514
					$tbl .= '>' . $behaviour . '</option>';
515

    
516
				endforeach;
517

    
518
				$tbl .= '</select>';
519

    
520
	endif;
521

    
522
				$tbl .= '</td><td>';
523
				$tbl .= '<a type="button" class="btn  btn-default" onclick="removeRow(\'newtbl\',this.parentNode.parentNode); return false;" href="#">';
524
				$tbl .= gettext('Remove') . '</a>';
525
				$tbl .= '</td></tr>';
526

    
527

    
528
			} //end foreach
529
		} //end if
530

    
531
	$tbl .= '</tbody></table>';
532

    
533
	$tbl .= '<a id="addrow" type="button" onclick="javascript:addRow(\'newtbl\'); return false;" href="#" class="btn btn-sm btn-success">' . gettext('Add row') .
534
			'</a>';
535

    
536
	return($tbl);
537
}
538

    
539
if ($input_errors)
540
	print_input_errors($input_errors);
541

    
542
if ($savemsg)
543
	print_info_box($savemsg, 'success');
544

    
545
if (is_subsystem_dirty('shaper'))
546
	print_info_box_np(gettext("The traffic shaper configuration has been changed")	.  ".<br />" . gettext("You must apply the changes in order for them to take effect."));
547

    
548
$tab_array = array();
549
$tab_array[] = array(gettext("By Interface"), false, "firewall_shaper.php");
550
$tab_array[] = array(gettext("By Queue"), false, "firewall_shaper_queues.php");
551
$tab_array[] = array(gettext("Limiter"), false, "firewall_shaper_vinterface.php");
552
$tab_array[] = array(gettext("Layer7"), true, "firewall_shaper_layer7.php");
553
$tab_array[] = array(gettext("Wizards"), false, "firewall_shaper_wizards.php");
554
display_top_tabs($tab_array);
555

    
556
// Create a StaticText control and populate it with the rules table
557
if(!$dfltmsg) {
558
	$section = new Form_Section('Add one (or more) rules');
559

    
560
	$section->addInput(new Form_StaticText(
561
		'Rule(s)',
562
		build_l7table()
563
	));
564

    
565
	$sform->add($section);
566
}
567
?>
568

    
569
	<div class="panel panel-default">
570
		<div class="panel-heading" align="center"><h2 class="panel-title">Layer 7</h2></div>
571
		<div class="panel-body">
572
			<div class="form-group">
573
				<div class="col-sm-2 ">
574
					<?=$tree?>
575
					<br />
576
					<a href="firewall_shaper_layer7.php?action=add" class="btn btn-sm btn-success">
577
						<?=gettext("Create new L7<br />rule group")?>
578
					</a>
579
				</div>
580
				<div class="col-sm-10">
581
<?php
582
if($dfltmsg)
583
	print_info_box($output_form = $dn_default_shaper_msg . $default_layer7shaper_msg);
584
else
585
	print($sform);
586
?>
587
				</div>
588
			</div>
589
		</div>
590
	</div>
591

    
592

    
593
<?php
594
include("foot.inc");
(65-65/237)