Project

General

Profile

Download (128 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	Copyright (C) 2008 Ermal Lu?i
4
	All rights reserved.
5

    
6
	Redistribution and use in source and binary forms, with or without
7
	modification, are permitted provided that the following conditions are met:
8

    
9
	1. Redistributions of source code must retain the above copyright notice,
10
	   this list of conditions and the following disclaimer.
11

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

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

    
27
	pfSense_BUILDER_BINARIES:	/bin/kill	/sbin/kldload	/bin/rm	/bin/ps
28
	pfSense_MODULE:	shaper
29
*/
30

    
31
/* XXX: needs some reducing on include. */
32
/* include all configuration functions. */
33
require_once("functions.inc");
34
require_once("util.inc");
35
require_once("notices.inc");
36

    
37
/*
38
 * I admit :) this is derived from xmplparse.inc StartElement()
39
 */
40
function &get_reference_to_me_in_config(&$mypath) 
41
{
42
	global $config;
43

    
44
	 $ptr =& $config['shaper'];
45
	foreach ($mypath as $indeks) {
46
		$ptr =& $ptr['queue'][$indeks];
47
	}
48

    
49
	return $ptr;
50
}
51

    
52
function unset_object_by_reference(&$mypath) 
53
{
54
	global $config;
55

    
56
	$ptr =& $config['shaper'];
57
	for ($i = 0; $i < count($mypath) - 1; $i++) {
58
		$ptr =& $ptr['queue'][$mypath[$i]];
59
	}
60
	unset($ptr['queue'][$mypath[$i]]);
61
}
62

    
63
function &get_dn_reference_to_me_in_config(&$mypath) 
64
{
65
	global $config;
66

    
67
	$ptr =& $config['dnshaper'];
68
	foreach ($mypath as $indeks) {
69
		$ptr =& $ptr['queue'][$indeks];
70
	}
71

    
72
	return $ptr;
73
}
74

    
75
function unset_dn_object_by_reference(&$mypath) 
76
{
77
	global $config;
78

    
79
	$ptr =& $config['dnshaper'];
80
	for ($i = 0; $i < count($mypath) - 1; $i++) {
81
		$ptr =& $ptr['queue'][$mypath[$i]];
82
	}
83
	unset($ptr['queue'][$mypath[$i]]);
84
}
85

    
86
function clean_child_queues($type, $mypath) 
87
{
88
	$ref = &get_reference_to_me_in_config($mypath);
89

    
90
	switch ($type) {
91
	case 'HFSC':
92
		if (isset($ref['borrow'])) unset($ref['borrow']);		
93
		if (isset($ref['hogs'])) unset($ref['hogs']);
94
		if (isset($ref['buckets'])) unset($ref['buckets']);
95
		break;
96
	case 'PRIQ':
97
		if (isset($ref['borrow'])) unset($ref['borrow']);		
98
		if (isset($ref['bandwidth'])) unset($ref['bandwidth']);
99
		if (isset($ref['bandwidthtype'])) unset($ref['bandwidthtype']);
100
		/* fall through */
101
	case 'FAIRQ':
102
		if (isset($ref['borrow'])) unset($ref['borrow']);		
103
		/* fall through */
104
	case 'CBQ':
105
		if (isset($ref['realtime'])) unset($ref['realtime']);	
106
		if (isset($ref['realtime1'])) unset($ref['realtime1']);
107
		if (isset($ref['realtime2'])) unset($ref['realtime2']);
108
		if (isset($ref['realtime3'])) unset($ref['realtime3']);
109
		if (isset($ref['upperlimit'])) unset($ref['upperlimit']);
110
		if (isset($ref['upperlimit1'])) unset($ref['upperlimit1']);
111
		if (isset($ref['upperlimit2'])) unset($ref['upperlimit2']);
112
		if (isset($ref['upperlimit3'])) unset($ref['upperlimit3']);
113
		if (isset($ref['linkshare'])) unset($ref['linkshare']);
114
		if (isset($ref['linkshare1'])) unset($ref['linkshare1']);
115
		if (isset($ref['linkshare2'])) unset($ref['linkshare2']);
116
		if (isset($ref['linkshare3'])) unset($ref['linkshare3']);	
117
		if (isset($ref['hogs'])) unset($ref['hogs']);
118
		if (isset($ref['buckets'])) unset($ref['buckets']);
119
		break;
120
	}
121
}
122

    
123
function get_bandwidthtype_scale($type) 
124
{
125
        switch ($type) {
126
        case "Gb":
127
                $factor = 1024 * 1024 * 1024;
128
        	break;
129
        case "Mb":
130
                $factor = 1024 * 1024;
131
        	break;
132
        case "Kb":
133
                $factor = 1024;
134
        	break;
135
        case "b":
136
        default:
137
                $factor = 1;
138
        	break;
139
        }
140
        return intval($factor);
141
}
142

    
143
function get_hfsc_bandwidth($object, $bw) 
144
{
145
	$pattern= "/[0-9]+/";
146
        if (preg_match($pattern, $bw, $match))
147
                $bw_1 = $match[1];
148
        else
149
                return 0;
150
        $pattern= "/(b|Kb|Mb|Gb|%)/";
151
        if (preg_match($pattern, $bw, $match)) {
152
                switch ($match[1]) {
153
                case '%':
154
                        $bw_1 = $bw_1 / 100 * get_interface_bandwidth($object);
155
                        break;
156
                default:
157
                        $bw_1 = $bw_1 * get_bandwidthtype_scale($match[0]);
158
                        break;
159
                }
160
		return floatval($bw_1);
161
        } else
162
                return 0;
163
}
164

    
165
function get_interface_bandwidth($object) 
166
{
167
	global $altq_list_queues;
168

    
169
        $int = $object->GetInterface();
170
        $altq =& $altq_list_queues[$int];
171
        if ($altq) {
172
                $bw_3 = $altq->GetBandwidth();
173
                $bw_3 = $bw_3 *  get_bandwidthtype_scale($altq->GetBwscale());
174
		return floatval($bw_3);
175
        } else
176
		return 0;
177
}
178

    
179
/*
180
 * This is duplicated here since we cannot include guiconfig.inc.
181
 * Including it makes all stuff break.
182
 */
183
function shaper_do_input_validation($postdata, $reqdfields, $reqdfieldsn, $input_errors) 
184
{
185

    
186
        /* check for bad control characters */
187
        foreach ($postdata as $pn => $pd) {
188
                if (is_string($pd) && preg_match("/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/", $pd)) {
189
                        $input_errors[] = "The field '" . $pn . "' contains invalid characters.";
190
                }
191
        }
192

    
193
        for ($i = 0; $i < count($reqdfields); $i++) {
194
                if ($postdata[$reqdfields[$i]] == "") {
195
                        $input_errors[] = "The field '" . $reqdfieldsn[$i] . "' is required.";
196
                }
197
        }
198
}
199

    
200
function cleanup_queue_from_rules($queue) 
201
{
202
	global $config;
203

    
204
	foreach ($config['filter']['rule'] as $rule) {
205
		if ($rule['defaultqueue'] == $queue)
206
			unset($rule['defaultqueue']);
207
		if ($rule['ackqueue'] == $queue)
208
			unset($rule['ackqueue']);
209
	}
210
}
211

    
212
function cleanup_dnqueue_from_rules($queue) 
213
{
214
	global $config;
215

    
216
	foreach ($config['filter']['rule'] as $rule) {
217
		if ($rule['dnpipe'] == $queue)
218
			unset($rule['dnpipe']);
219
		if ($rule['pdnpipe'] == $queue)
220
			unset($rule['pdnpipe']);
221
	}
222
}
223

    
224
class altq_root_queue {
225
	var $interface;
226
	var $tbrconfig ;
227
	var $bandwidth;
228
	var $bandwidthtype; /* b, Kb, Mb */
229
	var $scheduler;
230
	var $qlimit;
231
	var $queues = array();
232
	var $qenabled = false;
233
	var $link;
234
	var $default_present; /* if we have a default queue set */
235
	var $available_bw; /* in b/s */
236

    
237
	/* Accesor functions */
238
	function GetAvailableBandwidth() {
239
		return $this->available_bw;
240
	}
241
	function SetAvailableBandwidth($bw) {
242
		$this->available_bw = $bw;
243
	}
244
	function SetDefaultQueuePresent($value) {
245
		$this->default_present = $value;
246
	}
247
	function GetDefaultQueuePresent() {
248
		return trim($this->default_present);
249
	}
250
	function SetLink($link) {
251
		$this->link = $link;
252
	}
253
	function GetLink() {
254
		return $this->link;
255
	}	
256
	function GetEnabled() {
257
		return $this->qenabled;
258
	}
259
	function SetEnabled($value) {
260
		$this->qenabled = $value;
261
	}
262
	function CanHaveChildren() {
263
		return true;
264
	}
265
	function CanBeDeleted() {
266
		return false;
267
	}
268
	function GetQname() {
269
		return $this->interface;
270
	}
271
	function SetQname($name) {
272
		$this->interface = trim($name);
273
	}
274
	function GetInterface() {
275
		return $this->interface;
276
	}
277
	function SetInterface($name) {
278
		$this->interface = trim($name);
279
	}
280
	function GetTbrConfig() {
281
		return $this->tbrconfig;
282
	}
283
	function SetTbrConfig($tbrconfig) {
284
		$this->tbrconfig = $tbrconfig;
285
	}
286
	function GetBandwidth() {
287
		return $this->bandwidth;
288
	}
289
	function SetBandwidth($bw) {
290
		$this->bandwidth = $bw;
291
	}
292
	function GetBwscale() {
293
		return $this->bandwidthtype;
294
	}
295
	function SetBwscale($bwscale) {
296
		$this->bandwidthtype = $bwscale;
297
	}
298
	function GetScheduler() {
299
		return $this->scheduler;
300
	}
301
	function SetScheduler($scheduler) {
302
		$this->scheduler = trim($scheduler);
303
	}
304
	function GetQlimit() {
305
		return $this->qlimit;
306
	}
307
	function SetQlimit($limit) {
308
		$this->qlimit = $limit;
309
	}
310

    
311
	function validate_input($data, &$input_errors) {
312
		
313
		$reqdfields[] = "bandwidth";
314
		$reqdfieldsn[] = "Bandwidth";
315
		$reqdfields[] = "bandwidthtype";
316
		$reqdfieldsn[] = "Bandwidthtype";
317
		
318
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
319
		
320
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
321
			$input_errors[] = "Bandwidth must be an integer.";
322
                if ($data['bandwidth'] < 0)
323
			$input_errors[] = "Bandwidth cannot be negative.";
324
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
325
			$input_errors[] = "Qlimit must be an integer.";
326
	 	if ($data['qlimit'] < 0)
327
			$input_errors[] = "Qlimit must be an positive.";
328
                if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig'])))
329
			$input_errors[] = "Tbrsize must be an integer.";
330
                if ($data['tbrconfig'] < 0)
331
			$input_errors[] = "Tbrsize must be an positive.";
332
	}
333

    
334
	/* Implement this to shorten some code on the frontend page */
335
	function ReadConfig(&$conf) {
336
		if (isset($conf['tbrconfig']))
337
			$this->SetTbrConfig($conf['tbrconfig']);
338
		else
339
			$this->SetTbrConfig($conf['tbrconfig']);
340
		$this->SetBandwidth($conf['bandwidth']);
341
		if ($conf['bandwidthtype'] <> "")
342
			$this->SetBwscale($conf['bandwidthtype']);
343
		if (isset($conf['scheduler'])) {
344
			if ($this->GetScheduler() != $conf['scheduler']) {
345
				foreach ($this->queues as $q) {
346
					clean_child_queues($conf['scheduler'], $this->GetLink());
347
					$q->clean_queue($conf['scheduler']);
348
				}
349
			}
350
			$this->SetScheduler($conf['scheduler']);
351
		}
352
		if (isset($conf['qlimit']) && $conf['qlimit'] <> "")
353
			$this->SetQlimit($conf['qlimit']);
354
		else
355
			$this->SetQlimit("");
356
		if (isset($conf['name']))
357
			$this->SetQname($conf['name']);		
358
		if (!empty($conf['enabled']))
359
			$this->SetEnabled($conf['enabled']);
360
		else
361
			$this->SetEnabled("");
362
	}
363

    
364
	function copy_queue($interface, &$cflink) {
365
                $cflink['interface'] = $interface;
366
                $cflink['name'] = $interface;
367
                $cflink['scheduler'] = $this->GetScheduler();
368
                $cflink['bandwidth'] = $this->GetBandwidth();
369
                $cflink['bandwidthtype'] = $this->GetBwscale();
370
                $cflink['qlimit'] = $this->GetQlimit();
371
                $cflink['tbrconfig'] = $this->GetTbrConfig();
372
                $cflink['enabled'] = $this->GetEnabled();
373
		if (is_array($this->queues)) {
374
			$cflink['queue'] = array();
375
			foreach ($this->queues as $q) {
376
				$cflink['queue'][$q->GetQname()] = array();
377
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
378
			}
379
		}
380
	}
381

    
382
	function &get_queue_list($q = null) {
383
		$qlist = array();
384

    
385
		$qlist[$this->GetQname()] = & $this;
386
		if (is_array($this->queues)) {
387
			foreach ($this->queues as $queue)
388
				$queue->get_queue_list(&$qlist);
389
		}
390
		return $qlist;
391
	}
392

    
393
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
394

    
395
		if (!is_array($this->queues))
396
			$this->queues = array();
397

    
398
		switch ($this->GetScheduler()) {
399
		case "PRIQ":
400
			$q =& new priq_queue();
401
			break;
402
		case "HFSC":
403
			$q =& new hfsc_queue();
404
			break;
405
		case "CBQ":
406
			$q =& new cbq_queue();
407
			break;
408
		case "FAIRQ":
409
			$q =& new fairq_queue();
410
			break;
411
		default:
412
			/* XXX: but should not happen anyway */ 
413
			return;
414
			break;
415
		}
416
		$q->SetLink($path);
417
		$q->SetInterface($this->GetInterface());
418
		$q->SetEnabled("on");
419
		$q->SetParent(&$this);
420
		$q->ReadConfig($queue);
421
		$q->validate_input($queue, $input_errors);
422
		if (count($input_errors)) {
423
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
424
			return $q;
425
		}
426

    
427
		if (isset($queue['bandwidth'])) {
428
			switch ($queue['bandwidthtype']) {
429
			case "%":
430
				$myBw = $this->GetAvailableBandwidth() * $queue['bandwidth'] / 100;
431
				break;
432
			default:
433
				$myBw = $queue['bandwidth'] * get_bandwidthtype_scale($queue['bandwdithtype']);
434
				break;
435
			}
436
		}
437
		$q->SetAvailableBandwidth($myBw);
438
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
439
		$this->queues[$q->GetQname()] = &$q; 
440
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
441
		if (is_array($queue['queue'])) {
442
			foreach ($queue['queue'] as $key1 => $que) {
443
				array_push($path, $key1);
444
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
445
				array_pop($path);
446
			}
447
		}
448

    
449
		return $q;
450
	}
451

    
452
	/* interface here might be optional */
453
	function &find_queue($interface, $qname) {
454
		if ($qname == $this->GetQname()) {
455
			return $this;
456
		} 
457
		foreach ($this->queues as $q) {
458
			$result =& $q->find_queue("", $qname);
459
			if ($result)
460
				return $result;
461
		}
462
	}
463

    
464
	function &find_parentqueue($interface, $qname) {
465
		if ($qname == $interface) {
466
			$result =  NULL;
467
		} else if ($this->queues[$qname])	 {
468
			$result = $this;
469
		} else if ($this->GetScheduler() <> "PRIQ") {
470
			foreach ($this->queues as $q) {
471
				$result = $q->find_parentqueue("", $qname);
472
				if ($result)
473
					return $result;
474
			}
475
		}
476
	}
477

    
478
	function build_tree() {
479
		global $shaperIFlist;
480

    
481
		$tree = " <li><a href=\"firewall_shaper.php?interface=".$this->GetInterface()."&queue=". $this->GetInterface()."&action=show"; 
482
		$tree .= "\">" . $shaperIFlist[$this->GetInterface()] . "</a>";
483
		if (is_array($this->queues)) {
484
			$tree .= "<ul>";
485
			foreach ($this->queues as $q)  {
486
				$tree .= $q->build_tree();
487
			}
488
		$tree .= "</ul>";
489
		}
490
		$tree .= "</li>";
491
		return $tree;
492
	}
493
	
494
	function delete_queue() { 
495
		foreach ($this->queues as $q) {
496
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
497
			$q->delete_queue();			
498
		}
499
		unset_object_by_reference($this->GetLink());
500
	 }
501

    
502
	function delete_all() {
503
                if (count($this->queues)) {
504
                        foreach ($this->queues as $q) {
505
                        	$q->delete_all();
506
                        	unset_object_by_reference($q->GetLink());
507
                                unset($q);
508
               		}
509
        	        unset($this->queues);
510
                }
511
        }
512

    
513
	/*
514
	 * First it spits:
515
	 * altq on $interface ..............
516
	 *      then it goes like
517
	 *      foreach ($queues as $qkey => $queue)
518
	 *              this->queues[$qkey]->build_rule();
519
	 */
520
	function build_rules(&$default = false) {
521
		if (count($this->queues) > 0 && $this->GetEnabled() == "on") {
522
			$default = false;
523
			$rules = " altq on  " . get_real_interface($this->GetInterface());
524
			if ($this->GetScheduler())
525
				$rules .= " ".strtolower($this->GetScheduler());
526
			if ($this->GetBandwidth()) {
527
				$rules .= " bandwidth ".trim($this->GetBandwidth());
528
				if ($this->GetBwscale())
529
					$rules .= $this->GetBwscale();
530
			}
531
			if ($this->GetTbrConfig())
532
				$rules .= " tbrsize ".$this->GetTbrConfig();
533
			if (count($this->queues)) {
534
				$i = count($this->queues);
535
				$rules .= " queue { ";
536
				foreach ($this->queues as $qkey => $qnone) {
537
					if ($i > 1) {
538
						$i--;
539
						$rules .= " {$qkey}, ";
540
					} else
541
						$rules .= " {$qkey} ";
542
				}
543
				$rules .= " } \n";
544
				foreach ($this->queues as $q) {
545
					$rules .= $q->build_rules($default);
546
				}
547
			}
548
			if ($default == false) {
549
				$error = "SHAPER: no default queue specified for interface ". $this->GetInterface() . ". The interface queue will be enforced as default.";
550
				file_notice("Shaper", $error, "Error occurred", "");
551
				unset($error);
552
				return "\n";
553
			} 
554
			$frule .= $rules;
555
		}
556
		$rules .= " \n";
557
		return $rules;
558
	}
559

    
560
	function build_javascript() {
561
		$javascript = "<script type=\"text/javascript\">";
562
		$javascript .= "function mySuspend() {";
563
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);";
564
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';";
565
		$javascript .= "else if (document.all)";
566
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';";
567
		$javascript .= "}";
568

    
569
		$javascript .= "function myResume() {";
570
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)";
571
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';";
572
		$javascript .= "else if (document.all)";
