Project

General

Profile

Download (11.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * firewall_shaper.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
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
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this software
21
 *    must display the following acknowledgment:
22
 *    "This product includes software developed by the pfSense Project
23
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
24
 *
25
 * 4. The names "pfSense" and "pfSense Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    coreteam@pfsense.org.
29
 *
30
 * 5. Products derived from this software may not be called "pfSense"
31
 *    nor may "pfSense" appear in their names without prior written
32
 *    permission of the Electric Sheep Fencing, LLC.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *
37
 * "This product includes software developed by the pfSense Project
38
 * for use in the pfSense software distribution (http://www.pfsense.org/).
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 */
53

    
54
##|+PRIV
55
##|*IDENT=page-firewall-trafficshaper
56
##|*NAME=Firewall: Traffic Shaper
57
##|*DESCR=Allow access to the 'Firewall: Traffic Shaper' page.
58
##|*MATCH=firewall_shaper.php*
59
##|-PRIV
60

    
61
require_once("guiconfig.inc");
62
require_once("functions.inc");
63
require_once("filter.inc");
64
require_once("shaper.inc");
65
require_once("rrd.inc");
66

    
67
if ($_GET['reset'] != "") {
68
	/* XXX: Huh, why are we killing php? */
69
	mwexec("killall -9 pfctl php");
70
	exit;
71
}
72

    
73
$pgtitle = array(gettext("Firewall"), gettext("Traffic Shaper"), gettext("By Interface"));
74
$pglinks = array("", "@self", "@self");
75
$shortcut_section = "trafficshaper";
76

    
77
$shaperIFlist = get_configured_interface_with_descr();
78
read_altq_config();
79
/*
80
 * The whole logic in these code maybe can be specified.
81
 * If you find a better way contact me :).
82
 */
83

    
84
if ($_GET) {
85
	if ($_GET['queue']) {
86
		$qname = htmlspecialchars(trim($_GET['queue']));
87
	}
88
	if ($_GET['interface']) {
89
		$interface = htmlspecialchars(trim($_GET['interface']));
90
	}
91
	if ($_GET['action']) {
92
		$action = htmlspecialchars($_GET['action']);
93
	}
94
}
95

    
96
if ($_POST) {
97
	if ($_POST['name']) {
98
		$qname = htmlspecialchars(trim($_POST['name']));
99
	}
100
	if ($_POST['interface']) {
101
		$interface = htmlspecialchars(trim($_POST['interface']));
102
	}
103
	if ($_POST['parentqueue']) {
104
		$parentqueue = htmlspecialchars(trim($_POST['parentqueue']));
105
	}
106
}
107

    
108
if ($interface) {
109
	$altq = $altq_list_queues[$interface];
110

    
111
	if ($altq) {
112
		$queue =& $altq->find_queue($interface, $qname);
113
	} else {
114
		$addnewaltq = true;
115
	}
116
}
117

    
118
$dontshow = false;
119
$newqueue = false;
120
$dfltmsg = false;
121

    
122
if ($_GET) {
123
	switch ($action) {
124
		case "delete":
125
			if ($queue) {
126
				$queue->delete_queue();
127
				if (write_config()) {
128
					mark_subsystem_dirty('shaper');
129
				}
130
			}
131

    
132
			header("Location: firewall_shaper.php");
133
			exit;
134
			break;
135
		case "resetall":
136
			foreach ($altq_list_queues as $altq) {
137
				$altq->delete_all();
138
			}
139
			unset($altq_list_queues);
140
			$altq_list_queues = array();
141
			$tree = "<ul class=\"tree\" >";
142
			$tree .= get_interface_list_to_show();
143
			$tree .= "</ul>";
144
			unset($config['shaper']['queue']);
145
			unset($queue);
146
			unset($altq);
147
			$can_add = false;
148
			$can_enable = false;
149
			$dontshow = true;
150
			foreach ($config['filter']['rule'] as $key => $rule) {
151
				if (isset($rule['wizard']) && $rule['wizard'] == "yes") {
152
					unset($config['filter']['rule'][$key]);
153
				}
154
			}
155

    
156
			if (write_config()) {
157
				$retval = 0;
158
				$retval |= filter_configure();
159

    
160
				if (stristr($retval, "error") <> true) {
161
					$savemsg = get_std_save_message($retval);
162
					$class = 'success';
163
				} else {
164
					$savemsg = $retval;
165
					$class = 'warning';
166
				}
167
			} else {
168
				$savemsg = gettext("Unable to write config.xml (Access Denied?).");
169
				$class = 'warning';
170
			}
171

    
172
			$dfltmsg = true;
173

    
174

    
175
		break;
176

    
177
	case "add":
178
			/* XXX: Find better way because we shouldn't know about this */
179
		if ($altq) {
180

    
181
			switch ($altq->GetScheduler()) {
182
				case "PRIQ":
183
					$q = new priq_queue();
184
				break;
185
				case "FAIRQ":
186
					$q = new fairq_queue();
187
				break;
188
				case "HFSC":
189
					$q = new hfsc_queue();
190
				break;
191
				case "CBQ":
192
						$q = new cbq_queue();
193
				break;
194
				default:
195
					/* XXX: Happens when sched==NONE?! */
196
					$q = new altq_root_queue();
197
				break;
198
			}
199
		} else if ($addnewaltq) {
200
			$q = new altq_root_queue();
201
		} else {
202
			$input_errors[] = gettext("Could not create new queue/discipline! Any recent changes may need to be applied first.");
203
		}
204

    
205
		if ($q) {
206
			$q->SetInterface($interface);
207
			$sform = $q->build_form();
208
			$sform->addGlobal(new Form_Input(
209
				'parentqueue',
210
				null,
211
				'hidden',
212
				$qname
213
			));
214

    
215
			$newjavascript = $q->build_javascript();
216
			unset($q);
217
			$newqueue = true;
218
		}
219
		break;
220
		case "show":
221
			if ($queue) {
222
				$sform = $queue->build_form();
223
			} else {
224
				$input_errors[] = gettext("Queue not found!");
225
			}
226
		break;
227
		case "enable":
228
			if ($queue) {
229
				$queue->SetEnabled("on");
230
				$sform = $queue->build_form();
231
				if (write_config()) {
232
					mark_subsystem_dirty('shaper');
233
				}
234
			} else {
235
				$input_errors[] = gettext("Queue not found!");
236
			}
237
			break;
238
		case "disable":
239
			if ($queue) {
240
				$queue->SetEnabled("");
241
				$sform = $queue->build_form();
242
				if (write_config()) {
243
					mark_subsystem_dirty('shaper');
244
				}
245
			} else {
246
				$input_errors[] = gettext("Queue not found!");
247
			}
248
			break;
249
		default:
250
			$dfltmsg = true;
251
			$dontshow = true;
252
			break;
253
	}
254
}
255

    
256
if ($_POST) {
257
	unset($input_errors);
258

    
259
	if ($addnewaltq) {
260
		$altq =& new altq_root_queue();
261
		$altq->SetInterface($interface);
262
		$altq->ReadConfig($_POST);
263
		$altq->validate_input($_POST, $input_errors);
264
		if (!$input_errors) {
265
			unset($tmppath);
266
			$tmppath[] = $altq->GetInterface();
267
			$altq->SetLink($tmppath);
268
			$altq->wconfig();
269
			if (write_config()) {
270
				mark_subsystem_dirty('shaper');
271
			}
272
			$can_enable = true;
273
			$can_add = true;
274
		}
275

    
276
		read_altq_config();
277
		$sform = $altq->build_form();
278
	} else if ($parentqueue) { /* Add a new queue */
279
		$qtmp =& $altq->find_queue($interface, $parentqueue);
280
		if ($qtmp) {
281
			$tmppath =& $qtmp->GetLink();
282
			array_push($tmppath, $qname);
283
			$tmp =& $qtmp->add_queue($interface, $_POST, $tmppath, $input_errors);
284
			if (!$input_errors) {
285
				array_pop($tmppath);
286
				$tmp->wconfig();
287
				$can_enable = true;
288
				if ($tmp->CanHaveChildren() && $can_enable) {
289
					if ($tmp->GetDefault() <> "") {
290
						$can_add = false;
291
					} else {
292
						$can_add = true;
293
					}
294
				} else {
295
					$can_add = false;
296
				}
297
				if (write_config()) {
298
					mark_subsystem_dirty('shaper');
299
				}
300
				$can_enable = true;
301
				if ($altq->GetScheduler() != "PRIQ") { /* XXX */
302
					if ($tmp->GetDefault() <> "") {
303
						$can_add = false;
304
					} else {
305
						$can_add = true;
306
					}
307
				}
308
			}
309
			read_altq_config();
310
			$sform = $tmp->build_form();
311
		} else {
312
			$input_errors[] = gettext("Could not add new queue.");
313
		}
314
	} else if ($_POST['apply']) {
315
		write_config();
316

    
317
		$retval = 0;
318
		$retval = filter_configure();
319

    
320
		if (stristr($retval, "error") <> true) {
321
			$savemsg = get_std_save_message($retval);
322
			$class = 'success';
323
		} else {
324
			$savemsg = $retval;
325
			$class = 'warning';
326
		}
327

    
328
		/* reset rrd queues */
329
		system("rm -f /var/db/rrd/*queuedrops.rrd");
330
		system("rm -f /var/db/rrd/*queues.rrd");
331
		enable_rrd_graphing();
332

    
333
		clear_subsystem_dirty('shaper');
334

    
335
		if ($queue) {
336
			$sform = $queue->build_form();
337
			$dontshow = false;
338
		} else {
339
			$sform = $default_shaper_message;
340
			$dontshow = true;
341
		}
342
	} else if ($queue) {
343
		$queue->validate_input($_POST, $input_errors);
344
		if (!$input_errors) {
345
			$queue->update_altq_queue_data($_POST);
346
			$queue->wconfig();
347
			if (write_config()) {
348
				mark_subsystem_dirty('shaper');
349
			}
350
			$dontshow = false;
351
		}
352
		read_altq_config();
353
		$sform = $queue->build_form();
354
	} else	{
355
		$dfltmsg = true;
356
		$dontshow = true;
357
	}
358
	mwexec("killall qstats");
359
}
360

    
361
if (!$_POST && !$_GET) {
362
	$dfltmsg = true;
363
	$dontshow = true;
364
}
365

    
366
if ($queue) {
367
	if ($queue->GetEnabled()) {
368
		$can_enable = true;
369
	} else {
370
		$can_enable = false;
371
	}
372
	if ($queue->CanHaveChildren() && $can_enable) {
373
		if ($altq->GetQname() <> $queue->GetQname() && $queue->GetDefault() <> "") {
374
			$can_add = false;
375
		} else {
376
			$can_add = true;
377
		}
378
	} else {
379
		$can_add = false;
380
	}
381
}
382

    
383
include("head.inc");
384

    
385
$tree = '<ul class="tree" >';
386
if (is_array($altq_list_queues)) {
387
	foreach ($altq_list_queues as $tmpaltq) {
388
		$tree .= $tmpaltq->build_tree();
389
	}
390
	$tree .= get_interface_list_to_show();
391
}
392

    
393
$tree .= "</ul>";
394

    
395
if ($queue) {
396
	print($queue->build_javascript());
397
}
398

    
399
print($newjavascript);
400

    
401
if ($input_errors) {
402
	print_input_errors($input_errors);
403
}
404

    
405
if ($savemsg) {
406
	print_info_box($savemsg, $class);
407
}
408

    
409
if (is_subsystem_dirty('shaper')) {
410
	print_apply_box(gettext("The traffic shaper configuration has been changed.") . "<br />" . gettext("The changes must be applied for them to take effect."));
411
}
412

    
413
$tab_array = array();
414
$tab_array[] = array(gettext("By Interface"), true, "firewall_shaper.php");
415
$tab_array[] = array(gettext("By Queue"), false, "firewall_shaper_queues.php");
416
$tab_array[] = array(gettext("Limiters"), false, "firewall_shaper_vinterface.php");
417
$tab_array[] = array(gettext("Wizards"), false, "firewall_shaper_wizards.php");
418
display_top_tabs($tab_array);
419

    
420
?>
421
<script type="text/javascript" src="./vendor/tree/tree.js"></script>
422

    
423
<div class="table-responsive">
424
	<table class="table">
425
		<tbody>
426
			<tr class="tabcont">
427
				<td class="col-md-1">
428
<?php
429
// Display the shaper tree
430
print($tree);
431

    
432
if (count($altq_list_queues) > 0) {
433
?>
434
					<a href="firewall_shaper.php?action=resetall" class="btn btn-sm btn-danger">
435
						<i class="fa fa-trash icon-embed-btn"></i>
436
						<?=gettext('Remove Shaper')?>
437
					</a>
438
<?php
439
}
440
?>
441
				</td>
442
				<td>
443
<?php
444

    
445
if (!$dfltmsg && $sform)  {
446
	// Add global buttons
447
	if (!$dontshow || $newqueue) {
448
		if ($can_add || $addnewaltq) {
449
			if ($queue) {
450
				$url = 'firewall_shaper.php?interface='. $interface . '&queue=' . $queue->GetQname() . '&action=add';
451
			} else {
452
				$url = 'firewall_shaper.php?interface='. $interface . '&action=add';
453
			}
454

    
455
			$sform->addGlobal(new Form_Button(
456
				'add',
457
				'Add new Queue',
458
				$url,
459
				'fa-plus'
460
			))->addClass('btn-success');
461

    
462
		}
463

    
464
		if ($queue) {
465
			$url = 'firewall_shaper.php?interface='. $interface . '&queue=' . $queue->GetQname() . '&action=delete';
466
		} else {
467
			$url = 'firewall_shaper.php?interface='. $interface . '&action=delete';
468
		}
469

    
470
		$sform->addGlobal(new Form_Button(
471
			'delete',
472
			$queue ? 'Delete this queue':'Disable shaper on interface',
473
			$url,
474
			'fa-trash'
475
		))->addClass('btn-danger');
476

    
477
	}
478

    
479
	print($sform);
480
}
481
?>
482
				</td>
483
			</tr>
484
		</tbody>
485
	</table>
486
</div>
487

    
488
<?php
489
if ($dfltmsg) {
490
?>
491
<div>
492
	<div class="infoblock">
493
		<?php print_info_box($default_shaper_msg, 'info', false); ?>
494
	</div>
495
</div>
496
<?php
497
}
498
include("foot.inc");
(50-50/225)