573
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';";
574
		$javascript .= "}";
575
		$javascript .= "</script>";
576

    
577
		return $javascript;
578
	}
579
	
580
	function build_shortform() {
581
		global $g;
582

    
583
		$altq =& $this;
584
		if ($altq)
585
			$scheduler = ": " . $altq->GetScheduler();
586
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
587
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=". $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
588
		$form .= "</td></tr>";
589
		$form .= "<tr>";
590
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
591
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
592
		$form .= "</td><td width=\"50%\"></td></tr>";
593
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
594
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
595
		$form .= $this->GetInterface() . "&queue=";
596
		$form .= $this->GetQname() . "&action=delete\">";
597
		$form .= "<img src=\"";
598
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
599
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Disable shaper on interface\">";
600
		$form .= "<span>Disable shaper on interface</span></a></td></tr>";
601

    
602
		return $form;
603

    
604
	}
605
	/*
606
	 * For requesting the parameters of the root queue
607
	 * to the user like the traffic wizard does.
608
	 */
609
	function build_form() { 
610
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
611
		$form .= "Enable/Disable";
612
		$form .= "<br/></td><td class=\"vncellreq\">";
613
		$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
614
                if ($this->GetEnabled() == "on")
615
                        $form .=  " CHECKED";
616
		$form .= " ><span class=\"vexpl\"> Enable/disable discipline and its children</span>";
617
		$form .= "</td></tr>";
618
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
619
		$form .= "<td class=\"vncellreq\">";
620
		$form .= "<strong>".$this->GetQname()."</strong>";
621
		$form .= "</td></tr>";
622
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Scheduler Type ";
623
		$form .= "</td>";
624
		$form .= "<td class=\"vncellreq\">";
625
		$form .= "<select id=\"scheduler\" name=\"scheduler\" class=\"formselect\">";
626
		$form .= "<option value=\"HFSC\"";
627
		if ($this->GetScheduler() == "HFSC")
628
			$form .= " selected=\"yes\"";
629
		$form .= ">HFSC</option>";
630
		$form .= "<option value=\"CBQ\"";
631
		if ($this->GetScheduler() == "CBQ")
632
			$form .= " selected=\"yes\"";
633
		$form .= ">CBQ</option>";
634
		$form .= "<option value=\"FAIRQ\"";
635
                if ($this->GetScheduler() == "FAIRQ")
636
                	$form .= " selected=\"yes\"";
637
                $form .= ">FAIRQ</option>";
638
		$form .= "<option value=\"PRIQ\"";
639
		if ($this->GetScheduler() == "PRIQ")
640
			$form .= " selected=\"yes\"";
641
		$form .= ">PRIQ</option>";
642
		$form .= "</select>";
643
		$form .= "<br> <span class=\"vexpl\">";
644
		$form .= "NOTE: Changing this changes all child queues!";
645
		$form .= " Beware you can lose information.";
646
		$form .= "</span>";
647
		$form .= "</td></tr>";
648
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Bandwidth";
649
		$form .= "</td><td class=\"vncellreq\">";
650
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
651
		$form .= $this->GetBandwidth() . "\">"; 
652
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
653
		$form .= "<option value=\"Kb\"";
654
		if ($this->GetBwscale() == "Kb")
655
			$form .= " selected=\"yes\"";
656
		$form .= ">Kbit/s</option>";
657
		$form .= "<option value=\"Mb\"";
658
		if ($this->GetBwscale() == "Mb")
659
			$form .= " selected=\"yes\"";
660
		$form .= ">Mbit/s</option>";
661
		$form .= "<option value=\"Gb\"";
662
		if ($this->GetBwscale() == "Gb")
663
			$form .= " selected=\"yes\"";
664
		$form .= ">Gbit/s</option>";		
665
		$form .= "<option value=\"\"";
666
		if ($this->GetBwscale() == "b")
667
			$form .= " selected=\"yes\"";
668
		$form .= ">Bit/s</option>";
669
		$form .= "</select>";
670
		$form .= "</td></tr>";
671
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Queue Limit</td>";
672
		$form .= "<td class=\"vncellreq\">";
673
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
674
		$form .= $this->GetQlimit();
675
		$form .= "\">";
676
		$form .= "</td></tr>";
677
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">TBR Size</td>";
678
		$form .= "<td class=\"vncellreq\">";
679
		$form .= "<br /><input type=\"text\" id=\"tbrconfig\" name=\"tbrconfig\" value=\"";
680
		$form .= $this->GetTbrConfig();
681
		$form .= "\">";
682
		$form .= "<br> <span class=\"vexpl\">";
683
		$form .= "Adjusts the size, in bytes, of the token bucket regulator. ";
684
		$form .= "If not specified, heuristics based on the interface ";
685
		$form .= "bandwidth are used to determine the size.";
686
		$form .= "</span></td></tr>";
687
		$form .= "<input type=\"hidden\" id=\"interface\" name=\"interface\"";
688
		$form .= " value=\"" . $this->GetInterface() . "\">";
689
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"".$this->GetQname()."\" >";
690

    
691

    
692
		return $form;
693
	}
694

    
695
	function update_altq_queue_data(&$data) { 
696
		$this->ReadConfig($data);
697
	}
698
	
699
	/*
700
	 * Should call on each of it queues and subqueues
701
	 * the same function much like build_rules();
702
	 */
703
	function wconfig() { 
704
		$cflink = &get_reference_to_me_in_config($this->GetLink());
705
		if (!is_array($cflink))
706
			$cflink = array();
707
		$cflink['interface'] = $this->GetInterface();	
708
		$cflink['name'] = $this->GetQname();
709
		$cflink['scheduler'] = $this->GetScheduler();
710
		$cflink['bandwidth'] = $this->GetBandwidth();
711
		$cflink['bandwidthtype'] = $this->GetBwscale();
712
		$cflink['qlimit'] = trim($this->GetQlimit());
713
		if (empty($cflink['qlimit']))
714
			unset($cflink['qlimit']);
715
		$cflink['tbrconfig'] = trim($this->GetTbrConfig());
716
		if (empty($cflink['tbrconfig']))
717
			unset($cflink['tbrconfig']);
718
		$cflink['enabled'] = $this->GetEnabled();
719
		if (empty($cflink['enabled']))
720
			unset($cflink['enabled']);
721
	}
722

    
723
}
724

    
725
class priq_queue {
726
	var $qname;
727
	var $qinterface; 
728
	var $qlimit;
729
	var $qpriority;
730
	var $description;
731
	var $isparent;
732
	var $qbandwidth;
733
	var $qbandwidthtype;
734
	var $qdefault = "";
735
	var $qrio = "";
736
	var $qred = "";
737
	var $qecn = "";
738
	var $qack;
739
	var $qenabled = "";
740
	var $qparent;
741
	var $link;
742
	var $available_bw; /* in b/s */
743

    
744
	/* This is here to help with form building and building rules/lists */
745
		var $subqueues = array();
746

    
747
	/* Accesor functions */
748
	function GetAvailableBandwidth() {
749
		return $this->available_bw;
750
	}
751
	function SetAvailableBandwidth($bw) {
752
		$this->available_bw = $bw;
753
	}
754
	function SetLink($link) {
755
		$this->link = $link;
756
	}
757
	function GetLink() {
758
		return $this->link;
759
	}
760
	function &GetParent() {
761
		return $this->qparent;
762
	}
763
	function SetParent(&$parent) {
764
		$this->qparent = &$parent;
765
	}
766
	function GetEnabled() {
767
		return $this->qenabled;
768
	}
769
	function SetEnabled($value) {
770
		$this->qenabled = $value;
771
	}
772
	function CanHaveChildren() {
773
		return false;
774
	}
775
	function CanBeDeleted() {
776
		return true;
777
	}
778
	function GetQname() {
779
		return $this->qname;
780
	}
781
	function SetQname($name) {
782
		$this->qname = trim($name);
783
	}
784
	function GetBandwidth() {
785
		return $this->qbandwidth;
786
	}
787
	function SetBandwidth($bandwidth) {
788
		$this->qbandwidth = $bandwidth;
789
	}
790
	function GetInterface() {
791
		return $this->qinterface;
792
	}
793
	function SetInterface($name) {
794
		$this->qinterface = trim($name);
795
	}
796
	function GetQlimit() {
797
		return $this->qlimit;
798
	}
799
	function SetQlimit($limit) {
800
		$this->qlimit = $limit;
801
	}
802
	function GetQpriority() {
803
		return $this->qpriority;
804
	}
805
	function SetQpriority($priority) {
806
		$this->qpriority = $priority;
807
	}
808
	function GetDescription() {
809
		return $this->description;
810
	}
811
	function SetDescription($str) {
812
		$this->description = trim($str);
813
	}
814
	function GetFirstime() {
815
		return $this->firsttime;
816
	}
817
	function SetFirsttime($number) {
818
		$this->firsttime = $number;
819
	}
820
	function GetBwscale() {
821
		return $this->qbandwidthtype;
822
	}
823
	function SetBwscale($scale) {
824
		$this->qbandwidthtype = $scale;
825
	}
826
	function GetDefault() {
827
		return $this->qdefault;
828
	}
829
	function SetDefault($value = false) {
830
		$this->qdefault = $value;
831
		altq_set_default_queue($this->GetInterface(), "true");
832
	}
833
	function GetRed() {
834
		return $this->qred;
835
	}
836
	function SetRed($red = false) {
837
		$this->qred = $red;
838
	}
839
	function GetRio() {
840
		return $this->qrio;
841
	}
842
	function SetRio($rio = false) {
843
		$this->qrio = $rio;
844
	}
845
	function GetEcn() {
846
		return $this->qecn;
847
	}
848
	function SetEcn($ecn = false) {
849
		$this->qecn = $ecn;
850
	}
851
	function GetAck() {
852
		return $this->qack;
853
	}
854
	function SetAck($ack = false) {
855
		$this->qack = $ack;
856
	}
857

    
858
	function build_javascript() {
859
		$javascript = "<script type=\"text/javascript\">";
860
		$javascript .= "function mySuspend() { \n";
861
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);\n";
862
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
863
		$javascript .= "else if (document.all)\n";
864
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
865
		$javascript .= "}\n";
866

    
867
		$javascript .= "function myResume() {\n";
868
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
869
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
870
		$javascript .= "else if (document.all)\n";
871
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
872
		$javascript .= "}\n";
873
		$javascript .= "</script>";
874
		
875
		return $javascript;
876
	}
877
	
878
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
879

    
880
	/* 
881
	 * Currently this will not be called unless we decide to clone a whole 
882
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
883
	 */
884
	 function copy_queue($interface, &$cflink) {
885

    
886
 		$cflink['name'] = $this->GetQname();
887
                $cflink['interface'] = $interface;
888
                $cflink['qlimit'] = $this->GetQlimit();
889
                $cflink['priority'] = $this->GetQpriority();
890
                $cflink['description'] = $this->GetDescription();
891
                $cflink['enabled'] = $this->GetEnabled();
892
                $cflink['default'] = $this->GetDefault();
893
                $cflink['red'] = $this->GetRed();
894
                $cflink['rio'] = $this->GetRio();
895
                $cflink['ecn'] = $this->GetEcn();
896

    
897
                if (is_array($this->subqueues)) {
898
                        $cflinkp['queue'] = array();
899
                        foreach ($this->subqueues as $q) {
900
				 $cflink['queue'][$q->GetQname()] = array();
901
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
902
			}
903
                }
904

    
905
	 }
906

    
907
	function clean_queue($sched) {
908
		clean_child_queues($sched, $this->GetLink());
909
		if (is_array($this->subqueues)) {
910
			foreach ($this->subqueues as $q)
911
				$q->clean_queue($sched);
912
		}
913
	}
914

    
915
        function &get_queue_list(&$qlist) {
916
		
917
		$qlist[$this->GetQname()] = & $this;
918
		if (is_array($this->subqueues)) {
919
			foreach ($this->subqueues as $queue)
920
				$queue->get_queue_list($qlist);
921
		}
922
	}
923

    
924
	function delete_queue() {
925
		unref_on_altq_queue_list($this->GetQname());
926
		if ($this->GetDefault())
927
				altq_set_default_queue($this->GetInterface(), "false");
928
		cleanup_queue_from_rules($this->GetQname());
929
		unset_object_by_reference($this->GetLink());
930
	}
931
	
932
	function delete_all() {
933
                if (count($this->subqueues)) {
934
                        foreach ($this->subqueues as $q) {
935
                                $q->delete_all();
936
                                unset_object_by_reference($q->GetLink());
937
                                unset($q);
938
                        }
939
                        unset($this->subqueues);
940
                }
941
        }
942

    
943
	 function &find_queue($interface, $qname) { 
944
		if ($qname == $this->GetQname())
945
			return $this; 
946
	}
947
	
948
	function find_parentqueue($interface, $qname) { return; }
949
		
950
	function validate_input($data, &$input_errors) {
951
	
952
		$reqdfields[] = "name";
953
		$reqdfieldsn[] = "Name";
954
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
955

    
956
		if ($data['priority'] && (!is_numeric($data['priority'])
957
						|| ($data['priority'] < 1) || ($data['priority'] > 15))) {
958
					$input_errors[] = "The priority must be an integer between 1 and 15.";
959
		}
960
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
961
				$input_errors[] = "Queue limit must be an integer";
962
		if ($data['qlimit'] < 0)
963
				$input_errors[] = "Queue limit must be positive";
964
		if (!preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
965
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
966
		
967
	}
968

    
969
	function ReadConfig(&$q) {
970
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
971
			$this->SetQname($q['newname']);
972
		} else if (!empty($q['newname'])) {
973
			$this->SetQname($q['newname']);
974
		} else if (isset($q['name']))
975
			$this->SetQname($q['name']);
976
		if (isset($q['interface']))
977
				$this->SetInterface($q['interface']);
978
		$this->SetBandwidth($q['bandwidth']);
979
		if ($q['bandwidthtype'] <> "")
980
			$this->SetBwscale($q['bandwidthtype']);
981
		if (!empty($q['qlimit']))
982
			$this->SetQlimit($q['qlimit']);
983
		else
984
			$this->SetQlimit(""); // Default
985
		if (!empty($q['priority']))
986
			$this->SetQPriority($q['priority']);
987
		else
988
			$this->SetQpriority("");
989
		if (!empty($q['description']))
990
			$this->SetDescription($q['description']);
991
		else
992
			$this->SetDescription("");
993
		if (!empty($q['red']))
994
			$this->SetRed($q['red']);
995
		else
996
			$this->SetRed();
997
		if (!empty($q['rio']))
998
			$this->SetRio($q['rio']);
999
		else
1000
			$this->SetRio();
1001
		if (!empty($q['ecn']))
1002
			$this->SetEcn($q['ecn']);
1003
		else
1004
			$this->SetEcn();
1005
		if (!empty($q['default']))
1006
			$this->SetDefault($q['default']);
1007
		else
1008
			$this->SetDefault();
1009
		if (!empty($q['enabled']))
1010
			$this->SetEnabled($q['enabled']);
1011
		else
1012
			$this->SetEnabled("");
1013

    
1014
	}
1015

    
1016
	function build_tree() {
1017
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
1018
		$tree .= "\" ";
1019
		$tmpvalue = $this->GetDefault();
1020
		if (!empty($tmpvalue))
1021
			$tree .= " class=\"navlnk\"";
1022
		$tree .= " >" . $this->GetQname() . "</a>";
1023
		/* 
1024
		 * Not needed here!
1025
		 * if (is_array($queues) {
1026
		 *	  $tree .= "<ul>";
1027
		 *	  foreach ($q as $queues) 
1028
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1029
		 *	  endforeach	
1030
		 *	  $tree .= "</ul>";
1031
		 * }
1032
		 */
1033

    
1034
		$tree .= "</li>"; 
1035

    
1036
		return $tree;
1037
	}
1038
		
1039
	/* Should return something like:
1040
	 * queue $qname on $qinterface bandwidth ....
1041
	 */
1042
	function build_rules(&$default = false) {
1043
		$pfq_rule = " queue ". $this->qname;
1044
		if ($this->GetInterface())
1045
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1046
		$tmpvalue = $this->GetQpriority();
1047
		if (!empty($tmpvalue))
1048
			$pfq_rule .= " priority ".$this->GetQpriority();
1049
		$tmpvalue = $this->GetQlimit();
1050
		if (!empty($tmpvalue))
1051
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1052
		if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
1053
			$pfq_rule .= " priq ( ";
1054
			$tmpvalue = $this->GetRed();
1055
			if (!empty($tmpvalue)) {
1056
				$comma = 1;
1057
				$pfq_rule .= " red ";
1058
			}
1059
			$tmpvalue = $this->GetRio();
1060
			if (!empty($tmpvalue)) {
1061
				if ($comma) 
1062
					$pfq_rule .= " ,";
1063
				$comma = 1;
1064
				$pfq_rule .= " rio ";
1065
			}
1066
			$tmpvalue = $this->GetEcn();
1067
			if (!empty($tmpvalue)) {
1068
				if ($comma) 
1069
					$pfq_rule .= " ,";
1070
				$comma = 1;
1071
				$pfq_rule .= " ecn ";
1072
			}
1073
			$tmpvalue = $this->GetDefault();
1074
			if (!empty($tmpvalue)) {
1075
				if ($comma)
1076
					$pfq_rule .= " ,";
1077
				$pfq_rule .= " default ";
1078
				$default = true;
1079
			}
1080
			$pfq_rule .= " ) ";
1081
		}
1082

    
1083
		$pfq_rule .= " \n";
1084

    
1085
		return $pfq_rule;
1086
	}
1087

    
1088
	/*
1089
	 * To return the html form to show to user
1090
	 * for getting the parameters.
1091
	 * Should do even for first time when the
1092
	 * object is created and later when we may
1093
	 * need to update it.
1094
	 */
1095
	function build_form() {
1096
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
1097
                $form .= "Enable/Disable";
1098
                $form .= "<br/></td><td class=\"vncellreq\">";
1099
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
1100
                if ($this->GetEnabled() == "on")
1101
                        $form .=  " CHECKED";
1102
                $form .= " ><span class=\"vexpl\"> Enable/Disable queue and its children</span>";
1103
                $form .= "</td></tr>";
1104
		$form .= "<tr>";
1105
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">";
1106
		$form .= "Queue Name</td><td width=\"78%\" class=\"vtable\">";
1107
		$form .= "<input name=\"newname\" type=\"text\" id=\"newname\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1108
		$form .= htmlspecialchars($this->GetQname());
1109
		$form .= "\">";
1110
		$form .= "<input name=\"name\" type=\"hidden\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1111
		$form .= htmlspecialchars($this->GetQname());
1112
		$form .= "\">";
1113
		$form .= "<br /> <span class=\"vexpl\">Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.";
1114
		$form .= "</span><br /></td>";
1115
		$form .= "</tr><tr>";
1116
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Priority</td>";
1117
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
1118
		$form .= htmlspecialchars($this->GetQpriority());
1119
		$form .= "\">";
1120
		$form .= "<br> <span class=\"vexpl\">For hfsc, the range is 0 to 7. The default is 1.  Hfsc queues with a higher priority are preferred in the case of overload.</span></td>";
1121
		$form .= "</tr>";
1122
		$form .= "<tr>";
1123
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Queue limit</td>";
1124
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"8\" value=\"";
1125
		$form .= htmlspecialchars($this->GetQlimit());
1126
		$form .= "\">";
1127
		$form .= "<br> <span class=\"vexpl\">Queue limit in packets per second."; 
1128
		$form .= "</span></td>";
1129
		$form .= "<tr>";
1130
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncell\">Scheduler options</td>";
1131
		$form .= "<td width=\"78%\" class=\"vtable\">";
1132
		$tmpvalue = $this->GetDefault();	
1133
		if (!empty($tmpvalue)) { 
1134
			$form .= "<input type=\"checkbox\" id=\"default\" CHECKED name=\"default\" value=\"default\"";
1135
			$form .= "> Default queue<br>";
1136
		} else {
1137
			$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\" value=\"default\"";
1138
			$form .= "> Default queue<br>";
1139
		}
1140
		$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\" value=\"red\" ";
1141
		$tmpvalue = $this->GetRed();
1142
		if(!empty($tmpvalue)) 
1143
			$form .=  " CHECKED";
1144
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">Random Early Detection</a><br>";
1145
		$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\" value=\"rio\"";
1146
		$tmpvalue = $this->GetRio();
1147
		if(!empty($tmpvalue)) 
1148
			$form .=  " CHECKED";
1149
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">Random Early Detection In and Out</a><br>";
1150
		$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\" value=\"ecn\"";
1151
		$tmpvalue = $this->GetEcn();
1152
		if(!empty($tmpvalue)) 
1153
			$form .=  " CHECKED";
1154
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">Explicit Congestion Notification</a><br>";
1155
		$form .= "<span class=\"vexpl\"><br>Select options for this queue";
1156
		$form .= "</tr><tr>";
1157
		$form .= "<td width=\"22%\" class=\"vncellreq\">Description</td>";
1158
		$form .= "<td width=\"78%\" class=\"vtable\">";
1159
		$form .= "<input type=\"text\" name=\"description\" size=\"50%\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\"  >";
1160
		$form .= "</td></tr>";
1161
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1162
		$form .= " value=\"".$this->GetInterface()."\">";
1163

    
1164
		return $form;
1165
	}
1166

    
1167
	function build_shortform() {
1168
		/* XXX: Hacks in site. Mostly layer violations!  */
1169
		global $g, $altq_list_queues;
1170

    
1171
		$altq =& $altq_list_queues[$this->GetInterface()];
1172
		if ($altq)
1173
			$scheduler = ": " . $altq->GetScheduler();
1174
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
1175
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=" . $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
1176
		$form .= "</td></tr>";
1177
		/* 
1178
		 * XXX: Hack in sight maybe fix with a class that wraps all
1179
		 * of this layer violations
1180
		 */
1181
		$form .= "<tr>";
1182
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1183
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
1184
		$form .= "</td><td width=\"50%\"></td></tr>";
1185
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1186
		$tmpvalue = $this->GetQpriority();
1187
		if (!empty($tmpvalue))
1188
			$form .= "Priority: on </td></tr>";
1189
		$tmpvalue = $this->GetDefault();
1190
		if (!empty($tmpvalue))
1191
			$form .= "<tr><td class=\"vncellreq\">Default: on </td></tr>";
1192
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1193
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1194
		$form .= $this->GetInterface() . "&queue=";
1195
		$form .= $this->GetQname() . "&action=delete\">";
1196
		$form .= "<img src=\"";
1197
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1198
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Delete queue from interface\">";
1199
		$form .= "<span>Delete queue from interface</span></a></td></tr>";
1200
		
1201
		return $form;
1202

    
1203
	}
1204

    
1205
		function update_altq_queue_data(&$q) { 
1206
		$this->ReadConfig($q);
1207
	}
1208

    
1209
	function wconfig() {
1210
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1211
		if (!is_array($cflink))
1212
			$cflink = array();
1213
		$cflink['name'] = $this->GetQname();
1214
		$cflink['interface'] = $this->GetInterface();
1215
		$cflink['qlimit'] = trim($this->GetQlimit());
1216
		if (empty($cflink['qlimit']))
1217
			unset($cflink['qlimit']);
1218
		$cflink['priority'] = trim($this->GetQpriority());
1219
		if (empty($cflink['priority']))
1220
			unset($cflink['priority']);
1221
		$cflink['description'] = trim($this->GetDescription());
1222
		if (empty($cflink['description']))
1223
			unset($cflink['description']);
1224
		$cflink['enabled'] = trim($this->GetEnabled());
1225
		if (empty($cflink['enabled']))
1226
			unset($cflink['enabled']);
1227
		$cflink['default'] = trim($this->GetDefault());
1228
		if (empty($cflink['default']))
1229
			unset($cflink['default']);
1230
		$cflink['red'] = trim($this->GetRed());
1231
		if (empty($cflink['red']))
1232
			unset($cflink['red']);
1233
		$cflink['rio'] = trim($this->GetRio());
1234
		if (empty($cflink['rio']))
1235
			unset($cflink['rio']);
1236
		$cflink['ecn'] = trim($this->GetEcn());
1237
		if (empty($cflink['ecn']))
1238
			unset($cflink['ecn']);
1239
	}
1240
}
1241

    
1242
class hfsc_queue extends priq_queue {
1243
	/* realtime */
1244
	var $realtime;
1245
	var $r_m1;
1246
	var $r_d;
1247
	var $r_m2;
1248
	/* linkshare */
1249
	var $linkshare;
1250
	var $l_m1;
1251
	var $l_d;
1252
	var $l_m2;
1253
	/* upperlimit */
1254
	var $upperlimit;
1255
	var $u_m1;
1256
	var $u_d;
1257
	var $u_m2;
1258

    
1259
	/*
1260
	 * HFSC can have nested queues.
1261
	 */
1262
	function CanHaveChildren() {
1263
		return true;
1264
	}
1265
	function GetRealtime() {
1266
           return $this->realtime;
1267
	}
1268
	function GetR_m1() {
1269
		return $this->r_m1;
1270
	}
1271
	function GetR_d() {
1272
		return $this->r_d;
1273
	}
1274
	function GetR_m2() {
1275
		return $this->r_m2;
1276
	}
1277
	function SetRealtime() {
1278
		$this->realtime = "on";
1279
	}
1280
	function DisableRealtime() {
1281
		$this->realtime = "";
1282
	}
1283
	function SetR_m1($value) {
1284
		$this->r_m1 = $value;
1285
	}
1286
	function SetR_d($value) {
1287
		$this->r_d = $value;
1288
	}
1289
	function SetR_m2($value) {
1290
		$this->r_m2 = $value;
1291
	}
1292
	function GetLinkshare() {
1293
		return $this->linkshare;
1294
	}
1295
	function DisableLinkshare() {
1296
		$this->linkshare = "";
1297
	}
1298
	function GetL_m1() {
1299
		return $this->l_m1;
1300
	}
1301
	function GetL_d() {
1302
		return $this->l_d;
1303
	}
1304
	function GetL_m2() {
1305
		return $this->l_m2;
1306
	}
1307
	function SetLinkshare() {
1308
		$this->linkshare = "on";
1309
	}
1310
	function SetL_m1($value) {
1311
		$this->l_m1 = $value;
1312
	}
1313
	function SetL_d($value) {
1314
		$this->l_d = $value;
1315
	}
1316
	function SetL_m2($value) {
1317
		$this->l_m2 = $value;
1318
	}
1319
	function GetUpperlimit() {
1320
		return $this->upperlimit;
1321
	}
1322
	function GetU_m1() {
1323
		return $this->u_m1;
1324
	}
1325
	function GetU_d() {
1326
		return $this->u_d;
1327
	}
1328
	function GetU_m2() {
1329
		return $this->u_m2;
1330
	}
1331
	function SetUpperlimit() {
1332
		$this->upperlimit = "on";
1333
	}
1334
	function DisableUpperlimit() {
1335
		$this->upperlimit = "";
1336
	}
1337
	function SetU_m1($value) {
1338
		$this->u_m1 = $value;
1339
	}
1340
	function SetU_d($value) {
1341
		$this->u_d = $value;
1342
	}
1343
	function SetU_m2($value) {
1344
		$this->u_m2 = $value;
1345
	}
1346

    
1347
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1348

    
1349
		if (!is_array($this->subqueues))
1350
			$this->subqueues = array();
1351
		$q =& new hfsc_queue();
1352
		$q->SetInterface($this->GetInterface());
1353
		$q->SetParent(&$this);
1354
		$q->ReadConfig($qname);
1355
		$q->validate_input($qname, $input_errors);
1356
		if (count($input_errors)) {
1357
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
1358
			return $q;
1359
		}
1360

    
1361
		$q->SetEnabled("on");
1362
		$q->SetLink($path);
1363
		switch ($q->GetBwscale()) {
1364
		case "%":
1365
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1366
			break;
1367
		default:
1368
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1369
			break;
1370
		}
1371
		$q->SetAvailableBandwidth($myBw);
1372
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1373

    
1374
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1375
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1376
		if (is_array($qname['queue'])) {
1377
			foreach ($qname['queue'] as $key1 => $que) {
1378
				array_push($path, $key1);
1379
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1380
				array_pop($path);
1381
			}
1382
		}
1383
	
1384
		return $q;
1385
	}
1386

    
1387
        function copy_queue($interface, &$cflink) {
1388

    
1389
		$cflink['name'] = $this->GetQname();
1390
		$cflink['interface'] = $interface;
1391
		$cflink['qlimit'] = trim($this->GetQlimit());
1392
		if (empty($cflink['qlimit']))
1393
			unset($cflink['qlimit']);
1394
		$cflink['priority'] = trim($this->GetQpriority());
1395
		if (empty($cflink['priority']))
1396
			unset($cflink['priority']);
1397
		$cflink['description'] = trim($this->GetDescription());
1398
		if (empty($cflink['description']))
1399
			unset($cflink['description']);
1400
		$cflink['bandwidth'] = $this->GetBandwidth();
1401
		$cflink['bandwidthtype'] = $this->GetBwscale();
1402
		$cflink['enabled'] = trim($this->GetEnabled());
1403
		if (empty($cflink['enabled']))
1404
			unset($cflink['enabled']);
1405
		$cflink['default'] = trim($this->GetDefault());
1406
		if (empty($cflink['default']))
1407
			unset($cflink['default']);
1408
		$cflink['red'] = trim($this->GetRed());
1409
		if (empty($cflink['red']))
1410
			unset($cflink['red']);
1411
		$cflink['rio'] = trim($this->GetRio());
1412
		if (empty($cflink['rio']))
1413
			unset($cflink['rio']);
1414
		$cflink['ecn'] = trim($this->GetEcn());
1415
		if (empty($cflink['ecn']))
1416
			unset($cflink['ecn']);
1417
		if ($this->GetLinkshare() <> "") {
1418
			if ($this->GetL_m1() <> "") {
1419
				$cflink['linkshare1'] = $this->GetL_m1();
1420
				$cflink['linkshare2'] = $this->GetL_d();
1421
				$cflink['linkshare'] = "on";
1422
			} else {
1423
				unset($cflink['linkshare1']);
1424
				unset($cflink['linkshare2']);
1425
				unset($cflink['linkshare']);
1426
			}
1427
			if ($this->GetL_m2() <> "") {
1428
				$cflink['linkshare3'] = $this->GetL_m2();
1429
				$cflink['linkshare'] = "on";
1430
			} else {
1431
				unset($cflink['linkshare3']);
1432
				unset($cflink['linkshare']);
1433
			}
1434
		}
1435
		if ($this->GetRealtime() <> "") {
1436
			if ($this->GetR_m1() <> "") {
1437
				$cflink['realtime1'] = $this->GetR_m1();
1438
				$cflink['realtime2'] = $this->GetR_d();
1439
				$cflink['realtime'] = "on";
1440
			} else {
1441
				unset($cflink['realtime1']);
1442
                                unset($cflink['realtime2']);
1443
                                unset($cflink['realtime']);
1444
			}
1445
			if ($this->GetR_m2() <> "") {
1446
				$cflink['realtime3'] = $this->GetR_m2();
1447
				$cflink['realtime'] = "on";
1448
			} else {
1449
				unset($cflink['realtime3']);
1450
				unset($cflink['realtime']);
1451
			}
1452
		}
1453
		if ($this->GetUpperlimit() <> "") {
1454
			if ($this->GetU_m1() <> "") {
1455
				$cflink['upperlimit1'] = $this->GetU_m1();
1456
				$cflink['upperlimit2'] = $this->GetU_d();
1457
				$cflink['upperlimit'] = "on";
1458
			} else {
1459
				unset($cflink['upperlimit']);
1460
				unset($cflink['upperlimit1']);
1461
				unset($cflink['upperlimit2']);
1462
			}
1463
			if ($this->GetU_m2() <> "") {
1464
				$cflink['upperlimit3'] = $this->GetU_m2();
1465
				$cflink['upperlimit'] = "on";
1466
			} else {
1467
				unset($cflink['upperlimit3']);
1468
				unset($cflink['upperlimit']);
1469
			}
1470
		}
1471

    
1472
		if (is_array($this->subqueues)) {
1473
			$cflinkp['queue'] = array();
1474
			foreach ($this->subqueues as $q) {
1475
				$cflink['queue'][$q->GetQname()] = array();
1476
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1477
			}
1478
		}
1479
	}
1480

    
1481
	function delete_queue() { 
1482
		unref_on_altq_queue_list($this->GetQname());
1483
		$tmpvalue = $this->GetDefault();
1484
		if (!empty($tmpvalue)) 
1485
			altq_set_default_queue($this->GetInterface(), "false");
1486
		cleanup_queue_from_rules($this->GetQname());
1487
		$parent =& $this->GetParent();
1488
		foreach ($this->subqueues as $q)  {
1489
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1490
			$q->delete_queue();
1491
		}
1492
		unset_object_by_reference($this->GetLink());
1493
	}
1494

    
1495
	/*
1496
	 * Should search even its children
1497
	 */
1498
	function &find_queue($interface, $qname) {
1499
		if ($qname == $this->GetQname()) 
1500
			return $this;
1501

    
1502
		foreach ($this->subqueues as $q) {
1503
			$result =& $q->find_queue("", $qname);
1504
			if ($result)
1505
				return $result;
1506
		}
1507
	}
1508

    
1509
	function &find_parentqueue($interface, $qname) {
1510
		if ($this->subqueues[$qname]) 
1511
			return $this;
1512
		foreach ($this->subqueues as $q) {
1513
			$result = $q->find_parentqueue("", $qname);
1514
			if ($result)
1515
				return $result;
1516
		}
1517
	}
1518
	
1519
	function validate_input($data, &$input_errors) {
1520
		parent::validate_input($data, $input_errors);
1521
		
1522
		$reqdfields[] = "bandwidth";
1523
		$reqdfieldsn[] = "Bandwidth";
1524
		$reqdfields[] = "bandwidthtype";
1525
		$reqdfieldsn[] = "Bandwidthtype";
1526

    
1527
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1528
		
1529
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1530
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1531
                        	$input_errors[] = "Bandwidth must be an integer.";
1532

    
1533
                	if ($data['bandwidth'] < 0)
1534
                        	$input_errors[] = "Bandwidth cannot be negative.";
1535

    
1536
			if ($data['bandwidthtype'] == "%") {
1537
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1538
					$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1539
			}
1540
		/*
1541
			$parent =& $this->GetParent();
1542
			switch ($data['bandwidthtype']) {
1543
			case "%":
1544
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1545
			default:
1546
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1547
				break;
1548
			}
1549
			if ($parent->GetAvailableBandwidth() < $myBw)
1550
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1551
		*/
1552
		}
1553

    
1554
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1555
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1556
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1557
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1558
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1559
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1560
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1561
			$input_errors[] = ("upperlimit d value needs to be numeric");
1562
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1563
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1564

    
1565
		/*
1566
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1567
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1568
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1569
			if (floatval($bw_1) < floatval($bw_2)) 
1570
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1571

    
1572
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1573
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1574
		}
1575
		*/
1576
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1577
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1578
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1579
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1580
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1581
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1582
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1583
			$input_errors[] = ("linkshare d value needs to be numeric");
1584
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1585
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1586
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1587
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1588
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1589
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1590

    
1591
		/*
1592
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1593
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1594
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1595
                	if (floatval($bw_1) < floatval($bw_2))
1596
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1597

    
1598
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1599
                        	$input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1600
		}
1601
		*/
1602

    
1603
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1604
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1605
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1606
			$input_errors[] = ("realtime d value needs to be numeric");
1607
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1608
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1609

    
1610
		/*
1611
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1612
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1613
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1614
                	if (floatval($bw_1) < floatval($bw_2))
1615
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1616

    
1617
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1618
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1619
		}
1620
		*/
1621

    
1622
	}
1623

    
1624
	function ReadConfig(&$cflink) {
1625
		if (!empty($cflink['linkshare'])) {
1626
			if (!empty($cflink['linkshare1'])) {
1627
				$this->SetL_m1($cflink['linkshare1']);
1628
                                $this->SetL_d($cflink['linkshare2']);
1629
				$this->SetLinkshare();
1630
			} else {
1631
				$this->SetL_m1("");
1632
                                $this->SetL_d("");
1633
				$this->DisableLinkshare();
1634
			}
1635
			if (!empty($cflink['linkshare3'])) {
1636
                                $this->SetL_m2($cflink['linkshare3']);
1637
				$this->SetLinkshare();
1638
			}
1639
		} else
1640
			$this->DisableLinkshare();
1641
		if (!empty($cflink['realtime'])) {
1642
                        if (!empty($cflink['realtime1'])) {
1643
                                $this->SetR_m1($cflink['realtime1']);
1644
                                $this->SetR_d($cflink['realtime2']);
1645
				$this->SetRealtime();
1646
			} else {
1647
                                $this->SetR_m1("");
1648
                                $this->SetR_d("");
1649
				$this->DisableRealtime();
1650
			}
1651
                        if (!empty($cflink['realtime3'])) {
1652
                                $this->SetR_m2($cflink['realtime3']);
1653
				$this->SetRealtime();
1654
			}
1655
		} else
1656
			$this->DisableRealtime(); 
1657
		if (!empty($cflink['upperlimit'])) {
1658
                        if (!empty($cflink['upperlimit1'])) {
1659
                                $this->SetU_m1($cflink['upperlimit1']);
1660
                                $this->SetU_d($cflink['upperlimit2']);
1661
				$this->SetUpperlimit();
1662
			} else {
1663
                                $this->SetU_m1("");
1664
                                $this->SetU_d("");
1665
				$this->DisableUpperlimit();
1666
			}
1667
                        if (!empty($cflink['upperlimit3'])) {
1668
                                $this->SetU_m2($cflink['upperlimit3']);
1669
				$this->SetUpperlimit();
1670
			}
1671
		} else
1672
			$this->DisableUpperlimit();
1673
		parent::ReadConfig($cflink);
1674
	}
1675

    
1676
	function build_tree() {
1677
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1678
		$tree .= "\" ";
1679
		$tmpvalue = $this->GetDefault();
1680
		if (!empty($tmpvalue))
1681
			$tree .= " class=\"navlnk\"";
1682
		$tree .= " >" . $this->GetQname() . "</a>";
1683
		if (is_array($this->subqueues)) {
1684
			$tree .= "<ul>";
1685
			foreach ($this->subqueues as $q)  {
1686
				$tree .= $q->build_tree();
1687
			}	
1688
			$tree .= "</ul>";
1689
		}
1690
		$tree .= "</li>";
1691
		return $tree;
1692
	}
1693

    
1694
	/* Even this should take children into consideration */
1695
	function build_rules(&$default = false) {
1696

    
1697
		$pfq_rule = " queue ". $this->qname;
1698
		if ($this->GetInterface())
1699
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1700
		if ($this->GetBandwidth() && $this->GetBwscale())
1701
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1702
				
1703
		$tmpvalue = $this->GetQlimit();
1704
		if (!empty($tmpvalue))
1705
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1706
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1707
			$pfq_rule .= " hfsc ( ";
1708
			$tmpvalue = $this->GetRed();
1709
			if (!empty($tmpvalue)) {
1710
				$comma = 1;
1711
				$pfq_rule .= " red ";
1712
			}
1713
			
1714
			$tmpvalue = $this->GetRio();
1715
			if (!empty($tmpvalue)) {
1716
				if ($comma) 
1717
					$pfq_rule .= " ,";
1718
				$comma = 1;
1719
				$pfq_rule .= " rio ";
1720
			}
1721
			$tmpvalue = $this->GetEcn();
1722
			if (!empty($tmpvalue)) {
1723
				if ($comma) 
1724
					$pfq_rule .= " ,";
1725
				$comma = 1;
1726
				$pfq_rule .= " ecn ";
1727
			}
1728
			$tmpvalue = $this->GetDefault();
1729
			if (!empty($tmpvalue)) {
1730
				if ($comma)
1731
					$pfq_rule .= " ,";
1732
				$comma = 1;
1733
				$pfq_rule .= " default ";
1734
				$default = true;
1735
			}
1736

    
1737
			if ($this->GetRealtime() <> "")  {
1738
				if ($comma) 
1739
					$pfq_rule .= " , ";
1740
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1741
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1742
				else  if ($this->GetR_m2() <> "")
1743
					$pfq_rule .= " realtime " . $this->GetR_m2();
1744
				$comma = 1;
1745
			}
1746
			if ($this->GetLinkshare() <> "") {
1747
				if ($comma)
1748
					$pfq_rule .= " ,";
1749
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1750
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1751
				else if ($this->GetL_m2() <> "")
1752
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1753
				$comma = 1;
1754
			}
1755
			if ($this->GetUpperlimit() <> "") {
1756
				if ($comma)
1757
					$pfq_rule .= " ,";
1758
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1759
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1760
				else if ($this->GetU_m2() <> "")
1761
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1762
			}
1763
			$pfq_rule .= " ) ";
1764
		}
1765
		if (count($this->subqueues)) {
1766
			$i = count($this->subqueues);
1767
			$pfq_rule .= " { ";
1768
			foreach ($this->subqueues as $qkey => $qnone) {
1769
				if ($i > 1) {
1770
					$i--;
1771
					$pfq_rule .= " {$qkey}, ";
1772
				} else
1773
					$pfq_rule .= " {$qkey} ";
1774
			}
1775
			$pfq_rule .= " } \n";
1776
			foreach ($this->subqueues as $q)
1777
				$pfq_rule .= $q->build_rules(&$default);
1778
		}
1779

    
1780
		 $pfq_rule .= " \n";
1781
			
1782
		return $pfq_rule;
1783
	}
1784

    
1785
	function build_javascript() {
1786
		$javascript = parent::build_javascript();
1787
		$javascript .= "<script type=\"text/javascript\">";
1788
		$javascript .= "function enable_realtime(enable_over) { \n";
1789
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1790
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1791
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1792
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1793
		$javascript .= " } else { \n";
1794
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1795
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1796
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1797
		$javascript .= " } \n";
1798
		$javascript .= " } \n";
1799
		$javascript .= "function enable_linkshare(enable_over) { \n";
1800
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1801
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1802
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1803
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1804
		$javascript .= " } else { \n";
1805
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1806
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1807
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1808
		$javascript .= " } \n";
1809
		$javascript .= " } \n";
1810
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1811
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1812
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1813
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1814
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1815
		$javascript .= " } else { \n";
1816
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1817
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1818
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1819
		$javascript .= " } \n";
1820
			
1821
		$javascript .= "} \n";
1822
		$javascript .= "</script>";
1823

    
1824
		return $javascript;
1825
	}
1826

    
1827
	function build_form() {
1828
		$form = parent::build_form();
1829
		$form .= "<tr>";
1830
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
1831
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1832
		$form .= htmlspecialchars($this->GetBandwidth());
1833
		$form .= "\">";
1834
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1835
		$form .= "<option value=\"Gb\"";
1836
		if ($this->GetBwscale() == "Gb")
1837
			$form .= " selected=\"yes\"";
1838
		$form .= ">Gbit/s</option>";
1839
		$form .= "<option value=\"Mb\"";
1840
		if ($this->GetBwscale() == "Mb")
1841
			$form .= " selected=\"yes\"";
1842
		$form .= ">Mbit/s</option>";
1843
		$form .= "<option value=\"Kb\"";
1844
		if ($this->GetBwscale() == "Kb")
1845
			$form .= " selected=\"yes\"";
1846
		$form .= ">Kbit/s</option>";
1847
		$form .= "<option value=\"\"";
1848
		if ($this->GetBwscale() == "b")
1849
			$form .= " selected=\"yes\"";
1850
		$form .= ">Bit/s</option>";
1851
		$form .= "<option value=\"%\"";
1852
		if ($this->GetBwscale() == "%")
1853
			$form .= " selected=\"yes\"";
1854
		$form .= ">%</option>";
1855
		$form .= "</select> <br>";
1856
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
1857
		$form .= "</span></td></tr>";
1858
		$form .= "<tr>";
1859
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Service Curve (sc)</td>";
1860
		$form .= "<td width=\"78%\" class=\"vtable\">";
1861
		$form .= "<table>";
1862
		$form .= "<tr><td>&nbsp;</td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>";
1863
		$form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\"";
1864
		if($this->GetUpperlimit()<> "") 
1865
			$form .=  " CHECKED ";
1866
		$form .= "onChange=\"enable_upperlimit()\"> Upperlimit:</td><td><input size=\"6\" value=\"";
1867
		$form .= htmlspecialchars($this->GetU_m1());
1868
		$form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" ";
1869
		if ($this->GetUpperlimit() == "")
1870
			$form .= " disabled";
1871
		$form .= "></td><td><input size=\"6\" value=\"";
1872
		$form .= htmlspecialchars($this->GetU_d());
1873
		$form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" ";
1874
		if ($this->GetUpperlimit() == "")
1875
			$form .= " disabled";
1876
		$form .= "></td><td><input size=\"6\" value=\"";
1877
		$form .= htmlspecialchars($this->GetU_m2());
1878
		$form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" ";
1879
		if ($this->GetUpperlimit() == "")
1880
			$form .= " disabled";
1881
		$form .= "></td><td>The maximum allowed bandwidth for the queue.</td></tr>";
1882
		$form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\"";
1883
		if($this->GetRealtime() <> "") 
1884
			$form .=  " CHECKED ";
1885
		$form .= "onChange=\"enable_realtime()\"> Real time:</td><td><input size=\"6\" value=\"";
1886
		$form .= htmlspecialchars($this->GetR_m1());
1887
		$form .= "\" id=\"realtime1\" name=\"realtime1\" ";
1888
		if ($this->GetRealtime() == "")
1889
			$form .= " disabled";
1890
		$form .= "></td><td><input size=\"6\" value=\"";
1891
		$form .= htmlspecialchars($this->GetR_d());
1892
		$form .= "\" id=\"realtime2\" name=\"realtime2\" ";
1893
		if ($this->GetRealtime() == "")
1894
			$form .= " disabled";
1895
		$form .= "></td><td><input size=\"6\" value=\"";
1896
		$form .= htmlspecialchars($this->GetR_m2());
1897
		$form .= "\" id=\"realtime3\" name=\"realtime3\" ";
1898
		if ($this->GetRealtime() == "")
1899
			$form .= " disabled";
1900
		$form .= "></td><td>The minimum required bandwidth for the queue.</td></tr>";
1901
		$form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" id=\"linkshare\" name=\"linkshare\"";
1902
		if($this->GetLinkshare() <> "") 
1903
			$form .=  " CHECKED ";
1904
		$form .= "onChange=\"enable_linkshare()\"> Link share:</td><td><input size=\"6\" value=\"";
1905
		$form .= htmlspecialchars($this->GetL_m1());
1906
		$form .= "\" id=\"linkshare1\" name=\"linkshare1\" ";
1907
		if ($this->GetLinkshare() == "")
1908
			$form .= " disabled";
1909
		$form .= "></td><td><input size=\"6\" value=\"";
1910
		$form .= htmlspecialchars($this->GetL_d());
1911
		$form .= "\" id=\"linkshare2\" name=\"linkshare2\" ";
1912
		if ($this->GetLinkshare() == "")
1913
			$form .= " disabled";
1914
		$form .= "></td><td><input size=\"6\" value=\"";
1915
		$form .= htmlspecialchars($this->GetL_m2());
1916
		$form .= "\" id=\"linkshare3\" name=\"linkshare3\" ";
1917
		if ($this->GetLinkshare() == "")
1918
			$form .= " disabled";
1919
		$form .= "></td><td>The bandwidth share of a backlogged queue - this overrides priority.</td></tr>";
1920
		$form .= "</table><br>";
1921
		$form .= "The format for service curve specifications is (m1, d, m2).  m2 controls";
1922
		$form .= "the bandwidth assigned to the queue.  m1 and d are optional and can be";
1923
		$form .= "used to control the initial bandwidth assignment.  For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value";
1924
		$form .= "given in m2.";
1925
		$form .= "</span></td>";
1926
		$form .= "</tr>";
1927

    
1928
		return $form;
1929
	}
1930

    
1931
	function update_altq_queue_data(&$data) { 
1932
		$this->ReadConfig($data);
1933
	}
1934

    
1935
	function wconfig() {
1936
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1937
		if (!is_array($cflink))
1938
			$cflink = array();
1939
		$cflink['name'] = $this->GetQname();
1940
		$cflink['interface'] = $this->GetInterface();
1941
		$cflink['qlimit'] = trim($this->GetQlimit());
1942
		if (empty($cflink['qlimit']))
1943
			unset($cflink['qlimit']);
1944
		$cflink['priority'] = $this->GetQpriority();
1945
		if (empty($cflink['priority']))
1946
			unset($cflink['priority']);
1947
		$cflink['description'] = $this->GetDescription();
1948
		if (empty($cflink['description']))
1949
			unset($cflink['description']);
1950
		$cflink['bandwidth'] = $this->GetBandwidth();
1951
		$cflink['bandwidthtype'] = $this->GetBwscale();
1952
		$cflink['enabled'] = $this->GetEnabled();
1953
		if (empty($cflink['enabled']))
1954
			unset($cflink['enabled']);
1955
		$cflink['default'] = $this->GetDefault();
1956
		if (empty($cflink['default']))
1957
			unset($cflink['default']);
1958
		$cflink['red'] = trim($this->GetRed());
1959
		if (empty($cflink['red']))
1960
			unset($cflink['red']);
1961
		$cflink['rio'] = $this->GetRio();
1962
		if (empty($cflink['rio']))
1963
			unset($cflink['rio']);
1964
		$cflink['ecn'] = trim($this->GetEcn());
1965
		if (empty($cflink['ecn']))
1966
			unset($cflink['ecn']);
1967
		if ($this->GetLinkshare() <> "") {
1968
			if ($this->GetL_m1() <> "") {
1969
				$cflink['linkshare1'] = $this->GetL_m1();
1970
				$cflink['linkshare2'] = $this->GetL_d();
1971
				$cflink['linkshare'] = "on";
1972
			} else {
1973
				unset($cflink['linkshare']);
1974
				unset($cflink['linkshare1']);
1975
				unset($cflink['linkshare2']);
1976
			}
1977
			if ($this->GetL_m2() <> "") {
1978
				$cflink['linkshare3'] = $this->GetL_m2();
1979
				$cflink['linkshare'] = "on";
1980
			} else {
1981
				unset($cflink['linkshare']);
1982
				unset($cflink['linkshare3']);
1983
			}
1984
		} else {
1985
			unset($cflink['linkshare']);
1986
			unset($cflink['linkshare1']);
1987
			unset($cflink['linkshare2']);
1988
			unset($cflink['linkshare3']);
1989
		}
1990
		if ($this->GetRealtime() <> "") {
1991
			if ($this->GetR_m1() <> "") {
1992
				$cflink['realtime1'] = $this->GetR_m1();
1993
				$cflink['realtime2'] = $this->GetR_d();
1994
				$cflink['realtime'] = "on";
1995
			} else {
1996
				unset($cflink['realtime']);
1997
				unset($cflink['realtime1']);
1998
				unset($cflink['realtime2']);
1999
			}
2000
			if ($this->GetR_m2() <> "") {
2001
				$cflink['realtime3'] = $this->GetR_m2();
2002
				$cflink['realtime'] = "on";
2003
			} else {
2004
				unset($cflink['realtime']);
2005
				unset($cflink['realtime3']);
2006
			}
2007
		} else {
2008
			unset($cflink['realtime']);
2009
			unset($cflink['realtime1']);
2010
			unset($cflink['realtime2']);
2011
			unset($cflink['realtime3']);
2012
		}
2013
		if ($this->GetUpperlimit() <> "") {
2014
			if ($this->GetU_m1() <> "") {
2015
				$cflink['upperlimit1'] = $this->GetU_m1();
2016
				$cflink['upperlimit2'] = $this->GetU_d();
2017
				$cflink['upperlimit'] = "on";
2018
			} else {
2019
				unset($cflink['upperlimit']);
2020
				unset($cflink['upperlimit1']);
2021
				unset($cflink['upperlimit2']);
2022
			}
2023
			if ($this->GetU_m2() <> "") {
2024
				$cflink['upperlimit3'] = $this->GetU_m2();
2025
				$cflink['upperlimit'] = "on";
2026
			} else {
2027
				unset($cflink['upperlimit']);
2028
				unset($cflink['upperlimit3']);
2029
			}
2030
		} else {
2031
			unset($cflink['upperlimit']);
2032
			unset($cflink['upperlimit1']);
2033
			unset($cflink['upperlimit2']);
2034
			unset($cflink['upperlimit3']);
2035
		}
2036
	}
2037
}
2038

    
2039
class cbq_queue extends priq_queue {
2040
	var $qborrow = "";
2041

    
2042
	function GetBorrow() {
2043
		return $this->qborrow;
2044
	}
2045
	function SetBorrow($borrow) {
2046
		$this->qborrow = $borrow;
2047
	}
2048
	function CanHaveChildren() {
2049
		return true;
2050
	}
2051

    
2052
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2053

    
2054
		if (!is_array($this->subqueues))
2055
			$this->subqueues = array();
2056
		$q =& new cbq_queue();
2057
		$q->SetInterface($this->GetInterface());
2058
		$q->SetParent(&$this);
2059
		$q->ReadConfig($qname);
2060
                $q->validate_input($qname, $input_errors);
2061
                if (count($input_errors)) {
2062
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2063
                        return $q;
2064
                }
2065
                switch ($q->GetBwscale()) {
2066
                case "%":
2067
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2068
                        break;
2069
                default:
2070
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2071
                        break;
2072
                }
2073
                $q->SetAvailableBandwidth($myBw);
2074
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2075

    
2076
		$q->SetEnabled("on");
2077
		$q->SetLink($path);
2078
		$this->subqueues[$q->GetQName()] = &$q;
2079
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2080
		if (is_array($qname['queue'])) {
2081
			foreach ($qname['queue'] as $key1 => $que) {
2082
				array_push($path, $key1);
2083
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2084
				array_pop($path);
2085
			}
2086
		}
2087

    
2088
		return $q;
2089
	}
2090

    
2091
	function copy_queue($interface, &$cflink) {
2092

    
2093
		$cflink['interface'] = $interface;
2094
		$cflink['qlimit'] = trim($this->GetQlimit());
2095
		if (empty($clink['qlimit']))
2096
			unset($cflink['qlimit']);
2097
		$cflink['priority'] = trim($this->GetQpriority());
2098
		if (empty($cflink['priority']))
2099
			unset($cflink['priority']);
2100
		$cflink['name'] = $this->GetQname();
2101
		$cflink['description'] = trim($this->GetDescription());
2102
		if (empty($cflink['description']))
2103
			unset($cflink['description']);
2104
		$cflink['bandwidth'] = $this->GetBandwidth();
2105
		$cflink['bandwidthtype'] = $this->GetBwscale();
2106
		$cflink['enabled'] = trim($this->GetEnabled());
2107
		if (empty($cflink['enabled']))
2108
			unset($cflink['enabled']);
2109
		$cflink['default'] = trim($this->GetDefault());
2110
		if (empty($cflink['default']))
2111
			unset($cflink['default']);
2112
		$cflink['red'] = trim($this->GetRed());
2113
		if (empty($cflink['red']))
2114
			unset($cflink['red']);
2115
		$cflink['rio'] = trim($this->GetRio());
2116
		if (empty($cflink['rio']))
2117
			unset($cflink['rio']);
2118
		$cflink['ecn'] = trim($this->GetEcn());
2119
		if (empty($cflink['ecn']))
2120
			unset($cflink['ecn']);
2121
		$cflink['borrow'] = trim($this->GetBorrow());
2122
		if (empty($cflink['borrow']))
2123
			unset($cflink['borrow']);
2124
		if (is_array($this->queues)) {
2125
			$cflinkp['queue'] = array();
2126
			foreach ($this->subqueues as $q) {
2127
				$cflink['queue'][$q->GetQname()] = array();
2128
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
2129
			}
2130
		}
2131
	}
2132
	
2133
	/*
2134
	 * Should search even its children
2135
	 */
2136
	function &find_queue($interface, $qname) {
2137
		if ($qname == $this->GetQname())
2138
			return $this;
2139
		foreach ($this->subqueues as $q) {
2140
			$result =& $q->find_queue("", $qname);
2141
			if ($result)
2142
				return $result;
2143
		}
2144
	}
2145

    
2146
	function &find_parentqueue($interface, $qname) {
2147
		if ($this->subqueues[$qname])
2148
			return $this;
2149
		foreach ($this->subqueues as $q) {
2150
			$result = $q->find_parentqueue("", $qname);
2151
			if ($result)
2152
				return $result;
2153
		}
2154
	}
2155

    
2156
	function delete_queue() {
2157
		unref_on_altq_queue_list($this->GetQname());
2158
		if ($this->GetDefault())
2159
			altq_set_default_queue($this->GetInterface(), "false");
2160
		cleanup_queue_from_rules($this->GetQname());
2161
		foreach ($this->subqueues as $q) {
2162
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2163
			$q->delete_queue();
2164
		}
2165
		unset_object_by_reference($this->GetLink());
2166
	}
2167
	
2168
	function validate_input($data, &$input_errors) {
2169
		parent::validate_input($data, $input_errors);
2170
		
2171
		if ($data['priority'] > 7)
2172
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2173
		$reqdfields[] = "bandwidth";
2174
		$reqdfieldsn[] = "Bandwidth";
2175
		$reqdfields[] = "bandwidthtype";
2176
		$reqdfieldsn[] = "Bandwidthtype";
2177

    
2178
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2179
		
2180
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2181
			$input_errors[] = "Bandwidth must be an integer.";
2182

    
2183

    
2184
		if ($data['bandwidth'] < 0)
2185
                       $input_errors[] = "Bandwidth cannot be negative.";
2186

    
2187
		if ($data['bandwidthtype'] == "%") {
2188
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2189
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2190
		}
2191

    
2192
/*
2193
           $parent =& $this->GetParent();
2194
           switch ($data['bandwidthtype']) {
2195
                       case "%":
2196
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2197
                       default:
2198
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2199
                             break;
2200
           }
2201
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2202
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2203
*/
2204
	}
2205

    
2206
	function ReadConfig(&$q) {
2207
		parent::ReadConfig($q);
2208
		if (!empty($q['borrow']))
2209
			$this->SetBorrow("on");
2210
		else
2211
			$this->SetBorrow("");
2212
	}
2213
		
2214
	function build_javascript() {
2215
		return parent::build_javascript();
2216
	}
2217

    
2218
	function build_tree() {
2219
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2220
		$tree .= "\" ";
2221
		$tmpvalue = trim($this->GetDefault());
2222
		if (!empty($tmpvalue))
2223
			$tree .= " class=\"navlnk\"";
2224
		$tree .= " >" . $this->GetQname() . "</a>";
2225
		if (is_array($this->subqueues)) {
2226
			$tree .= "<ul>";
2227
			foreach ($this->subqueues as $q)  {
2228
				$tree .= $q->build_tree();
2229
			}	
2230
			$tree .= "</ul>";
2231
		}
2232
		$tree .= "</li>";
2233
		return $tree;
2234
	}
2235
		
2236
	/* Even this should take children into consideration */
2237
	function build_rules(&$default = false) {
2238
		$pfq_rule = "queue ". $this->qname;
2239
		if ($this->GetInterface())
2240
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2241
		if ($this->GetBandwidth() && $this->GetBwscale())
2242
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2243
		$tmpvalue = $this->GetQpriority();
2244
		if (!empty($tmpvalue))
2245
			$pfq_rule .= " priority " . $this->GetQpriority();
2246
		$tmpvalue = trim($this->GetQlimit());
2247
		if (!empty($tmpvalue))
2248
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2249
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow()) {
2250
			$pfq_rule .= " cbq ( ";
2251
			$tmpvalue = trim($this->GetRed());
2252
			if (!empty($tmpvalue)) {
2253
				$comma = 1;
2254
				$pfq_rule .= " red ";
2255
			}
2256
			$tmpvalue = trim($this->GetRio());
2257
			if (!empty($tmpvalue)) {
2258
				if ($comma) 
2259
					$pfq_rule .= " ,";
2260
				$comma = 1;
2261
				$pfq_rule .= " rio ";
2262
			}
2263
			$tmpvalue = trim($this->GetEcn());
2264
			if (!empty($tmpvalue)) {
2265
				if ($comma) 
2266
					$pfq_rule .= " ,";
2267
				$comma = 1;
2268
				$pfq_rule .= " ecn ";
2269
			}
2270
			$tmpvalue = trim($this->GetDefault());
2271
			if (!empty($tmpvalue)) {
2272
				if ($comma)
2273
					$pfq_rule .= " ,";
2274
				$comma = 1;
2275
				$pfq_rule .= " default ";
2276
				$default = true;
2277
			}
2278
			$tmpvalue = trim($this->GetBorrow());
2279
			if (!empty($tmpvalue)) {
2280
				if ($comma)
2281
					$pfq_rule .= ", ";
2282
				$pfq_rule .= " borrow ";
2283
			}
2284
			$pfq_rule .= " ) ";
2285
		} 
2286
		if (count($this->subqueues)) {
2287
			$i = count($this->subqueues);
2288
			$pfq_rule .= " { ";
2289
			foreach ($this->subqueues as $qkey => $qnone) {
2290
				if ($i > 1) {
2291
					$i--;
2292
					$pfq_rule .= " {$qkey}, ";
2293
				} else
2294
					$pfq_rule .= " {$qkey} ";
2295
			}
2296
			$pfq_rule .= " } \n";
2297
			foreach ($this->subqueues as $q)
2298
				$pfq_rule .= $q->build_rules($default);
2299
		}
2300

    
2301
		$pfq_rule .= " \n";
2302
		return $pfq_rule;
2303
	}
2304

    
2305
	function build_form() {
2306
		$form = parent::build_form();
2307
		$form .= "<tr>";
2308
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2309
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2310
		if ($this->GetBandwidth() > 0)
2311
			$form .= htmlspecialchars($this->GetBandwidth());
2312
		$form .= "\">";
2313
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2314
		$form .= "<option value=\"Gb\"";
2315
		if ($this->GetBwscale() == "Gb")
2316
			$form .= " selected=\"yes\"";
2317
		$form .= ">Gbit/s</option>";
2318
		$form .= "<option value=\"Mb\"";
2319
		if ($this->GetBwscale() == "Mb")
2320
			$form .= " selected=\"yes\"";
2321
		$form .= ">Mbit/s</option>";
2322
		$form .= "<option value=\"Kb\"";
2323
		if ($this->GetBwscale() == "Kb")
2324
			$form .= " selected=\"yes\"";
2325
		$form .= ">Kbit/s</option>";
2326
		$form .= "<option value=\"\"";
2327
		if ($this->GetBwscale() == "b")
2328
			$form .= " selected=\"yes\"";
2329
		$form .= ">Bit/s</option>";
2330
		$form .= "<option value=\"%\"";
2331
		if ($this->GetBwscale() == "%")
2332
			$form .= " selected=\"yes\"";
2333
		$form .= ">%</option>";
2334
		$form .= "</select> <br>";
2335
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2336
		$form .= "</span></td></tr>";
2337
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2338
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2339
		if($this->GetBorrow() == "on") 
2340
			$form .=  " CHECKED ";
2341
		$form .= "> Borrow from other queues when available<br></td></tr>";
2342

    
2343
		return $form;
2344
	}
2345

    
2346
	function update_altq_queue_data(&$data) { 
2347
		$this->ReadConfig($data);
2348
	}
2349

    
2350
	function wconfig() {
2351
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2352
		if (!is_array($cflink))
2353
			$cflink = array();
2354
		$cflink['interface'] = $this->GetInterface();
2355
		$cflink['qlimit'] = trim($this->GetQlimit());
2356
		if (empty($cflink['qlimit']))
2357
			unset($cflink['qlimit']);
2358
		$cflink['priority'] = $this->GetQpriority();
2359
		if (empty($cflink['priority']))
2360
			unset($cflink['priority']);
2361
		$cflink['name'] = $this->GetQname();
2362
		$cflink['description'] = $this->GetDescription();
2363
		if (empty($cflink['description']))
2364
			unset($cflink['description']);
2365
		$cflink['bandwidth'] = $this->GetBandwidth();
2366
		$cflink['bandwidthtype'] = $this->GetBwscale();
2367
		$cflink['enabled'] = trim($this->GetEnabled());
2368
		if (empty($cflink['enabled']))
2369
			unset($cflink['enabled']);
2370
		$cflink['default'] = trim($this->GetDefault());
2371
		if (empty($cflink['default']))
2372
			unset($cflink['default']);
2373
		$cflink['red'] = trim($this->GetRed());
2374
		if (empty($cflink['red']))
2375
			unset($cflink['red']);
2376
		$cflink['rio'] = trim($this->GetRio());
2377
		if (empty($cflink['rio']))
2378
			unset($cflink['rio']);
2379
		$cflink['ecn'] = trim($this->GetEcn());
2380
		if (empty($cflink['ecn']))
2381
			unset($cflink['ecn']);
2382
		$cflink['borrow'] = trim($this->GetBorrow());
2383
		if (empty($cflink['borrow']))
2384
			unset($cflink['borrow']);
2385
	}
2386
}
2387

    
2388
class fairq_queue extends priq_queue {
2389
	var $hogs;
2390
	var $buckets;
2391

    
2392
	function GetBuckets() {
2393
		return $this->buckets;
2394
	}
2395
	function SetBuckets($buckets) {
2396
		$this->buckets = $buckets;
2397
	}
2398
	function GetHogs() {
2399
		return $this->hogs;
2400
	}
2401
	function SetHogs($hogs) {
2402
		$this->hogs = $hogs;
2403
	}
2404
	function CanHaveChildren() {
2405
		return false;
2406
	}
2407

    
2408

    
2409
	function copy_queue($interface, &$cflink) {
2410
                $cflink['interface'] = $interface;
2411
                $cflink['qlimit'] = $this->GetQlimit();
2412
                $cflink['priority'] = $this->GetQpriority();
2413
                $cflink['name'] = $this->GetQname();
2414
                $cflink['description'] = $this->GetDescription();
2415
                $cflink['bandwidth'] = $this->GetBandwidth();
2416
                $cflink['bandwidthtype'] = $this->GetBwscale();
2417
                $cflink['enabled'] = $this->GetEnabled();
2418
                $cflink['default'] = $this->GetDefault();
2419
                $cflink['red'] = $this->GetRed();
2420
                $cflink['rio'] = $this->GetRio();
2421
                $cflink['ecn'] = $this->GetEcn();
2422
                $cflink['buckets'] = $this->GetBuckets();
2423
		$cflink['hogs'] = $this->GetHogs();
2424
	}
2425
	
2426
	/*
2427
	 * Should search even its children
2428
	 */
2429
	function &find_queue($interface, $qname) {
2430
		if ($qname == $this->GetQname())
2431
			return $this;
2432
	}
2433

    
2434
	function find_parentqueue($interface, $qname) { return; }
2435

    
2436
	function delete_queue() {
2437
		unref_on_altq_queue_list($this->GetQname());
2438
		if ($this->GetDefault())
2439
			altq_set_default_queue($this->GetInterface(), "false");
2440
		cleanup_queue_from_rules($this->GetQname());
2441
		unset_object_by_reference($this->GetLink());
2442
	}
2443
	
2444
	function validate_input($data, &$input_errors) {
2445
		parent::validate_input($data, $input_errors);
2446
		
2447
		if ($data['priority'] > 255)
2448
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2449
		$reqdfields[] = "bandwidth";
2450
		$reqdfieldsn[] = "Bandwidth";
2451
		$reqdfields[] = "bandwidthtype";
2452
		$reqdfieldsn[] = "Bandwidthtype";
2453

    
2454
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2455
		
2456
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2457
	                 $input_errors[] = "Bandwidth must be an integer.";
2458

    
2459

    
2460
	        if ($data['bandwidth'] < 0)
2461
                       $input_errors[] = "Bandwidth cannot be negative.";
2462

    
2463

    
2464
        	if ($data['bandwidthtype'] == "%") {
2465
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2466
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2467
           	}
2468

    
2469
/*
2470
           	$parent =& $this->GetParent();
2471
           	switch ($data['bandwidthtype']) {
2472
                       case "%":
2473
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2474
                       default:
2475
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2476
                             break;
2477
           	}
2478
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2479
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2480
*/
2481
	}
2482
	
2483
	function ReadConfig(&$q) {
2484
		parent::ReadConfig($q);
2485
		if (!empty($q['buckets']))
2486
			$this->SetBuckets($q['buckets']);
2487
		else
2488
			$this->SetBuckets("");
2489
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2490
			$this->SetHogs($q['hogs']);
2491
		else
2492
			$this->SetHogs("");
2493
	}
2494
		
2495
	function build_javascript() {
2496
		return parent::build_javascript();
2497
	}
2498

    
2499
	function build_tree() {
2500
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2501
		$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2502
		$tree .= "\" ";
2503
		$tmpvalue = trim($this->GetDefault());
2504
		if (!empty($tmpvalue))
2505
			$tree .= " class=\"navlnk\"";
2506
		$tree .= " >" . $this->GetQname() . "</a>";
2507
		$tree .= "</li>";
2508
		return $tree;
2509
	}
2510
		
2511
	/* Even this should take children into consideration */
2512
	function build_rules(&$default = false) {
2513
		$pfq_rule = "queue ". $this->qname;
2514
		if ($this->GetInterface())
2515
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2516
		if ($this->GetBandwidth() && $this->GetBwscale())
2517
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2518
		$tmpvalue = trim($this->GetQpriority());
2519
		if (!empty($tmpvalue))
2520
			$pfq_rule .= " priority " . $this->GetQpriority();
2521
		$tmpvalue = trim($this->GetQlimit());
2522
		if (!empty($tmpvalue))
2523
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2524
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2525
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2526
			$pfq_rule .= " fairq ( ";
2527
			$tmpvalue = trim($this->GetRed());
2528
			if (!empty($tmpvalue)) {
2529
				$comma = 1;
2530
				$pfq_rule .= " red ";
2531
			}
2532
			$tmpvalue = trim($this->GetRio());
2533
			if (!empty($tmpvalue)) {
2534
				if ($comma) 
2535
					$pfq_rule .= " ,";
2536
				$comma = 1;
2537
				$pfq_rule .= " rio ";
2538
			}
2539
			$tmpvalue = trim($this->GetEcn());
2540
			if (!empty($tmpvalue)) {
2541
				if ($comma) 
2542
					$pfq_rule .= " ,";
2543
				$comma = 1;
2544
				$pfq_rule .= " ecn ";
2545
			}
2546
			$tmpvalue = trim($this->GetDefault());
2547
			if (!empty($tmpvalue)) {
2548
				if ($comma)
2549
					$pfq_rule .= " ,";
2550
				$comma = 1;
2551
				$pfq_rule .= " default ";
2552
				$default = true;
2553
			}
2554
			$tmpvalue = trim($this->GetBuckets());
2555
			if (!empty($tmpvalue)) {
2556
				if ($comma)
2557
					$pfq_rule .= ", ";
2558
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2559
			}
2560
			$tmpvalue = trim($this->GetHogs());
2561
			if (!empty($tmpvalue)) {
2562
				if ($comma)
2563
					$pfq_rule .= ", ";
2564
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2565
			}
2566
				$pfq_rule .= " ) ";
2567
		} 
2568

    
2569
		$pfq_rule .= " \n";
2570
		return $pfq_rule;
2571
	}
2572

    
2573
	function build_form() {
2574
		$form = parent::build_form();
2575
		$form .= "<tr>";
2576
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2577
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2578
		if ($this->GetBandwidth() > 0)
2579
			$form .= htmlspecialchars($this->GetBandwidth());
2580
		$form .= "\">";
2581
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2582
		$form .= "<option value=\"Gb\"";
2583
		if ($this->GetBwscale() == "Gb")
2584
			$form .= " selected=\"yes\"";
2585
		$form .= ">Gbit/s</option>";
2586
		$form .= "<option value=\"Mb\"";
2587
		if ($this->GetBwscale() == "Mb")
2588
			$form .= " selected=\"yes\"";
2589
		$form .= ">Mbit/s</option>";
2590
		$form .= "<option value=\"Kb\"";
2591
		if ($this->GetBwscale() == "Kb")
2592
			$form .= " selected=\"yes\"";
2593
		$form .= ">Kbit/s</option>";
2594
		$form .= "<option value=\"\"";
2595
		if ($this->GetBwscale() == "b")
2596
			$form .= " selected=\"yes\"";
2597
		$form .= ">Bit/s</option>";
2598
		$form .= "<option value=\"%\"";
2599
		if ($this->GetBwscale() == "%")
2600
			$form .= " selected=\"yes\"";
2601
		$form .= ">%</option>";
2602
		$form .= "</select> <br>";
2603
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2604
		$form .= "</span></td></tr>";
2605
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2606
		$form .= "<td class=\"vtable\"><table><tr><td>";
2607
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2608
		$tmpvalue = trim($this->GetBuckets());
2609
		if(!empty($tmpvalue)) 
2610
			$form .=  $this->GetBuckets();
2611
		$form .= "\"> Number of buckets available.<br></td></tr>";
2612
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2613
		$tmpvalue = trim($this->GetHogs());
2614
		if(!empty($tmpvalue)) 
2615
			$form .=  $this->GetHogs();
2616
		$form .= "\"> Bandwidth limit for hosts to not saturate link.<br></td></tr>";
2617
		$form .= "</table></td></tr>";
2618
		return $form;
2619
	}
2620

    
2621
	function update_altq_queue_data(&$data) { 
2622
		$this->ReadConfig($data);
2623
	}
2624

    
2625
	function wconfig() {
2626
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2627
		if (!is_array($cflink))
2628
			$cflink = array();
2629
		$cflink['interface'] = $this->GetInterface();
2630
		$cflink['qlimit'] = trim($this->GetQlimit());
2631
		if (empty($cflink['qlimit']))
2632
			unset($cflink['qlimit']);
2633
		$cflink['priority'] = trim($this->GetQpriority());
2634
		if (empty($cflink['priority']))
2635
			unset($cflink['priority']);
2636
		$cflink['name'] = $this->GetQname();
2637
		$cflink['description'] = trim($this->GetDescription());
2638
		if (empty($cflink['description']))
2639
			unset($cflink['description']);
2640
		$cflink['bandwidth'] = $this->GetBandwidth();
2641
		$cflink['bandwidthtype'] = $this->GetBwscale();
2642
		$cflink['enabled'] = $this->GetEnabled();
2643
		if (empty($cflink['enabled']))
2644
			unset($cflink['enabled']);
2645
		$cflink['default'] = trim($this->GetDefault());
2646
		if (empty($cflink['default']))
2647
			unset($cflink['default']);
2648
		$cflink['red'] = trim($this->GetRed());
2649
		if (empty($cflink['red']))
2650
			unset($cflink['red']);
2651
		$cflink['rio'] = trim($this->GetRio());
2652
		if (empty($cflink['rio']))
2653
			unset($cflink['rio']);
2654
		$cflink['ecn'] = trim($this->GetEcn());
2655
		if (empty($cflink['ecn']))
2656
			unset($cflink['ecn']);
2657
		$cflink['buckets'] = trim($this->GetBuckets());
2658
		if (empty($cflink['buckets']))
2659
			unset($cflink['buckets']);
2660
		$cflink['hogs'] = trim($this->GetHogs());
2661
		if (empty($cflink['hogs']))
2662
			unset($cflink['hogs']);
2663
	}
2664
}
2665

    
2666

    
2667
/*
2668
 * dummynet(4) wrappers.
2669
 */
2670

    
2671

    
2672
/*
2673
 * List of respective objects!
2674
 */
2675
$dummynet_pipe_list = array();
2676

    
2677
class dummynet_class {
2678
        var $qname;
2679
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2680
        var $qlimit;
2681
        var $description;
2682
	var $qenabled;
2683
	var $link;
2684
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2685
        var $plr;
2686

    
2687
        var $buckets;
2688
        /* mask parameters */
2689
        var $mask;
2690
        var $noerror;
2691

    
2692
        /* Accessor functions */
2693
        function SetLink($link) {
2694
                $this->link = $link;
2695
        }
2696
        function GetLink() {
2697
                return $this->link;
2698
        }
2699
	function Getmask() {
2700
		return $this->mask;
2701
	}
2702
	function SetMask($mask) {
2703
		$this->mask = $mask;
2704
	}
2705
	function &GetParent() {
2706
		return $this->qparent;
2707
	}
2708
	function SetParent(&$parent) {
2709
		$this->qparent = &$parent;
2710
	}
2711
        function GetEnabled() {
2712
                return $this->qenabled;
2713
        }
2714
        function SetEnabled($value) {
2715
                $this->qenabled = $value;
2716
        }
2717
	function CanHaveChildren() {
2718
		return false;
2719
        }
2720
	function CanBeDeleted() {
2721
                return true;
2722
        }
2723
        function GetQname() {
2724
                return $this->qname;
2725
        }
2726
        function SetQname($name) {
2727
                $this->qname = trim($name);
2728
        }
2729
        function GetQlimit() {
2730
                return $this->qlimit;
2731
        }
2732
        function SetQlimit($limit) {
2733
               	$this->qlimit = $limit;
2734
        }
2735
        function GetDescription() {
2736
                return $this->description;
2737
        }
2738
        function SetDescription($str) {
2739
                $this->description = trim($str);
2740
        }
2741
        function GetFirstime() {
2742
                return $this->firsttime;
2743
        }
2744
        function SetFirsttime($number) {
2745
                $this->firsttime = $number;
2746
        }
2747
        function GetBuckets() {
2748
                return $this->buckets;
2749
        }
2750
        function SetBuckets($buckets) {
2751
                $this->buckets = $buckets;
2752
        }
2753
	function SetNumber($number) {
2754
		$this->qnumber = $number;
2755
	}
2756
	function GetNumber() {
2757
		return $this->qnumber;
2758
	}
2759
        function GetPlr() {
2760
                return $this->plr;
2761
        }
2762
        function SetPlr($plr) {
2763
                $this->plr = $plr;
2764
        }
2765

    
2766
	function build_javascript() { return; } /* Do not remove */
2767

    
2768
	function validate_input($data, &$input_errors) {
2769
		$reqdfields[] = "bandwidth";
2770
		$reqdfieldsn[] = "Bandwidth";
2771
		$reqdfields[] = "bandwidthtype";
2772
		$reqdfieldsn[] = "Bandwidthtype";
2773
		$reqdfields[] = "name";
2774
		$reqdfieldsn[] = "Name";
2775
	
2776
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2777

    
2778
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2779
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2780
            		$input_errors[] = "Plr must be an integer between 1 and 100.";
2781
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2782
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2783
            		$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2784
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2785
            		$input_errors[] = "Queue limit must be an integer";
2786
        	if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2787
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2788
	}
2789
}
2790

    
2791
class dnpipe_class extends dummynet_class {
2792
        var $delay;
2793
	var $qbandwidth;
2794
	var $qbandwidthtype;
2795

    
2796
		/* This is here to help on form building and building rules/lists */
2797
        var $subqueues = array();
2798

    
2799
	function CanHaveChildren() {
2800
	        return true;
2801
        }
2802
	function SetDelay($delay) {
2803
		$this->delay = $delay;
2804
	}
2805
	function GetDelay() {
2806
		return $this->delay;
2807
	}
2808
	function GetBwscale() {
2809
                return $this->qbandwidthtype;
2810
        }
2811
        function SetBwscale($scale) {
2812
               	$this->qbandwidthtype = $scale;
2813
        }		
2814
	function delete_queue() {
2815
		cleanup_dnqueue_from_rules($this->GetQname());
2816
		foreach ($this->subqueues as $q)
2817
			$q->delete_queue();
2818
		unset_dn_object_by_reference($this->GetLink());
2819
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2820
        }
2821
        function GetBandwidth() {
2822
                return $this->qbandwidth;
2823
        }
2824
        function SetBandwidth($bandwidth) {
2825
                $this->qbandwidth = $bandwidth;
2826
        }
2827

    
2828
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2829

    
2830
		if (!is_array($this->subqueues))
2831
			$this->subqueues = array();
2832
			
2833
		$q =& new dnqueue_class();
2834
		$q->SetLink($path);
2835
		$q->SetEnabled("on");
2836
		$q->SetPipe($this->GetQname());
2837
		$q->SetParent(&$this);
2838
		$q->ReadConfig($queue);
2839
		$q->validate_input($queue, $input_errors);
2840
		if (count($input_errors)) {
2841
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2842
			return $q;
2843
		}
2844
		$this->subqueues[$q->GetQname()] = &$q;
2845
            
2846
		return $q;
2847
	}
2848

    
2849
	function &get_queue_list($q = null) {
2850
		$qlist = array();
2851

    
2852
		$qlist[$this->GetQname()] = $this->GetNumber();
2853
		if (is_array($this->subqueues)) {
2854
			foreach ($this->subqueues as $queue)
2855
				$queue->get_queue_list(&$qlist);
2856
		}
2857
		return $qlist;
2858
	}
2859
		
2860
        /*
2861
         * Should search even its children
2862
         */
2863
        function &find_queue($pipe, $qname) {
2864
                if ($qname == $this->GetQname()) 
2865
                        return $this;
2866
               	foreach ($this->subqueues as $q) {
2867
                       	$result =& $q->find_queue("", $qname);
2868
						if ($result)
2869
                       	        return $result;
2870
               	}
2871
        }
2872

    
2873
	function &find_parentqueue($pipe, $qname) {
2874
		return NULL;
2875
       	}
2876

    
2877
	function validate_input($data, &$input_errors) {
2878
		parent::validate_input($data, $input_errors);
2879

    
2880
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2881
       		     	$input_errors[] = "Bandwidth must be an integer.";
2882
		if ($data['delay'] && (!is_numeric($data['delay'])))
2883
            		$input_errors[] = "Delay must be an integer.";
2884
		}
2885

    
2886
	function ReadConfig(&$q) {
2887
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
2888
			$this->SetQname($q['newname']);
2889
		} else if (!empty($q['newname'])) {
2890
			$this->SetQname($q['newname']);
2891
		} else {
2892
			$this->SetQname($q['name']);
2893
		}
2894
		$this->SetNumber($q['number']);
2895
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2896
			$this->SetBandwidth($q['bandwidth']);
2897
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2898
				$this->SetBwscale($q['bandwidthtype']);
2899
		}
2900
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2901
              		$this->SetQlimit($q['qlimit']);
2902
		else
2903
              		$this->SetQlimit("");
2904
		if (isset($q['mask']) && $q['mask'] <> "")
2905
              		$this->SetMask($q['mask']);
2906
		else
2907
              		$this->SetMask("");
2908
		if (isset($q['buckets']) && $q['buckets'] <> "")
2909
              		$this->SetBuckets($q['buckets']);
2910
		else
2911
              		$this->SetBuckets("");
2912
            	if (isset($q['plr']) && $q['plr'] <> "")
2913
            		$this->SetPlr($q['plr']);
2914
		else
2915
            		$this->SetPlr("");
2916
		if (isset($q['delay']) && $q['delay'] <> "")
2917
            		$this->SetDelay($q['delay']);
2918
		else
2919
			$this->SetDelay(0);
2920
            	if (isset($q['description']) && $q['description'] <> "")
2921
			$this->SetDescription($q['description']);
2922
		else
2923
			$this->SetDescription("");
2924
		$this->SetEnabled($q['enabled']);
2925

    
2926
        }
2927

    
2928
	function build_tree() {
2929
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2930
		$tree .= $this->GetQname() . "</a>";
2931
		if (is_array($this->subqueues)) {
2932
			$tree .= "<ul>";
2933
			foreach ($this->subqueues as $q)  {
2934
				$tree .= $q->build_tree();
2935
			}	
2936
			$tree .= "</ul>";
2937
		}
2938
		$tree .= "</li>";
2939
		
2940
		return $tree;
2941
	}
2942

    
2943
        function build_rules() {
2944
		if ($this->GetEnabled() == "")
2945
			return;
2946

    
2947
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2948
		if ($this->GetBandwidth() && $this->GetBwscale())
2949
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2950
		if ($this->GetQlimit())
2951
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2952
		if ($this->GetPlr())
2953
			$pfq_rule .= " plr " . $this->GetPlr();
2954
		if ($this->GetBuckets())
2955
			$pfq_rule .= " buckets " . $this->GetBuckets();
2956
		if ($this->GetDelay())
2957
			$pfq_rule .= " delay " . $this->GetDelay();
2958

    
2959
		$mask = $this->GetMask();
2960
		if (!empty($mask)) {
2961
			/* XXX TODO extend this to support more complicated masks */
2962
			switch ($mask) {
2963
			case 'srcaddress':
2964
				$pfq_rule .= " mask src-ip 0xffffffff ";
2965
				break;
2966
			case 'dstaddress':
2967
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2968
				break;
2969
			default:
2970
				break;
2971
			}
2972
			$pfq_rule .= "\n";
2973

    
2974
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2975
       			        foreach ($this->subqueues as $q)
2976
				$pfq_rule .= $q->build_rules();
2977
               		}
2978
    		}            
2979
		$pfq_rule .= " \n";
2980

    
2981
		return $pfq_rule;
2982
        }
2983

    
2984
	function update_dn_data(&$data) { 
2985
		$this->ReadConfig($data);
2986
	}
2987

    
2988
        function build_form() { 
2989
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
2990
                $form .= "Enable";
2991
                $form .= "</td><td class=\"vncellreq\">";
2992
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
2993
                if ($this->GetEnabled() == "on")
2994
                        $form .=  " CHECKED";
2995
                $form .= " ><span class=\"vexpl\"> Enable limiter and its children</span>";
2996
                $form .= "</td></tr>";
2997
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
2998
		$form .= "<td class=\"vncellreq\">";
2999
		$form .= "<input type=\"text\" id=\"newname\" name=\"newname\" value=\"";
3000
		$form .= $this->GetQname()."\">";
3001
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"";
3002
		$form .= $this->GetQname()."\">";
3003
		$form .= "</td></tr>";
3004
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Bandwidth";
3005
		$form .= "</td><td class=\"vncellreq\">";
3006
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
3007
		$form .= $this->GetBandwidth() . "\">"; 
3008
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
3009
		$form .= "<option value=\"Kb\"";
3010
		if ($this->GetBwscale() == "Kb")
3011
			$form .= " selected=\"yes\"";
3012
		$form .= ">Kbit/s</option>";
3013
		$form .= "<option value=\"Mb\"";
3014
		if ($this->GetBwscale() == "Mb")
3015
			$form .= " selected=\"yes\"";
3016
		$form .= ">Mbit/s</option>";
3017
		$form .= "<option value=\"Gb\"";
3018
		if ($this->GetBwscale() == "Gb")
3019
			$form .= " selected=\"yes\"";
3020
		$form .= ">Gbit/s</option>";		
3021
		$form .= "<option value=\"\"";
3022
		if ($this->GetBwscale() == "b")
3023
			$form .= " selected=\"yes\"";
3024
		$form .= ">Bit/s</option>";
3025
		$form .= "</select>";
3026
		$form .= "</td></tr>";
3027
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Mask</td>";
3028
		$form .= "<td class=\"vncellreq\">";
3029
		$form .= "<select name=\"mask\" class=\"formselect\">";
3030
		$form .= "<option value=\"none\"";
3031
		if ($this->GetMask() == "none")
3032
			$form .= " selected=\"yes\"";
3033
		$form .= ">none</option>";
3034
		$form .= "<option value=\"srcaddress\"";
3035
		if ($this->GetMask() == "srcaddress")
3036
			$form .= " selected=\"yes\"";
3037
		$form .= ">Source addresses</option>";
3038
		$form .= "<option value=\"dstaddress\"";
3039
		if ($this->GetMask() == "dstaddress")
3040
			$form .= " selected=\"yes\"";
3041
		$form .= ">Destination addresses</option>";
3042
		$form .= "</select>";
3043
		$form .= "&nbsp;<br>";
3044
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
3045
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
3046
		$form .= "be created for each source/destination IP address encountered, \n";
3047
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
3048
		$form .= "limits per host.</span>";
3049
		$form .= "</td></tr>";
3050
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
3051
		$form .= "<td class=\"vncellreq\">";
3052
		$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3053
		$form .= $this->GetDescription();
3054
		$form .= "\">";
3055
		$form .= "<br> <span class=\"vexpl\">";
3056
		$form .= "You may enter a description here ";
3057
		$form .= "for your reference (not parsed).</span>";
3058
		$form .= "</td></tr>";
3059
      		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3060
		$form .= "<td></td>";
3061
                $form .= "<td><div id=\"showadvancedboxspr\">";
3062
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3063
		$form .= " value=\"Show advanced options\"></input></a>";
3064
                $form .= "</div></td></tr>";
3065
                $form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3066

    
3067
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3068
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3069
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3070
		$form .= $this->GetDelay() . "\">";
3071
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3072
		$form .= "should specify 0 here (or leave the field empty)</span>";
3073
		$form .= "</td></tr><br/>";
3074
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3075
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3076
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3077
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3078
		$form .= $this->GetPlr() . "\">";
3079
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3080
        	$form .= "should specify 0 here (or leave the field empty).";
3081
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3082
		$form .= "</td></tr>";
3083
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3084
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3085
		$form .= "<td class=\"vncellreq\">";
3086
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3087
		$form .= $this->GetQlimit() . "\">";
3088
		$form .= "&nbsp;slots<br>";
3089
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3090
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
3091
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
3092
		$form .= "are delivered to their destination.</span>";
3093
		$form .= "</td></tr>";
3094
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3095
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3096
                $form .= "<td class=\"vncellreq\">";
3097
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3098
                $form .= $this->GetBuckets() . "\">";
3099
                $form .= "&nbsp;slots<br>";
3100
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3101
                $form .= "should leave the field empty. It increases the hash size set.";
3102
                $form .= "</td></tr>";
3103

    
3104
		return $form;
3105
			
3106
		}
3107

    
3108
	function wconfig() {
3109
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3110
            	if (!is_array($cflink))
3111
            		$cflink = array();
3112
		$cflink['name'] = $this->GetQname();
3113
		$cflink['number'] = $this->GetNumber();
3114
            	$cflink['qlimit'] = $this->GetQlimit();
3115
            	$cflink['plr'] = $this->GetPlr();
3116
            	$cflink['description'] = $this->GetDescription();
3117
		$cflink['bandwidth'] = $this->GetBandwidth();
3118
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3119
		$cflink['enabled'] = $this->GetEnabled();
3120
		$cflink['buckets'] = $this->GetBuckets();
3121
		$cflink['mask'] = $this->GetMask();
3122
		$cflink['delay'] = $this->GetDelay();
3123
	}
3124

    
3125
}
3126

    
3127
class dnqueue_class extends dummynet_class {
3128
        var $pipeparent;
3129
        var $weight;
3130

    
3131
        function GetWeight() {
3132
                return $this->weight;
3133
        }
3134
        function SetWeight($weight) {
3135
                $this->weight = $weight;
3136
        }
3137
	function GetPipe() {
3138
		return $this->pipeparent;
3139
	}
3140
	function SetPipe($pipe) {
3141
		$this->pipeparent = $pipe;
3142
	}
3143

    
3144
	/* Just a stub in case we ever try to call this from the frontend. */
3145
	function &add_queue($interface, &$queue, &$path, &$input_errors) { return; }
3146

    
3147
	function delete_queue() {
3148
		cleanup_dnqueue_from_rules($this->GetQname());
3149
		unset_dn_object_by_reference($this->GetLink());
3150
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3151
        }
3152

    
3153
	function validate_input($data, &$input_errors) {
3154
		parent::validate_input($data, $input_errors);
3155

    
3156
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3157
			($data['weight'] < 1 && $data['weight'] > 100))) 
3158
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3159
	}
3160

    
3161
        /*
3162
         * Should search even its children
3163
         */
3164
        function &find_queue($pipe, $qname) {
3165
                if ($qname == $this->GetQname()) 
3166
                	return $this;
3167
		else
3168
			return NULL;
3169
        }
3170

    
3171
	function &find_parentqueue($pipe, $qname) {
3172
		return $this->qparent;
3173
        }
3174

    
3175
        function &get_queue_list(&$qlist) {
3176
		if ($this->GetEnabled() == "")
3177
			return;
3178
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3179
        }		
3180

    
3181
	function ReadConfig(&$q) {
3182
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
3183
			$this->SetQname($q['newname']);
3184
		} else if (!empty($q['newname'])) {
3185
			$this->SetQname($q['newname']);
3186
		} else {
3187
			$this->SetQname($q['name']);
3188
		}
3189
		$this->SetNumber($q['number']);
3190
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3191
       		       	$this->SetQlimit($q['qlimit']);
3192
		else
3193
       		       	$this->SetQlimit("");
3194
		if (isset($q['mask']) && $q['mask'] <> "")
3195
              		$this->SetMask($q['mask']);
3196
		else
3197
              		$this->SetMask("");
3198
       		if (isset($q['weight']) && $q['weight'] <> "")
3199
            		$this->SetWeight($q['weight']);
3200
		else
3201
            		$this->SetWeight("");
3202
            	if (isset($q['description']) && $q['description'] <> "")
3203
			$this->SetDescription($q['description']);
3204
		else
3205
			$this->SetDescription("");
3206
		$this->SetEnabled($q['enabled']);
3207
        }
3208

    
3209
	function build_tree() {
3210
		$parent =& $this->GetParent();
3211
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3212
		$tree .= $this->GetQname() . "</a>";
3213
		$tree .= "</li>";
3214
		
3215
		return $tree;
3216
	}
3217

    
3218
        function build_rules() {
3219
		if ($this->GetEnabled() == "")
3220
			return; 
3221

    
3222
		$parent =& $this->GetParent();
3223
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3224
		if ($this->GetQlimit())
3225
                    	$pfq_rule .= " queue " . $this->GetQimit();
3226
		if ($this->GetWeight())
3227
			$pfq_rule .= " weight " . $this->GetWeight();
3228
		if ($this->GetBuckets())
3229
			$pfq_rule .= " buckets " . $this->GetBuckets();
3230
		$mask = $this->GetMask();
3231
		if (!empty($mask)) {
3232
			/* XXX TODO extend this to support more complicated masks */
3233
			switch ($mask) {
3234
			case 'srcaddress':
3235
				$pfq_rule .= " mask src-ip 0xffffffff ";
3236
				break;
3237
			case 'dstaddress':
3238
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3239
				break;
3240
			default:
3241
				break;
3242
			}
3243
			$pfq_rule .= "\n";
3244
		}
3245

    
3246
		return $pfq_rule;
3247
	}
3248

    
3249
        function build_form() { 
3250
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
3251
                $form .= "Enable/Disable";
3252
                $form .= "</td><td class=\"vncellreq\">";
3253
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
3254
                if ($this->GetEnabled() == "on")
3255
                        $form .=  " CHECKED";
3256
                $form .= " ><span class=\"vexpl\"> Enable/Disable queue and its children</span>";
3257
                $form .= "</td></tr>";
3258
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
3259
		$form .= "<td class=\"vncellreq\">";
3260
		$form .= "<input type=\"text\" id=\"newname\" name=\"newname\" value=\"";
3261
		$form .= $this->GetQname()."\">";
3262
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"";
3263
		$form .= $this->GetQname()."\">";
3264
		$form .= "</td></tr>";
3265
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Mask</td>";
3266
		$form .= "<td class=\"vncellreq\">";
3267
		$form .= "<select name=\"mask\" class=\"formselect\">";
3268
		$form .= "<option value=\"none\"";
3269
		if ($this->GetMask() == "none")
3270
			$form .= " selected=\"yes\"";
3271
		$form .= ">none</option>";
3272
		$form .= "<option value=\"srcaddress\"";
3273
		if ($this->GetMask() == "srcaddress")
3274
			$form .= " selected=\"yes\"";
3275
		$form .= ">Source addresses</option>";
3276
		$form .= "<option value=\"dstaddress\"";
3277
		if ($this->GetMask() == "dstaddress")
3278
			$form .= " selected=\"yes\"";
3279
		$form .= ">Destination addresses</option>";
3280
		$form .= "</select>";
3281
		$form .= "&nbsp;slots<br>";
3282
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
3283
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
3284
		$form .= "be created for each source/destination IP address encountered, \n";
3285
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
3286
		$form .= "limits per host.</span>";
3287
		$form .= "</td></tr>";
3288
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
3289
		$form .= "<td class=\"vncellreq\">";
3290
		$form .= "<input type=\"text\" id=\"description\" class=\"formfld unknown\" size=\"50%\" name=\"description\" value=\"";
3291
		$form .= $this->GetDescription();
3292
		$form .= "\">";
3293
		$form .= "<br> <span class=\"vexpl\">";
3294
		$form .= "You may enter a description here ";
3295
		$form .= "for your reference (not parsed).</span>";
3296
		$form .= "</td></tr>";
3297
		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3298
		$form .= "<td></td>";
3299
                $form .= "<td><div id=\"showadvancedboxspr\">";
3300
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3301
		$form .= " value=\"Show advanced options\"></input></a>";
3302
                $form .= "</div></td></tr>";
3303
		$form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3304
		$form .= "<td valign=\"center\" class=\"vncellreq\">Weight</td>";
3305
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3306
		$form .= "<input name=\"weight\" type=\"text\" id=\"weight\" size=\"5\" value=\"";
3307
		$form .= $this->GetWeight() . "\">";
3308
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: For queues under the same parent "; 
3309
		$form .= "this specifies the share that a queue gets(values range from 1 to 100, you can leave it blank otherwise)</span>";
3310
		$form .= "</td></tr>";
3311
		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3312
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3313
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3314
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3315
		$form .= $this->GetPlr() . "\">";
3316
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3317
        	$form .= "should specify 0 here (or leave the field empty).";
3318
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3319
		$form .= "</td></tr>";
3320
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3321
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3322
		$form .= "<td class=\"vncellreq\">";
3323
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3324
		$form .= $this->GetQlimit() . "\">";
3325
		$form .= "&nbsp;slots<br>";
3326
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3327
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, ";
3328
        	$form .= "then they are delayed by value specified in the Delay field, and then they ";
3329
		$form .= "are delivered to their destination.</span>";
3330
		$form .= "</td></tr>";
3331
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3332
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3333
                $form .= "<td class=\"vncellreq\">";
3334
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3335
                $form .= $this->GetBuckets() . "\">";
3336
                $form .= "&nbsp;slots<br>";
3337
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3338
                $form .= "should leave the field empty. It increases the hash size set.";
3339
                $form .= "</td></tr>";
3340

    
3341
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3342
		$form .= " value=\"" . $this->GetPipe() . "\">";
3343

    
3344
		return $form;
3345
			
3346
	}
3347

    
3348
        function update_dn_data(&$data) { 
3349
		$this->ReadConfig($data);
3350
	}
3351

    
3352
	function wconfig() {
3353
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3354
            	if (!is_array($cflink))
3355
            		$cflink = array();
3356
		$cflink['name'] = $this->GetQname();
3357
		$cflink['number'] = $this->GetNumber();
3358
            	$cflink['qlimit'] = $this->GetQlimit();
3359
            	$cflink['description'] = $this->GetDescription();
3360
		$cflink['weight'] = $this->GetWeight();
3361
		$cflink['enabled'] = $this->GetEnabled();
3362
		$cflink['buckets'] = $this->GetBuckets();
3363
		$cflink['mask'] = $this->GetMask();
3364
	}
3365
}
3366

    
3367
// List of layer7 objects
3368
$layer7_rules_list = array();
3369

    
3370
class layer7 {
3371
    
3372
    var $rname; //alias
3373
    var $rdescription; //alias description
3374
    var $rport; //divert port
3375
    var $renabled; //rule enabled
3376
    var $rsets = array(); //array of l7 associations
3377
    
3378
    // Auxiliary functions
3379
    
3380
    function GetRName() {
3381
        return $this->rname;
3382
    }
3383
    function SetRName($rname) {
3384
        $this->rname = $rname;
3385
    }
3386
    function GetRDescription() {
3387
        return $this->rdescription;
3388
    }
3389
    function SetRDescription($rdescription) {
3390
        $this->rdescription = $rdescription;
3391
    }
3392
    function GetRPort() {
3393
        return $this->rport;
3394
    }
3395
    function SetRPort($rport) {
3396
        $this->rport = $rport;
3397
    }
3398
    function GetREnabled() {
3399
        return $this->renabled;
3400
    }
3401
    function SetREnabled($value) {
3402
        $this->renabled = $value;
3403
    }
3404
    function GetRl7() {
3405
        return $this->rsets;
3406
    }
3407
    function SetRl7($rsets) {
3408
        $this->rsets = $rsets;
3409
    }
3410
    
3411
    //Add a tuple (rule,sctructure,element) to the $rsets
3412
    
3413
    function add_rule($l7set) {
3414
       	$this->rsets[] = $l7set;
3415
    }
3416
    
3417
    // Build the layer7 rules
3418
    function build_l7_rules() {
3419
        if($this->GetREnabled() == "") {
3420
            return;
3421
        }
3422
        //$l7rules = "#" . $this->rdescription . "\n";
3423
        foreach ($this->rsets as $rl7) {
3424
            $l7rules .= $rl7->build_rules();
3425
        }
3426
        return $l7rules;
3427
    }
3428
    
3429
    // Read the config from array
3430
    function ReadConfig(&$qname, &$q) {
3431
        $this->SetRName($qname);
3432
        $this->SetREnabled($q['enabled']);
3433
        $this->SetRPort($q['divert_port']);
3434
        if(isset($q['description']) && $q['description'] <> "")
3435
            $this->SetRDescription($q['description']);
3436
        $rsets = $q['l7rules'];
3437
        //Put individual rules in the array
3438
	if(is_array($rsets)) {
3439
	    $this->rsets = array(); // XXX: ugly hack
3440
	    foreach($rsets as $l7r) {
3441
	        $l7obj = new l7rule();
3442
	        $l7obj->SetRProtocol($l7r['protocol']);
3443
	        $l7obj->SetRStructure($l7r['structure']);
3444
	        $l7obj->SetRBehaviour($l7r['behaviour']);
3445
	        $this->add_rule($l7obj);
3446
	    }
3447
	}
3448
    }
3449
    
3450
    //Generate a random port for the divert socket
3451
    function gen_divert_port() {
3452
        $dports = get_divert_ports(); //array of used ports
3453
	$divert_port = 1; // Initialize
3454
	while (($divert_port % 2) != 0 || in_array($divert_port, $dports)) {
3455
		$divert_port = rand(40000, 60000);
3456
	}
3457
        return $divert_port;
3458
    }
3459
    
3460
    //Helps building the left tree
3461
    function build_tree() {
3462
        $tree = " <li><a href=\"firewall_shaper_layer7.php?container=" . $this->GetRName() ."&action=show\">"; 
3463
        $tree .= $this->GetRName() . "</a>";
3464
	$tree .= "</li>";
3465
		
3466
	return $tree;
3467
    }
3468
    
3469
    function build_form() {
3470
        $form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
3471
	$form .= "Enable/Disable";
3472
	$form .= "</td><td class=\"vncellreq\">";
3473
	$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\" ";
3474
	if ($this->GetREnabled() == "on") {
3475
       	    $form .=  "checked = \"CHECKED\"";
3476
	}
3477
	$form .= " ><span class=\"vexpl\"> Enable/Disable layer7 Container</span>";
3478
	$form .= "</td></tr>";
3479
        $form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
3480
	$form .= "<td class=\"vncellreq\">";
3481
	$form .= "<input type=\"text\" id=\"container\" name=\"container\" value=\"";
3482
	$form .= $this->GetRName()."\">";
3483
	$form .= "</td></tr>";
3484
	$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
3485
	$form .= "<td class=\"vncellreq\">";
3486
	$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3487
	$form .= $this->GetRDescription();
3488
	$form .= "\">";
3489
	$form .= "<br> <span class=\"vexpl\">";
3490
	$form .= "You may enter a description here ";
3491
	$form .= "for your reference (not parsed).</span>";
3492
	$form .= "</td></tr>";
3493
	
3494
	return $form;
3495
    }
3496
    
3497
    //Write the setting to the $config array
3498
    function wconfig() {
3499
	global $config;
3500
	
3501
	if(!is_array($config['l7shaper']['container'])) {
3502
		$config['l7shaper']['container'] = array();
3503
	}
3504
        //
3505
        $cflink =& get_l7c_reference_to_me_in_config($this->GetRName());
3506
	// Test if this rule does exists already
3507
	if(!$cflink) {
3508
		$cflink =& $config['l7shaper']['container'][];
3509
	}
3510
	$cflink['name'] = $this->GetRName();
3511
        $cflink['enabled'] = $this->GetREnabled();
3512
        $cflink['description'] = $this->GetRDescription();
3513
        $cflink['divert_port'] = $this->GetRPort();
3514
        
3515
	//Destroy previously existent rules
3516
	if(is_array($cflink['rules'])) {
3517
		unset($cflink['l7rules']);
3518
	}
3519
	
3520
        $cflink['l7rules'] = array();
3521
	
3522
        $i = 0;
3523
        foreach($this->rsets as $rulel7) {
3524
            $cflink['l7rules'][$i]['protocol'] = $rulel7->GetRProtocol();
3525
            $cflink['l7rules'][$i]['structure'] = $rulel7->GetRStructure();
3526
            $cflink['l7rules'][$i]['behaviour'] = $rulel7->GetRBehaviour();
3527
            $i++;
3528
        }
3529
    }
3530
    
3531
    //This function is necessary to help producing the overload options for keep state
3532
    function get_unique_structures() {
3533
        
3534
        $unique_structures = array("action" => false, "dummynet" => false, "altq" => false);
3535
        foreach($this->rsets as $l7rule) {
3536
		if($l7rule->GetRStructure() == "action")
3537
			$unique_structures['action'] = true;
3538
		else if($l7rule->GetRStructure() == "limiter")
3539
			$unique_structures['dummynet'] = true;
3540
		else
3541
			$unique_structures['altq'] = true;
3542
        }
3543
	//Delete non used structures so we don't have to check this in filter.inc
3544
	foreach($unique_structures as $key => $value)
3545
		if(!$value)
3546
			unset($unique_structures[$key]);
3547
        return $unique_structures;
3548
    }
3549
    
3550
    function validate_input($data, &$input_errors) {
3551
	$reqdfields[] = "container";
3552
	$reqdfieldsn[] = "Name";
3553
		
3554
	shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
3555
        
3556
        if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['container']))
3557
            $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
3558
    }
3559
    
3560
    function delete_l7c() {
3561
	mwexec("/bin/pkill -f 'ipfw-classifyd .* -p ". $this->GetRPort() . "'", true);
3562
	unset_l7_object_by_reference($this->GetRName());
3563
	cleanup_l7_from_rules($this->GetRName());
3564
    }
3565
}
3566

    
3567
class l7rule {
3568
    
3569
    var $rprotocol; //protocol
3570
    var $rstructure; //action, limiter, queue
3571
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3572
    
3573
    //Auxiliary Functions
3574
    
3575
    function GetRProtocol() {
3576
        return $this->rprotocol;
3577
    }
3578
    function SetRProtocol($rprotocol) {
3579
        $this->rprotocol = $rprotocol;
3580
    }
3581
    function GetRStructure() {
3582
        return $this->rstructure;
3583
    }
3584
    function SetRStructure($rstructure) {
3585
        $this->rstructure = $rstructure;
3586
    }
3587
    function GetRBehaviour() {
3588
        return $this->rbehaviour;
3589
    }
3590
    function SetRBehaviour($rbehaviour) {
3591
        $this->rbehaviour = $rbehaviour;
3592
    }
3593
    
3594
    //XXX Do we need to test any particularity for AltQ queues?
3595
    function build_rules() {
3596
	global $dummynet_pipe_list;
3597
	switch ($this->GetRStructure()) {
3598
		case "limiter":
3599
			read_dummynet_config();
3600
			$dn_list =& get_unique_dnqueue_list();
3601
			$found = false;
3602
			if(is_array($dn_list)) {
3603
				foreach($dn_list as $key => $value) {
3604
					if($key == $this->GetRBehaviour()) {
3605
						if($value[0] == "?")
3606
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3607
						else
3608
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3609
						$found = true;
3610
					}
3611
					if($found)
3612
						break;
3613
				}
3614
			}
3615
			break;
3616
		default: //This is for action and for altq
3617
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3618
			break;
3619
	}
3620
        return $l7rule;
3621
    }
3622
}
3623

    
3624
/*
3625
 * This function allows to return an array with all the used divert socket ports
3626
 */
3627
function get_divert_ports() {
3628
    global $layer7_rules_list;
3629
    $dports = array();
3630
    
3631
    foreach($layer7_rules_list as $l7r)
3632
        $dports[] = $l7r->GetRPort();
3633
    
3634
    return $dports;
3635
}
3636

    
3637
function &get_l7c_reference_to_me_in_config(&$name) {
3638
	global $config;
3639
	
3640
	$ptr = NULL;
3641
	
3642
	if(is_array($config['l7shaper']['container'])) {
3643
		foreach($config['l7shaper']['container'] as $key => $value) {
3644
			if($value['name'] == $name)
3645
				$ptr =& $config['l7shaper']['container'][$key];
3646
		}
3647
	}	
3648
	return $ptr;
3649
// $ptr can be null. has to be checked later
3650
}
3651

    
3652
function unset_l7_object_by_reference(&$name) {
3653
	global $config;
3654
        
3655
	if(is_array($config['l7shaper']['container'])) {
3656
		foreach($config['l7shaper']['container'] as $key => $value) {
3657
			if($value['name'] == $name) {
3658
				unset($config['l7shaper']['container'][$key]['l7rules']);
3659
				unset($config['l7shaper']['container'][$key]);
3660
				break;
3661
			}
3662
		}
3663
	}
3664
}
3665

    
3666
function read_layer7_config() {
3667
    global $layer7_rules_list, $config;
3668
    
3669
    $l7cs = &$config['l7shaper']['container'];
3670
    
3671
    $layer7_rules_list = array();
3672
    
3673
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3674
	return;
3675
    
3676
    foreach ($l7cs as $conf) {
3677
	if (empty($conf['name']))
3678
		continue; /* XXX: grrrrrr at php */ 
3679
        $root =& new layer7();
3680
        $root->ReadConfig($conf['name'],$conf);
3681
        $layer7_rules_list[$root->GetRName()] = &$root;
3682
    }
3683
}
3684

    
3685
function generate_layer7_files() {
3686
    global $layer7_rules_list, $g;
3687
    
3688
    read_layer7_config();
3689
    
3690
    if (!empty($layer7_rules_list)) {
3691
	if (!is_module_loaded("ipdivert.ko"))
3692
		mwexec("/sbin/kldload ipdivert.ko");
3693

    
3694
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3695
    }
3696
    
3697
    foreach($layer7_rules_list as $l7rules) {
3698
        if($l7rules->GetREnabled()) {
3699
            $filename = $l7rules->GetRName() . ".l7";
3700
            $path = "{$g['tmp_path']}/" . $filename;
3701
        
3702
            $rules = $l7rules->build_l7_rules();
3703
        
3704
            $fp = fopen($path,'w');
3705
            fwrite($fp,$rules);
3706
            fclose($fp);
3707
        }
3708
    }
3709
}
3710

    
3711
function layer7_start_l7daemon() {
3712
    global $layer7_rules_list, $g;
3713

    
3714
    /*
3715
     * XXX: ermal - Needed ?!
3716
     * read_layer7_config();
3717
     */
3718

    
3719
    foreach($layer7_rules_list as $l7rules) {
3720
        if($l7rules->GetREnabled()) {
3721
            $filename = $l7rules->GetRName() . ".l7";
3722
            $path = "{$g['tmp_path']}/" . $filename;
3723

    
3724
	    unset($l7pid);
3725
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3726
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3727
	    if (count($l7pid) > 0) {
3728
		log_error("Sending HUP signal to {$l7pid[0]}");
3729
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3730
	    } else {
3731
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3732
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3733
		mwexec_bg($ipfw_classifyd_init);
3734
	    }
3735
        }
3736
    }
3737
}
3738

    
3739
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3740
function generate_protocols_array() {
3741
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3742
	$protocols_new = array();
3743
	if(is_array($protocols)) {
3744
		foreach($protocols as $key => $proto) {
3745
			if (strstr($proto, ".pat"))
3746
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3747
		}
3748
		sort($protocols_new);
3749
	}		
3750
	return $protocols_new;
3751
}
3752

    
3753
function get_l7_unique_list() {
3754
	global $layer7_rules_list;
3755
	
3756
	$l7list = array();
3757
	if(is_array($layer7_rules_list)) 
3758
		foreach($layer7_rules_list as $l7c)
3759
			if($l7c->GetREnabled())
3760
				$l7list[] = $l7c->GetRName();
3761
	
3762
	return $l7list;
3763
}
3764

    
3765
// Disable a removed l7 container from the filter
3766
function cleanup_l7_from_rules(&$name) {
3767
	global $config;
3768

    
3769
	if(is_array($config['filter']['rule']))
3770
		foreach ($config['filter']['rule'] as $key => $rule) {
3771
			if ($rule['l7container'] == $name)
3772
				unset($config['filter']['rule'][$key]['l7container']);
3773
		}
3774
}
3775

    
3776
function get_dummynet_name_list() {
3777
	
3778
	$dn_name_list =& get_unique_dnqueue_list();
3779
	$dn_name = array();
3780
	if(is_array($dn_name_list))
3781
		foreach($dn_name_list as $key => $value)
3782
			$dn_name[] = $key;
3783
	
3784
	return $dn_name;
3785
	
3786
}
3787

    
3788
function get_altq_name_list() {
3789
	$altq_name_list =& get_unique_queue_list();
3790
	$altq_name = array();
3791
	if(is_array($altq_name_list))
3792
		foreach($altq_name_list as $key => $aqobj)
3793
			$altq_name[] = $key;
3794
		
3795
	return $altq_name;
3796
}
3797

    
3798
/*
3799
 * XXX: TODO Make a class shaper to hide all these function
3800
 * from the global namespace.
3801
 */
3802

    
3803
/* 
3804
 * This is a layer violation but for now there is no way 
3805
 * i can find to properly do this with PHP.
3806
 */
3807
function altq_set_default_queue($interface, $value) {
3808
	global $altq_list_queues;
3809
		
3810
	$altq_tmp =& $altq_list_queues[$interface];
3811
	if ($altq_tmp) {
3812
		if ($value) {
3813
			$altq_tmp->SetDefaultQueuePresent("true");
3814
		}
3815
		else {
3816
			$altq_tmp->SetDefaultQueuePresent("false");
3817
		}
3818
	}
3819
}
3820

    
3821
function altq_get_default_queue($interface) {
3822
	global $altq_list_queues;
3823

    
3824
	$altq_tmp = $altq_list_queues[$interface];
3825
	if ($altq_tmp)  
3826
		return $altq_tmp->GetDefaultQueuePresent(); 
3827
}
3828

    
3829
function altq_check_default_queues() {
3830
	global $altq_list_queues;
3831

    
3832
	$count = 0;
3833
	if (is_array($altq_list_queues)) {
3834
		foreach($altq_list_queues as $altq) {
3835
			if ($altq->GetDefaultQueuePresent())
3836
				$count++;
3837
		}
3838
	}
3839
	else  $count++;;
3840
	
3841
	return 0;
3842
}
3843

    
3844
function &get_unique_queue_list() {
3845
	global $altq_list_queues;
3846
	
3847
	$qlist = array();
3848
	if (is_array($altq_list_queues)) {
3849
		foreach ($altq_list_queues as $altq) {
3850
			if ($altq->GetEnabled() == "")
3851
				continue;
3852
			$tmplist =& $altq->get_queue_list();
3853
			foreach ($tmplist as $qname => $link) {
3854
				if ($link->GetEnabled() <> "")
3855
					$qlist[$qname] = $link;	
3856
			}
3857
		}
3858
	}
3859
	return $qlist;
3860
}
3861

    
3862
function &get_unique_dnqueue_list() {
3863
	global $dummynet_pipe_list;
3864
	
3865
	$qlist = array();
3866
	if (is_array($dummynet_pipe_list)) {
3867
		foreach ($dummynet_pipe_list as $dn) {
3868
			if ($dn->GetEnabled() == "")
3869
				continue;
3870
			$tmplist =& $dn->get_queue_list();
3871
			foreach ($tmplist as $qname => $link) {
3872
				$qlist[$qname] = $link;	
3873
			}
3874
		}
3875
	}
3876
	return $qlist;
3877
}
3878

    
3879
function ref_on_altq_queue_list($parent, $qname) {
3880
	if (isset($GLOBALS['queue_list'][$qname]))
3881
		$GLOBALS['queue_list'][$qname]++;
3882
	else
3883
		$GLOBALS['queue_list'][$qname] = 1;
3884

    
3885
	unref_on_altq_queue_list($parent);
3886
}
3887

    
3888
function unref_on_altq_queue_list($qname) {
3889
	$GLOBALS['queue_list'][$qname]--;
3890
	if ($GLOBALS['queue_list'][$qname] <= 1)
3891
		unset($GLOBALS['queue_list'][$qname]);	
3892
}
3893

    
3894
function read_altq_config() {
3895
	global $altq_list_queues, $config;
3896
	$path = array();
3897
	
3898
	if (!is_array($config['shaper']))
3899
		$config['shaper'] = array();
3900
	if (!is_array($config['shaper']['queue']))
3901
		$config['shaper']['queue'] = array();
3902
	$a_int = &$config['shaper']['queue'];
3903

    
3904
	$altq_list_queues = array();
3905
	
3906
	if (!is_array($config['shaper']['queue']))
3907
		return;
3908

    
3909
	foreach ($a_int as $key => $conf) {
3910
		$int = $conf['interface'];
3911
		$root =& new altq_root_queue();
3912
		$root->SetInterface($int);
3913
		$altq_list_queues[$root->GetInterface()] = &$root;
3914
		$root->ReadConfig($conf);
3915
		array_push($path, $key);
3916
		$root->SetLink($path);
3917
		if (is_array($conf['queue'])) {
3918
			foreach ($conf['queue'] as $key1 => $q) {
3919
				array_push($path, $key1);
3920
				/* 
3921
				 * XXX: we compeletely ignore errors here but anyway we must have 
3922
				 *	checked them before so no harm should be come from this.
3923
				 */
3924
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3925
				array_pop($path);
3926
			} 	
3927
		}
3928
		array_pop($path);
3929
	}
3930
}
3931

    
3932
function read_dummynet_config() {
3933
	global $dummynet_pipe_list, $config;
3934
	$path = array();
3935
	$dnqueuenumber = 1;
3936
	$dnpipenumber = 1;
3937

    
3938
	if (!is_array($config['dnshaper']))
3939
		$config['dnshaper'] = array();
3940
	if (!is_array($config['dnshaper']['queue']))
3941
		$config['dnshaper']['queue'] = array();
3942
	$a_int = &$config['dnshaper']['queue'];
3943

    
3944
	$dummynet_pipe_list = array();
3945
	
3946
	if (!is_array($config['dnshaper']['queue'])
3947
		|| !count($config['dnshaper']['queue']))
3948
		return;
3949

    
3950
	foreach ($a_int as $key => $conf) {
3951
		if (empty($conf['name']))
3952
			continue; /* XXX: grrrrrr at php */ 
3953
		$root =& new dnpipe_class();
3954
		$root->ReadConfig($conf);
3955
		$root->SetNumber($dnpipenumber);	
3956
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3957
		array_push($path, $key);
3958
		$root->SetLink($path);
3959
		if (is_array($conf['queue'])) {
3960
			foreach ($conf['queue'] as $key1 => $q) {
3961
				array_push($path, $key1);
3962
				/* XXX: We cheat a little here till a better way is found. */
3963
				$q['number'] = $dnqueuenumber;
3964
				/* 
3965
				 * XXX: we compeletely ignore errors here but anyway we must have 
3966
				 *	checked them before so no harm should be come from this.
3967
				 */	
3968
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3969
				array_pop($path);
3970

    
3971
				$dnqueuenumber++;
3972
			} 	
3973
		}
3974
		array_pop($path);
3975
			
3976
		$dnpipenumber++;
3977
	}
3978
}
3979

    
3980
function get_interface_list_to_show() {
3981
	global $altq_list_queues, $config;
3982
	global $shaperIFlist;
3983

    
3984
	$tree = "";
3985
	foreach ($shaperIFlist as $shif => $shDescr) {
3986
		if ($altq_list_queues[$shif]) {
3987
			continue;
3988
		} else  {
3989
			if (!is_altq_capable(get_real_interface($shif)))
3990
				continue;
3991
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3992
		}
3993
	}
3994
	
3995
	return $tree;
3996
}
3997

    
3998
function filter_generate_altq_queues() {
3999
	global $altq_list_queues;
4000
	
4001
	read_altq_config();
4002

    
4003
	$altq_rules = "";
4004
	foreach ($altq_list_queues as $altq) 
4005
		$altq_rules .= $altq->build_rules();
4006

    
4007
	return $altq_rules;
4008
}
4009

    
4010
function filter_generate_dummynet_rules() {
4011
	global $g, $dummynet_pipe_list;
4012
	
4013
	read_dummynet_config();
4014
	
4015
	if (!empty($dummynet_pipe_list)) {
4016
		if (!is_module_loaded("dummynet.ko"))
4017
			mwexec("/sbin/kldload dummynet");
4018
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
4019
		//mwexec("pfctl -F dummynet");
4020
	}
4021

    
4022
	$dn_rules = "";
4023
	foreach ($dummynet_pipe_list as $dn) 
4024
		$dn_rules .= $dn->build_rules();
4025

    
4026
	if (!empty($dn_rules)) {
4027
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
4028
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
4029
	}
4030
	//return $dn_rules;
4031
}
4032

    
4033
function build_iface_without_this_queue($iface, $qname) {
4034
	global $g, $altq_list_queues;
4035

    
4036
	$altq =& $altq_list_queues[$iface];
4037
				if ($altq)
4038
						$scheduler = ": " . $altq->GetScheduler();
4039
	$form = "<tr><td width=\"20%\" >";
4040
	$form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
4041
		$form .= "</td></tr>";
4042
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
4043
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
4044
		$form .= $iface . "&queue=". $qname . "&action=add\">";
4045
		$form .= "<img src=\"";
4046
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
4047
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
4048
		$form .= " Clone shaper/queue on this interface</a></td></tr>";
4049

    
4050
		return $form;
4051

    
4052
}
4053

    
4054

    
4055
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
4056
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
4057
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
4058
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
4059
$default_shaper_msg .= " </p></strong></span>";
4060
$default_shaper_msg .= "</td></tr>";
4061

    
4062
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
4063
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
4064
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
4065
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
4066
$dn_default_shaper_msg .= " </p></strong></span>";
4067
$dn_default_shaper_msg .= "</td></tr>";
4068

    
4069
?>
(45-45/61)