Project

General

Profile

Download (129 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 $available_bw; /* in b/s */
235

    
236
	/* Accesor functions */
237
	function GetAvailableBandwidth() {
238
		return $this->available_bw;
239
	}
240
	function SetAvailableBandwidth($bw) {
241
		$this->available_bw = $bw;
242
	}
243
	function GetDefaultQueuePresent() {
244
		if (!empty($this->queues)) {
245
			foreach ($this->queues as $q) {
246
				if ($q->GetDefault())
247
					return true;
248
			}
249
		}
250

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

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

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

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

    
385
	function &get_queue_list($q = null) {
386
		$qlist = array();
387

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

    
396
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
397

    
398
		if (!is_array($this->queues))
399
			$this->queues = array();
400

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

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

    
452
		return $q;
453
	}
454

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

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

    
481
	function build_tree() {
482
		global $shaperIFlist;
483

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

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

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

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

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

    
580
		return $javascript;
581
	}
582
	
583
	function build_shortform() {
584
		global $g;
585

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

    
605
		return $form;
606

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

    
694

    
695
		return $form;
696
	}
697

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

    
726
}
727

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

    
747
	/* This is here to help with form building and building rules/lists */
748
	var $subqueues = array();
749

    
750
	/* Accesor functions */
751
	function GetAvailableBandwidth() {
752
		return $this->available_bw;
753
	}
754
	function SetAvailableBandwidth($bw) {
755
		$this->available_bw = $bw;
756
	}
757
	function SetLink($link) {
758
		$this->link = $link;
759
	}
760
	function GetLink() {
761
		return $this->link;
762
	}
763
	function &GetParent() {
764
		return $this->qparent;
765
	}
766
	function SetParent(&$parent) {
767
		$this->qparent = &$parent;
768
	}
769
	function GetEnabled() {
770
		return $this->qenabled;
771
	}
772
	function SetEnabled($value) {
773
		$this->qenabled = $value;
774
	}
775
	function CanHaveChildren() {
776
		return false;
777
	}
778
	function CanBeDeleted() {
779
		return true;
780
	}
781
	function GetQname() {
782
		return $this->qname;
783
	}
784
	function SetQname($name) {
785
		$this->qname = trim($name);
786
	}
787
	function GetBandwidth() {
788
		return $this->qbandwidth;
789
	}
790
	function SetBandwidth($bandwidth) {
791
		$this->qbandwidth = $bandwidth;
792
	}
793
	function GetInterface() {
794
		return $this->qinterface;
795
	}
796
	function SetInterface($name) {
797
		$this->qinterface = trim($name);
798
	}
799
	function GetQlimit() {
800
		return $this->qlimit;
801
	}
802
	function SetQlimit($limit) {
803
		$this->qlimit = $limit;
804
	}
805
	function GetQpriority() {
806
		return $this->qpriority;
807
	}
808
	function SetQpriority($priority) {
809
		$this->qpriority = $priority;
810
	}
811
	function GetDescription() {
812
		return $this->description;
813
	}
814
	function SetDescription($str) {
815
		$this->description = trim($str);
816
	}
817
	function GetFirstime() {
818
		return $this->firsttime;
819
	}
820
	function SetFirsttime($number) {
821
		$this->firsttime = $number;
822
	}
823
	function GetBwscale() {
824
		return $this->qbandwidthtype;
825
	}
826
	function SetBwscale($scale) {
827
		$this->qbandwidthtype = $scale;
828
	}
829
	function GetDefaultQueuePresent() {
830
		if ($this->GetDefault())
831
			return true;
832
		if (!empty($this->subqueues)) {
833
			foreach ($this->subqueues as $q) {
834
				if ($q->GetDefault())
835
					return true;
836
			}
837
		}
838

    
839
		return false;
840
	}
841
	function GetDefault() {
842
		return $this->qdefault;
843
	}
844
	function SetDefault($value = false) {
845
		$this->qdefault = $value;
846
	}
847
	function GetRed() {
848
		return $this->qred;
849
	}
850
	function SetRed($red = false) {
851
		$this->qred = $red;
852
	}
853
	function GetRio() {
854
		return $this->qrio;
855
	}
856
	function SetRio($rio = false) {
857
		$this->qrio = $rio;
858
	}
859
	function GetEcn() {
860
		return $this->qecn;
861
	}
862
	function SetEcn($ecn = false) {
863
		$this->qecn = $ecn;
864
	}
865
	function GetAck() {
866
		return $this->qack;
867
	}
868
	function SetAck($ack = false) {
869
		$this->qack = $ack;
870
	}
871

    
872
	function build_javascript() {
873
		$javascript = "<script type=\"text/javascript\">";
874
		$javascript .= "function mySuspend() { \n";
875
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
876
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
877
		$javascript .= "else if (document.all)\n";
878
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
879
		$javascript .= "}\n";
880

    
881
		$javascript .= "function myResume() {\n";
882
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
883
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
884
		$javascript .= "else if (document.all)\n";
885
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
886
		$javascript .= "}\n";
887
		$javascript .= "</script>";
888
		
889
		return $javascript;
890
	}
891
	
892
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
893

    
894
	/* 
895
	 * Currently this will not be called unless we decide to clone a whole 
896
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
897
	 */
898
	 function copy_queue($interface, &$cflink) {
899

    
900
 		$cflink['name'] = $this->GetQname();
901
                $cflink['interface'] = $interface;
902
                $cflink['qlimit'] = $this->GetQlimit();
903
                $cflink['priority'] = $this->GetQpriority();
904
                $cflink['description'] = $this->GetDescription();
905
                $cflink['enabled'] = $this->GetEnabled();
906
                $cflink['default'] = $this->GetDefault();
907
                $cflink['red'] = $this->GetRed();
908
                $cflink['rio'] = $this->GetRio();
909
                $cflink['ecn'] = $this->GetEcn();
910

    
911
                if (is_array($this->subqueues)) {
912
                        $cflinkp['queue'] = array();
913
                        foreach ($this->subqueues as $q) {
914
				 $cflink['queue'][$q->GetQname()] = array();
915
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
916
			}
917
                }
918

    
919
	 }
920

    
921
	function clean_queue($sched) {
922
		clean_child_queues($sched, $this->GetLink());
923
		if (is_array($this->subqueues)) {
924
			foreach ($this->subqueues as $q)
925
				$q->clean_queue($sched);
926
		}
927
	}
928

    
929
        function &get_queue_list(&$qlist) {
930
		
931
		$qlist[$this->GetQname()] = & $this;
932
		if (is_array($this->subqueues)) {
933
			foreach ($this->subqueues as $queue)
934
				$queue->get_queue_list($qlist);
935
		}
936
	}
937

    
938
	function delete_queue() {
939
		unref_on_altq_queue_list($this->GetQname());
940
		cleanup_queue_from_rules($this->GetQname());
941
		unset_object_by_reference($this->GetLink());
942
	}
943
	
944
	function delete_all() {
945
                if (count($this->subqueues)) {
946
                        foreach ($this->subqueues as $q) {
947
                                $q->delete_all();
948
                                unset_object_by_reference($q->GetLink());
949
                                unset($q);
950
                        }
951
                        unset($this->subqueues);
952
                }
953
        }
954

    
955
	 function &find_queue($interface, $qname) { 
956
		if ($qname == $this->GetQname())
957
			return $this; 
958
	}
959
	
960
	function find_parentqueue($interface, $qname) { return; }
961
		
962
	function validate_input($data, &$input_errors) {
963
	
964
		$reqdfields[] = "name";
965
		$reqdfieldsn[] = "Name";
966
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
967

    
968
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
969
			$input_errors[] = "Bandwidth must be an integer.";
970
                if ($data['bandwidth'] < 0)
971
			$input_errors[] = "Bandwidth cannot be negative.";
972
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
973
			$input_errors[] = "Qlimit must be an integer.";
974
	 	if ($data['qlimit'] < 0)
975
			$input_errors[] = "Qlimit must be an positive.";
976
		if ($data['priority'] && (!is_numeric($data['priority'])
977
		    || ($data['priority'] < 1) || ($data['priority'] > 15))) {
978
			$input_errors[] = "The priority must be an integer between 1 and 15.";
979
		}
980
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
981
				$input_errors[] = "Queue limit must be an integer";
982
		if ($data['qlimit'] < 0)
983
				$input_errors[] = "Queue limit must be positive";
984
		if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['newname']))
985
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
986
		if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
987
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
988
		$default = $this->GetDefault();
989
		if (!empty($data['default']) && altq_get_default_queue($data['interface']) && empty($default))
990
			$input_errors[] = "Only one default queue per interface is allowed.";
991
	}
992

    
993
	function ReadConfig(&$q) {
994
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
995
			$this->SetQname($q['newname']);
996
		} else if (!empty($q['newname'])) {
997
			$this->SetQname($q['newname']);
998
		} else if (isset($q['name']))
999
			$this->SetQname($q['name']);
1000
		if (isset($q['interface']))
1001
			$this->SetInterface($q['interface']);
1002
		$this->SetBandwidth($q['bandwidth']);
1003
		if ($q['bandwidthtype'] <> "")
1004
			$this->SetBwscale($q['bandwidthtype']);
1005
		if (!empty($q['qlimit']))
1006
			$this->SetQlimit($q['qlimit']);
1007
		else
1008
			$this->SetQlimit(""); // Default
1009
		if (!empty($q['priority']))
1010
			$this->SetQPriority($q['priority']);
1011
		else
1012
			$this->SetQpriority("");
1013
		if (!empty($q['description']))
1014
			$this->SetDescription($q['description']);
1015
		else
1016
			$this->SetDescription("");
1017
		if (!empty($q['red']))
1018
			$this->SetRed($q['red']);
1019
		else
1020
			$this->SetRed();
1021
		if (!empty($q['rio']))
1022
			$this->SetRio($q['rio']);
1023
		else
1024
			$this->SetRio();
1025
		if (!empty($q['ecn']))
1026
			$this->SetEcn($q['ecn']);
1027
		else
1028
			$this->SetEcn();
1029
		if (!empty($q['default']))
1030
			$this->SetDefault($q['default']);
1031
		else
1032
			$this->SetDefault();
1033
		if (!empty($q['enabled']))
1034
			$this->SetEnabled($q['enabled']);
1035
		else
1036
			$this->SetEnabled("");
1037

    
1038
	}
1039

    
1040
	function build_tree() {
1041
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
1042
		$tree .= "\" ";
1043
		$tmpvalue = $this->GetDefault();
1044
		if (!empty($tmpvalue))
1045
			$tree .= " class=\"navlnk\"";
1046
		$tree .= " >" . $this->GetQname() . "</a>";
1047
		/* 
1048
		 * Not needed here!
1049
		 * if (is_array($queues) {
1050
		 *	  $tree .= "<ul>";
1051
		 *	  foreach ($q as $queues) 
1052
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1053
		 *	  endforeach	
1054
		 *	  $tree .= "</ul>";
1055
		 * }
1056
		 */
1057

    
1058
		$tree .= "</li>"; 
1059

    
1060
		return $tree;
1061
	}
1062
		
1063
	/* Should return something like:
1064
	 * queue $qname on $qinterface bandwidth ....
1065
	 */
1066
	function build_rules(&$default = false) {
1067
		$pfq_rule = " queue ". $this->qname;
1068
		if ($this->GetInterface())
1069
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1070
		$tmpvalue = $this->GetQpriority();
1071
		if (!empty($tmpvalue))
1072
			$pfq_rule .= " priority ".$this->GetQpriority();
1073
		$tmpvalue = $this->GetQlimit();
1074
		if (!empty($tmpvalue))
1075
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1076
		if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
1077
			$pfq_rule .= " priq ( ";
1078
			$tmpvalue = $this->GetRed();
1079
			if (!empty($tmpvalue)) {
1080
				$comma = 1;
1081
				$pfq_rule .= " red ";
1082
			}
1083
			$tmpvalue = $this->GetRio();
1084
			if (!empty($tmpvalue)) {
1085
				if ($comma) 
1086
					$pfq_rule .= " ,";
1087
				$comma = 1;
1088
				$pfq_rule .= " rio ";
1089
			}
1090
			$tmpvalue = $this->GetEcn();
1091
			if (!empty($tmpvalue)) {
1092
				if ($comma) 
1093
					$pfq_rule .= " ,";
1094
				$comma = 1;
1095
				$pfq_rule .= " ecn ";
1096
			}
1097
			$tmpvalue = $this->GetDefault();
1098
			if (!empty($tmpvalue)) {
1099
				if ($comma)
1100
					$pfq_rule .= " ,";
1101
				$pfq_rule .= " default ";
1102
				$default = true;
1103
			}
1104
			$pfq_rule .= " ) ";
1105
		}
1106

    
1107
		$pfq_rule .= " \n";
1108

    
1109
		return $pfq_rule;
1110
	}
1111

    
1112
	/*
1113
	 * To return the html form to show to user
1114
	 * for getting the parameters.
1115
	 * Should do even for first time when the
1116
	 * object is created and later when we may
1117
	 * need to update it.
1118
	 */
1119
	function build_form() {
1120
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
1121
                $form .= "Enable/Disable";
1122
                $form .= "<br/></td><td class=\"vncellreq\">";
1123
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
1124
                if ($this->GetEnabled() == "on")
1125
                        $form .=  " CHECKED";
1126
                $form .= " ><span class=\"vexpl\"> Enable/Disable queue and its children</span>";
1127
                $form .= "</td></tr>";
1128
		$form .= "<tr>";
1129
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">";
1130
		$form .= "Queue Name</td><td width=\"78%\" class=\"vtable\">";
1131
		$form .= "<input name=\"newname\" type=\"text\" id=\"newname\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1132
		$form .= htmlspecialchars($this->GetQname());
1133
		$form .= "\">";
1134
		$form .= "<input name=\"name\" type=\"hidden\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1135
		$form .= htmlspecialchars($this->GetQname());
1136
		$form .= "\">";
1137
		$form .= "<br /> <span class=\"vexpl\">Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.";
1138
		$form .= "</span><br /></td>";
1139
		$form .= "</tr><tr>";
1140
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Priority</td>";
1141
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
1142
		$form .= htmlspecialchars($this->GetQpriority());
1143
		$form .= "\">";
1144
		$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>";
1145
		$form .= "</tr>";
1146
		$form .= "<tr>";
1147
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Queue limit</td>";
1148
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"8\" value=\"";
1149
		$form .= htmlspecialchars($this->GetQlimit());
1150
		$form .= "\">";
1151
		$form .= "<br> <span class=\"vexpl\">Queue limit in packets per second."; 
1152
		$form .= "</span></td>";
1153
		$form .= "<tr>";
1154
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncell\">Scheduler options</td>";
1155
		$form .= "<td width=\"78%\" class=\"vtable\">";
1156
		if (empty($this->subqueues)) {
1157
			if ($this->GetDefault()) { 
1158
				$form .= "<input type=\"checkbox\" id=\"default\" CHECKED name=\"default\" value=\"default\"";
1159
				$form .= "> " . gettext("Default queue") . "<br>";
1160
			} else {
1161
				$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\" value=\"default\"";
1162
				$form .= "> " . gettext("Default queue") . "<br>";
1163
			}
1164
		}
1165
		$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\" value=\"red\" ";
1166
		$tmpvalue = $this->GetRed();
1167
		if(!empty($tmpvalue)) 
1168
			$form .=  " CHECKED";
1169
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">Random Early Detection</a><br>";
1170
		$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\" value=\"rio\"";
1171
		$tmpvalue = $this->GetRio();
1172
		if(!empty($tmpvalue)) 
1173
			$form .=  " CHECKED";
1174
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">Random Early Detection In and Out</a><br>";
1175
		$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\" value=\"ecn\"";
1176
		$tmpvalue = $this->GetEcn();
1177
		if(!empty($tmpvalue)) 
1178
			$form .=  " CHECKED";
1179
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">Explicit Congestion Notification</a><br>";
1180
		$form .= "<span class=\"vexpl\"><br>Select options for this queue";
1181
		$form .= "</tr><tr>";
1182
		$form .= "<td width=\"22%\" class=\"vncellreq\">Description</td>";
1183
		$form .= "<td width=\"78%\" class=\"vtable\">";
1184
		$form .= "<input type=\"text\" name=\"description\" size=\"50%\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\"  >";
1185
		$form .= "</td></tr>";
1186
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1187
		$form .= " value=\"".$this->GetInterface()."\">";
1188

    
1189
		return $form;
1190
	}
1191

    
1192
	function build_shortform() {
1193
		/* XXX: Hacks in site. Mostly layer violations!  */
1194
		global $g, $altq_list_queues;
1195
		global $shaperIFlist;
1196
		
1197
		$altq =& $altq_list_queues[$this->GetInterface()];
1198
		if ($altq)
1199
			$scheduler = ": " . $altq->GetScheduler();
1200
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
1201
		$form .= "<a href=\"firewall_shaper.php?interface=" . $this->GetInterface() . "&queue=" . $this->GetQname()."&action=show\">". $shaperIFlist[$this->GetInterface()] .$scheduler."</a>";
1202
		$form .= "</td></tr>";
1203
		/* 
1204
		 * XXX: Hack in sight maybe fix with a class that wraps all
1205
		 * of this layer violations
1206
		 */
1207
		$form .= "<tr>";
1208
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1209
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
1210
		$form .= "</td><td width=\"50%\"></td></tr>";
1211
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1212
		$tmpvalue = $this->GetQpriority();
1213
		if (!empty($tmpvalue))
1214
			$form .= "Priority: on </td></tr>";
1215
		$tmpvalue = $this->GetDefault();
1216
		if (!empty($tmpvalue))
1217
			$form .= "<tr><td class=\"vncellreq\">Default: on </td></tr>";
1218
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1219
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1220
		$form .= $this->GetInterface() . "&queue=";
1221
		$form .= $this->GetQname() . "&action=delete\">";
1222
		$form .= "<img src=\"";
1223
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1224
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Delete queue from interface\">";
1225
		$form .= "<span>Delete queue from interface</span></a></td></tr>";
1226
		
1227
		return $form;
1228

    
1229
	}
1230

    
1231
		function update_altq_queue_data(&$q) { 
1232
		$this->ReadConfig($q);
1233
	}
1234

    
1235
	function wconfig() {
1236
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1237
		if (!is_array($cflink))
1238
			$cflink = array();
1239
		$cflink['name'] = $this->GetQname();
1240
		$cflink['interface'] = $this->GetInterface();
1241
		$cflink['qlimit'] = trim($this->GetQlimit());
1242
		if (empty($cflink['qlimit']))
1243
			unset($cflink['qlimit']);
1244
		$cflink['priority'] = trim($this->GetQpriority());
1245
		if (empty($cflink['priority']))
1246
			unset($cflink['priority']);
1247
		$cflink['description'] = trim($this->GetDescription());
1248
		if (empty($cflink['description']))
1249
			unset($cflink['description']);
1250
		$cflink['enabled'] = trim($this->GetEnabled());
1251
		if (empty($cflink['enabled']))
1252
			unset($cflink['enabled']);
1253
		$cflink['default'] = trim($this->GetDefault());
1254
		if (empty($cflink['default']))
1255
			unset($cflink['default']);
1256
		$cflink['red'] = trim($this->GetRed());
1257
		if (empty($cflink['red']))
1258
			unset($cflink['red']);
1259
		$cflink['rio'] = trim($this->GetRio());
1260
		if (empty($cflink['rio']))
1261
			unset($cflink['rio']);
1262
		$cflink['ecn'] = trim($this->GetEcn());
1263
		if (empty($cflink['ecn']))
1264
			unset($cflink['ecn']);
1265
	}
1266
}
1267

    
1268
class hfsc_queue extends priq_queue {
1269
	/* realtime */
1270
	var $realtime;
1271
	var $r_m1;
1272
	var $r_d;
1273
	var $r_m2;
1274
	/* linkshare */
1275
	var $linkshare;
1276
	var $l_m1;
1277
	var $l_d;
1278
	var $l_m2;
1279
	/* upperlimit */
1280
	var $upperlimit;
1281
	var $u_m1;
1282
	var $u_d;
1283
	var $u_m2;
1284

    
1285
	/*
1286
	 * HFSC can have nested queues.
1287
	 */
1288
	function CanHaveChildren() {
1289
		return true;
1290
	}
1291
	function GetRealtime() {
1292
           return $this->realtime;
1293
	}
1294
	function GetR_m1() {
1295
		return $this->r_m1;
1296
	}
1297
	function GetR_d() {
1298
		return $this->r_d;
1299
	}
1300
	function GetR_m2() {
1301
		return $this->r_m2;
1302
	}
1303
	function SetRealtime() {
1304
		$this->realtime = "on";
1305
	}
1306
	function DisableRealtime() {
1307
		$this->realtime = "";
1308
	}
1309
	function SetR_m1($value) {
1310
		$this->r_m1 = $value;
1311
	}
1312
	function SetR_d($value) {
1313
		$this->r_d = $value;
1314
	}
1315
	function SetR_m2($value) {
1316
		$this->r_m2 = $value;
1317
	}
1318
	function GetLinkshare() {
1319
		return $this->linkshare;
1320
	}
1321
	function DisableLinkshare() {
1322
		$this->linkshare = "";
1323
	}
1324
	function GetL_m1() {
1325
		return $this->l_m1;
1326
	}
1327
	function GetL_d() {
1328
		return $this->l_d;
1329
	}
1330
	function GetL_m2() {
1331
		return $this->l_m2;
1332
	}
1333
	function SetLinkshare() {
1334
		$this->linkshare = "on";
1335
	}
1336
	function SetL_m1($value) {
1337
		$this->l_m1 = $value;
1338
	}
1339
	function SetL_d($value) {
1340
		$this->l_d = $value;
1341
	}
1342
	function SetL_m2($value) {
1343
		$this->l_m2 = $value;
1344
	}
1345
	function GetUpperlimit() {
1346
		return $this->upperlimit;
1347
	}
1348
	function GetU_m1() {
1349
		return $this->u_m1;
1350
	}
1351
	function GetU_d() {
1352
		return $this->u_d;
1353
	}
1354
	function GetU_m2() {
1355
		return $this->u_m2;
1356
	}
1357
	function SetUpperlimit() {
1358
		$this->upperlimit = "on";
1359
	}
1360
	function DisableUpperlimit() {
1361
		$this->upperlimit = "";
1362
	}
1363
	function SetU_m1($value) {
1364
		$this->u_m1 = $value;
1365
	}
1366
	function SetU_d($value) {
1367
		$this->u_d = $value;
1368
	}
1369
	function SetU_m2($value) {
1370
		$this->u_m2 = $value;
1371
	}
1372

    
1373
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1374

    
1375
		if (!is_array($this->subqueues))
1376
			$this->subqueues = array();
1377
		$q =& new hfsc_queue();
1378
		$q->SetInterface($this->GetInterface());
1379
		$q->SetParent(&$this);
1380
		$q->ReadConfig($qname);
1381
		$q->validate_input($qname, $input_errors);
1382
		if (count($input_errors)) {
1383
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
1384
			return $q;
1385
		}
1386

    
1387
		$q->SetEnabled("on");
1388
		$q->SetLink($path);
1389
		switch ($q->GetBwscale()) {
1390
		case "%":
1391
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1392
			break;
1393
		default:
1394
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1395
			break;
1396
		}
1397
		$q->SetAvailableBandwidth($myBw);
1398
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1399

    
1400
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1401
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1402
		if (is_array($qname['queue'])) {
1403
			foreach ($qname['queue'] as $key1 => $que) {
1404
				array_push($path, $key1);
1405
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1406
				array_pop($path);
1407
			}
1408
		}
1409
	
1410
		return $q;
1411
	}
1412

    
1413
        function copy_queue($interface, &$cflink) {
1414

    
1415
		$cflink['name'] = $this->GetQname();
1416
		$cflink['interface'] = $interface;
1417
		$cflink['qlimit'] = trim($this->GetQlimit());
1418
		if (empty($cflink['qlimit']))
1419
			unset($cflink['qlimit']);
1420
		$cflink['priority'] = trim($this->GetQpriority());
1421
		if (empty($cflink['priority']))
1422
			unset($cflink['priority']);
1423
		$cflink['description'] = trim($this->GetDescription());
1424
		if (empty($cflink['description']))
1425
			unset($cflink['description']);
1426
		$cflink['bandwidth'] = $this->GetBandwidth();
1427
		$cflink['bandwidthtype'] = $this->GetBwscale();
1428
		$cflink['enabled'] = trim($this->GetEnabled());
1429
		if (empty($cflink['enabled']))
1430
			unset($cflink['enabled']);
1431
		$cflink['default'] = trim($this->GetDefault());
1432
		if (empty($cflink['default']))
1433
			unset($cflink['default']);
1434
		$cflink['red'] = trim($this->GetRed());
1435
		if (empty($cflink['red']))
1436
			unset($cflink['red']);
1437
		$cflink['rio'] = trim($this->GetRio());
1438
		if (empty($cflink['rio']))
1439
			unset($cflink['rio']);
1440
		$cflink['ecn'] = trim($this->GetEcn());
1441
		if (empty($cflink['ecn']))
1442
			unset($cflink['ecn']);
1443
		if ($this->GetLinkshare() <> "") {
1444
			if ($this->GetL_m1() <> "") {
1445
				$cflink['linkshare1'] = $this->GetL_m1();
1446
				$cflink['linkshare2'] = $this->GetL_d();
1447
				$cflink['linkshare'] = "on";
1448
			} else {
1449
				unset($cflink['linkshare1']);
1450
				unset($cflink['linkshare2']);
1451
				unset($cflink['linkshare']);
1452
			}
1453
			if ($this->GetL_m2() <> "") {
1454
				$cflink['linkshare3'] = $this->GetL_m2();
1455
				$cflink['linkshare'] = "on";
1456
			} else {
1457
				unset($cflink['linkshare3']);
1458
				unset($cflink['linkshare']);
1459
			}
1460
		}
1461
		if ($this->GetRealtime() <> "") {
1462
			if ($this->GetR_m1() <> "") {
1463
				$cflink['realtime1'] = $this->GetR_m1();
1464
				$cflink['realtime2'] = $this->GetR_d();
1465
				$cflink['realtime'] = "on";
1466
			} else {
1467
				unset($cflink['realtime1']);
1468
                                unset($cflink['realtime2']);
1469
                                unset($cflink['realtime']);
1470
			}
1471
			if ($this->GetR_m2() <> "") {
1472
				$cflink['realtime3'] = $this->GetR_m2();
1473
				$cflink['realtime'] = "on";
1474
			} else {
1475
				unset($cflink['realtime3']);
1476
				unset($cflink['realtime']);
1477
			}
1478
		}
1479
		if ($this->GetUpperlimit() <> "") {
1480
			if ($this->GetU_m1() <> "") {
1481
				$cflink['upperlimit1'] = $this->GetU_m1();
1482
				$cflink['upperlimit2'] = $this->GetU_d();
1483
				$cflink['upperlimit'] = "on";
1484
			} else {
1485
				unset($cflink['upperlimit']);
1486
				unset($cflink['upperlimit1']);
1487
				unset($cflink['upperlimit2']);
1488
			}
1489
			if ($this->GetU_m2() <> "") {
1490
				$cflink['upperlimit3'] = $this->GetU_m2();
1491
				$cflink['upperlimit'] = "on";
1492
			} else {
1493
				unset($cflink['upperlimit3']);
1494
				unset($cflink['upperlimit']);
1495
			}
1496
		}
1497

    
1498
		if (is_array($this->subqueues)) {
1499
			$cflinkp['queue'] = array();
1500
			foreach ($this->subqueues as $q) {
1501
				$cflink['queue'][$q->GetQname()] = array();
1502
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1503
			}
1504
		}
1505
	}
1506

    
1507
	function delete_queue() { 
1508
		unref_on_altq_queue_list($this->GetQname());
1509
		cleanup_queue_from_rules($this->GetQname());
1510
		$parent =& $this->GetParent();
1511
		foreach ($this->subqueues as $q)  {
1512
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1513
			$q->delete_queue();
1514
		}
1515
		unset_object_by_reference($this->GetLink());
1516
	}
1517

    
1518
	/*
1519
	 * Should search even its children
1520
	 */
1521
	function &find_queue($interface, $qname) {
1522
		if ($qname == $this->GetQname()) 
1523
			return $this;
1524

    
1525
		foreach ($this->subqueues as $q) {
1526
			$result =& $q->find_queue("", $qname);
1527
			if ($result)
1528
				return $result;
1529
		}
1530
	}
1531

    
1532
	function &find_parentqueue($interface, $qname) {
1533
		if ($this->subqueues[$qname]) 
1534
			return $this;
1535
		foreach ($this->subqueues as $q) {
1536
			$result = $q->find_parentqueue("", $qname);
1537
			if ($result)
1538
				return $result;
1539
		}
1540
	}
1541
	
1542
	function validate_input($data, &$input_errors) {
1543
		parent::validate_input($data, $input_errors);
1544
		
1545
		$reqdfields[] = "bandwidth";
1546
		$reqdfieldsn[] = "Bandwidth";
1547
		$reqdfields[] = "bandwidthtype";
1548
		$reqdfieldsn[] = "Bandwidthtype";
1549

    
1550
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1551
		
1552
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1553
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1554
                        	$input_errors[] = "Bandwidth must be an integer.";
1555

    
1556
                	if ($data['bandwidth'] < 0)
1557
                        	$input_errors[] = "Bandwidth cannot be negative.";
1558

    
1559
			if ($data['bandwidthtype'] == "%") {
1560
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1561
					$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1562
			}
1563
		/*
1564
			$parent =& $this->GetParent();
1565
			switch ($data['bandwidthtype']) {
1566
			case "%":
1567
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1568
			default:
1569
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1570
				break;
1571
			}
1572
			if ($parent->GetAvailableBandwidth() < $myBw)
1573
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1574
		*/
1575
		}
1576

    
1577
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1578
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1579
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1580
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1581
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1582
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1583
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1584
			$input_errors[] = ("upperlimit d value needs to be numeric");
1585
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1586
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1587

    
1588
		/*
1589
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1590
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1591
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1592
			if (floatval($bw_1) < floatval($bw_2)) 
1593
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1594

    
1595
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1596
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1597
		}
1598
		*/
1599
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1600
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1601
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1602
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1603
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1604
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1605
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1606
			$input_errors[] = ("linkshare d value needs to be numeric");
1607
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1608
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1609
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1610
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1611
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1612
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1613

    
1614
		/*
1615
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1616
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1617
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1618
                	if (floatval($bw_1) < floatval($bw_2))
1619
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1620

    
1621
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1622
                        	$input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1623
		}
1624
		*/
1625

    
1626
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1627
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1628
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1629
			$input_errors[] = ("realtime d value needs to be numeric");
1630
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1631
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1632

    
1633
		/*
1634
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1635
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1636
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1637
                	if (floatval($bw_1) < floatval($bw_2))
1638
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1639

    
1640
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1641
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1642
		}
1643
		*/
1644
	}
1645

    
1646
	function ReadConfig(&$cflink) {
1647
		if (!empty($cflink['linkshare'])) {
1648
			if (!empty($cflink['linkshare1'])) {
1649
				$this->SetL_m1($cflink['linkshare1']);
1650
                                $this->SetL_d($cflink['linkshare2']);
1651
				$this->SetLinkshare();
1652
			} else {
1653
				$this->SetL_m1("");
1654
                                $this->SetL_d("");
1655
				$this->DisableLinkshare();
1656
			}
1657
			if (!empty($cflink['linkshare3'])) {
1658
                                $this->SetL_m2($cflink['linkshare3']);
1659
				$this->SetLinkshare();
1660
			}
1661
		} else
1662
			$this->DisableLinkshare();
1663
		if (!empty($cflink['realtime'])) {
1664
                        if (!empty($cflink['realtime1'])) {
1665
                                $this->SetR_m1($cflink['realtime1']);
1666
                                $this->SetR_d($cflink['realtime2']);
1667
				$this->SetRealtime();
1668
			} else {
1669
                                $this->SetR_m1("");
1670
                                $this->SetR_d("");
1671
				$this->DisableRealtime();
1672
			}
1673
                        if (!empty($cflink['realtime3'])) {
1674
                                $this->SetR_m2($cflink['realtime3']);
1675
				$this->SetRealtime();
1676
			}
1677
		} else
1678
			$this->DisableRealtime(); 
1679
		if (!empty($cflink['upperlimit'])) {
1680
                        if (!empty($cflink['upperlimit1'])) {
1681
                                $this->SetU_m1($cflink['upperlimit1']);
1682
                                $this->SetU_d($cflink['upperlimit2']);
1683
				$this->SetUpperlimit();
1684
			} else {
1685
                                $this->SetU_m1("");
1686
                                $this->SetU_d("");
1687
				$this->DisableUpperlimit();
1688
			}
1689
                        if (!empty($cflink['upperlimit3'])) {
1690
                                $this->SetU_m2($cflink['upperlimit3']);
1691
				$this->SetUpperlimit();
1692
			}
1693
		} else
1694
			$this->DisableUpperlimit();
1695
		parent::ReadConfig($cflink);
1696
	}
1697

    
1698
	function build_tree() {
1699
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1700
		$tree .= "\" ";
1701
		$tmpvalue = $this->GetDefault();
1702
		if (!empty($tmpvalue))
1703
			$tree .= " class=\"navlnk\"";
1704
		$tree .= " >" . $this->GetQname() . "</a>";
1705
		if (is_array($this->subqueues)) {
1706
			$tree .= "<ul>";
1707
			foreach ($this->subqueues as $q)  {
1708
				$tree .= $q->build_tree();
1709
			}	
1710
			$tree .= "</ul>";
1711
		}
1712
		$tree .= "</li>";
1713
		return $tree;
1714
	}
1715

    
1716
	/* Even this should take children into consideration */
1717
	function build_rules(&$default = false) {
1718

    
1719
		$pfq_rule = " queue ". $this->qname;
1720
		if ($this->GetInterface())
1721
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1722
		if ($this->GetBandwidth() && $this->GetBwscale())
1723
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1724
				
1725
		$tmpvalue = $this->GetQlimit();
1726
		if (!empty($tmpvalue))
1727
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1728
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1729
			$pfq_rule .= " hfsc ( ";
1730
			$tmpvalue = $this->GetRed();
1731
			if (!empty($tmpvalue)) {
1732
				$comma = 1;
1733
				$pfq_rule .= " red ";
1734
			}
1735
			
1736
			$tmpvalue = $this->GetRio();
1737
			if (!empty($tmpvalue)) {
1738
				if ($comma) 
1739
					$pfq_rule .= " ,";
1740
				$comma = 1;
1741
				$pfq_rule .= " rio ";
1742
			}
1743
			$tmpvalue = $this->GetEcn();
1744
			if (!empty($tmpvalue)) {
1745
				if ($comma) 
1746
					$pfq_rule .= " ,";
1747
				$comma = 1;
1748
				$pfq_rule .= " ecn ";
1749
			}
1750
			$tmpvalue = $this->GetDefault();
1751
			if (!empty($tmpvalue)) {
1752
				if ($comma)
1753
					$pfq_rule .= " ,";
1754
				$comma = 1;
1755
				$pfq_rule .= " default ";
1756
				$default = true;
1757
			}
1758

    
1759
			if ($this->GetRealtime() <> "")  {
1760
				if ($comma) 
1761
					$pfq_rule .= " , ";
1762
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1763
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1764
				else  if ($this->GetR_m2() <> "")
1765
					$pfq_rule .= " realtime " . $this->GetR_m2();
1766
				$comma = 1;
1767
			}
1768
			if ($this->GetLinkshare() <> "") {
1769
				if ($comma)
1770
					$pfq_rule .= " ,";
1771
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1772
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1773
				else if ($this->GetL_m2() <> "")
1774
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1775
				$comma = 1;
1776
			}
1777
			if ($this->GetUpperlimit() <> "") {
1778
				if ($comma)
1779
					$pfq_rule .= " ,";
1780
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1781
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1782
				else if ($this->GetU_m2() <> "")
1783
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1784
			}
1785
			$pfq_rule .= " ) ";
1786
		}
1787
		if (count($this->subqueues)) {
1788
			$i = count($this->subqueues);
1789
			$pfq_rule .= " { ";
1790
			foreach ($this->subqueues as $qkey => $qnone) {
1791
				if ($i > 1) {
1792
					$i--;
1793
					$pfq_rule .= " {$qkey}, ";
1794
				} else
1795
					$pfq_rule .= " {$qkey} ";
1796
			}
1797
			$pfq_rule .= " } \n";
1798
			foreach ($this->subqueues as $q)
1799
				$pfq_rule .= $q->build_rules(&$default);
1800
		}
1801

    
1802
		 $pfq_rule .= " \n";
1803
			
1804
		return $pfq_rule;
1805
	}
1806

    
1807
	function build_javascript() {
1808
		$javascript = parent::build_javascript();
1809
		$javascript .= "<script type=\"text/javascript\">";
1810
		$javascript .= "function enable_realtime(enable_over) { \n";
1811
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1812
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1813
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1814
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1815
		$javascript .= " } else { \n";
1816
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1817
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1818
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1819
		$javascript .= " } \n";
1820
		$javascript .= " } \n";
1821
		$javascript .= "function enable_linkshare(enable_over) { \n";
1822
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1823
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1824
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1825
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1826
		$javascript .= " } else { \n";
1827
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1828
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1829
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1830
		$javascript .= " } \n";
1831
		$javascript .= " } \n";
1832
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1833
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1834
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1835
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1836
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1837
		$javascript .= " } else { \n";
1838
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1839
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1840
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1841
		$javascript .= " } \n";
1842
			
1843
		$javascript .= "} \n";
1844
		$javascript .= "</script>";
1845

    
1846
		return $javascript;
1847
	}
1848

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

    
1950
		return $form;
1951
	}
1952

    
1953
	function update_altq_queue_data(&$data) { 
1954
		$this->ReadConfig($data);
1955
	}
1956

    
1957
	function wconfig() {
1958
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1959
		if (!is_array($cflink))
1960
			$cflink = array();
1961
		$cflink['name'] = $this->GetQname();
1962
		$cflink['interface'] = $this->GetInterface();
1963
		$cflink['qlimit'] = trim($this->GetQlimit());
1964
		if (empty($cflink['qlimit']))
1965
			unset($cflink['qlimit']);
1966
		$cflink['priority'] = $this->GetQpriority();
1967
		if (empty($cflink['priority']))
1968
			unset($cflink['priority']);
1969
		$cflink['description'] = $this->GetDescription();
1970
		if (empty($cflink['description']))
1971
			unset($cflink['description']);
1972
		$cflink['bandwidth'] = $this->GetBandwidth();
1973
		$cflink['bandwidthtype'] = $this->GetBwscale();
1974
		$cflink['enabled'] = $this->GetEnabled();
1975
		if (empty($cflink['enabled']))
1976
			unset($cflink['enabled']);
1977
		$cflink['default'] = $this->GetDefault();
1978
		if (empty($cflink['default']))
1979
			unset($cflink['default']);
1980
		$cflink['red'] = trim($this->GetRed());
1981
		if (empty($cflink['red']))
1982
			unset($cflink['red']);
1983
		$cflink['rio'] = $this->GetRio();
1984
		if (empty($cflink['rio']))
1985
			unset($cflink['rio']);
1986
		$cflink['ecn'] = trim($this->GetEcn());
1987
		if (empty($cflink['ecn']))
1988
			unset($cflink['ecn']);
1989
		if ($this->GetLinkshare() <> "") {
1990
			if ($this->GetL_m1() <> "") {
1991
				$cflink['linkshare1'] = $this->GetL_m1();
1992
				$cflink['linkshare2'] = $this->GetL_d();
1993
				$cflink['linkshare'] = "on";
1994
			} else {
1995
				unset($cflink['linkshare']);
1996
				unset($cflink['linkshare1']);
1997
				unset($cflink['linkshare2']);
1998
			}
1999
			if ($this->GetL_m2() <> "") {
2000
				$cflink['linkshare3'] = $this->GetL_m2();
2001
				$cflink['linkshare'] = "on";
2002
			} else {
2003
				unset($cflink['linkshare']);
2004
				unset($cflink['linkshare3']);
2005
			}
2006
		} else {
2007
			unset($cflink['linkshare']);
2008
			unset($cflink['linkshare1']);
2009
			unset($cflink['linkshare2']);
2010
			unset($cflink['linkshare3']);
2011
		}
2012
		if ($this->GetRealtime() <> "") {
2013
			if ($this->GetR_m1() <> "") {
2014
				$cflink['realtime1'] = $this->GetR_m1();
2015
				$cflink['realtime2'] = $this->GetR_d();
2016
				$cflink['realtime'] = "on";
2017
			} else {
2018
				unset($cflink['realtime']);
2019
				unset($cflink['realtime1']);
2020
				unset($cflink['realtime2']);
2021
			}
2022
			if ($this->GetR_m2() <> "") {
2023
				$cflink['realtime3'] = $this->GetR_m2();
2024
				$cflink['realtime'] = "on";
2025
			} else {
2026
				unset($cflink['realtime']);
2027
				unset($cflink['realtime3']);
2028
			}
2029
		} else {
2030
			unset($cflink['realtime']);
2031
			unset($cflink['realtime1']);
2032
			unset($cflink['realtime2']);
2033
			unset($cflink['realtime3']);
2034
		}
2035
		if ($this->GetUpperlimit() <> "") {
2036
			if ($this->GetU_m1() <> "") {
2037
				$cflink['upperlimit1'] = $this->GetU_m1();
2038
				$cflink['upperlimit2'] = $this->GetU_d();
2039
				$cflink['upperlimit'] = "on";
2040
			} else {
2041
				unset($cflink['upperlimit']);
2042
				unset($cflink['upperlimit1']);
2043
				unset($cflink['upperlimit2']);
2044
			}
2045
			if ($this->GetU_m2() <> "") {
2046
				$cflink['upperlimit3'] = $this->GetU_m2();
2047
				$cflink['upperlimit'] = "on";
2048
			} else {
2049
				unset($cflink['upperlimit']);
2050
				unset($cflink['upperlimit3']);
2051
			}
2052
		} else {
2053
			unset($cflink['upperlimit']);
2054
			unset($cflink['upperlimit1']);
2055
			unset($cflink['upperlimit2']);
2056
			unset($cflink['upperlimit3']);
2057
		}
2058
	}
2059
}
2060

    
2061
class cbq_queue extends priq_queue {
2062
	var $qborrow = "";
2063

    
2064
	function GetBorrow() {
2065
		return $this->qborrow;
2066
	}
2067
	function SetBorrow($borrow) {
2068
		$this->qborrow = $borrow;
2069
	}
2070
	function CanHaveChildren() {
2071
		return true;
2072
	}
2073

    
2074
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2075

    
2076
		if (!is_array($this->subqueues))
2077
			$this->subqueues = array();
2078
		$q =& new cbq_queue();
2079
		$q->SetInterface($this->GetInterface());
2080
		$q->SetParent(&$this);
2081
		$q->ReadConfig($qname);
2082
                $q->validate_input($qname, $input_errors);
2083
                if (count($input_errors)) {
2084
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2085
                        return $q;
2086
                }
2087
                switch ($q->GetBwscale()) {
2088
                case "%":
2089
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2090
                        break;
2091
                default:
2092
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2093
                        break;
2094
                }
2095
                $q->SetAvailableBandwidth($myBw);
2096
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2097

    
2098
		$q->SetEnabled("on");
2099
		$q->SetLink($path);
2100
		$this->subqueues[$q->GetQName()] = &$q;
2101
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2102
		if (is_array($qname['queue'])) {
2103
			foreach ($qname['queue'] as $key1 => $que) {
2104
				array_push($path, $key1);
2105
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2106
				array_pop($path);
2107
			}
2108
		}
2109

    
2110
		return $q;
2111
	}
2112

    
2113
	function copy_queue($interface, &$cflink) {
2114

    
2115
		$cflink['interface'] = $interface;
2116
		$cflink['qlimit'] = trim($this->GetQlimit());
2117
		if (empty($clink['qlimit']))
2118
			unset($cflink['qlimit']);
2119
		$cflink['priority'] = trim($this->GetQpriority());
2120
		if (empty($cflink['priority']))
2121
			unset($cflink['priority']);
2122
		$cflink['name'] = $this->GetQname();
2123
		$cflink['description'] = trim($this->GetDescription());
2124
		if (empty($cflink['description']))
2125
			unset($cflink['description']);
2126
		$cflink['bandwidth'] = $this->GetBandwidth();
2127
		$cflink['bandwidthtype'] = $this->GetBwscale();
2128
		$cflink['enabled'] = trim($this->GetEnabled());
2129
		if (empty($cflink['enabled']))
2130
			unset($cflink['enabled']);
2131
		$cflink['default'] = trim($this->GetDefault());
2132
		if (empty($cflink['default']))
2133
			unset($cflink['default']);
2134
		$cflink['red'] = trim($this->GetRed());
2135
		if (empty($cflink['red']))
2136
			unset($cflink['red']);
2137
		$cflink['rio'] = trim($this->GetRio());
2138
		if (empty($cflink['rio']))
2139
			unset($cflink['rio']);
2140
		$cflink['ecn'] = trim($this->GetEcn());
2141
		if (empty($cflink['ecn']))
2142
			unset($cflink['ecn']);
2143
		$cflink['borrow'] = trim($this->GetBorrow());
2144
		if (empty($cflink['borrow']))
2145
			unset($cflink['borrow']);
2146
		if (is_array($this->queues)) {
2147
			$cflinkp['queue'] = array();
2148
			foreach ($this->subqueues as $q) {
2149
				$cflink['queue'][$q->GetQname()] = array();
2150
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
2151
			}
2152
		}
2153
	}
2154
	
2155
	/*
2156
	 * Should search even its children
2157
	 */
2158
	function &find_queue($interface, $qname) {
2159
		if ($qname == $this->GetQname())
2160
			return $this;
2161
		foreach ($this->subqueues as $q) {
2162
			$result =& $q->find_queue("", $qname);
2163
			if ($result)
2164
				return $result;
2165
		}
2166
	}
2167

    
2168
	function &find_parentqueue($interface, $qname) {
2169
		if ($this->subqueues[$qname])
2170
			return $this;
2171
		foreach ($this->subqueues as $q) {
2172
			$result = $q->find_parentqueue("", $qname);
2173
			if ($result)
2174
				return $result;
2175
		}
2176
	}
2177

    
2178
	function delete_queue() {
2179
		unref_on_altq_queue_list($this->GetQname());
2180
		cleanup_queue_from_rules($this->GetQname());
2181
		foreach ($this->subqueues as $q) {
2182
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2183
			$q->delete_queue();
2184
		}
2185
		unset_object_by_reference($this->GetLink());
2186
	}
2187
	
2188
	function validate_input($data, &$input_errors) {
2189
		parent::validate_input($data, $input_errors);
2190
		
2191
		if ($data['priority'] > 7)
2192
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2193
		$reqdfields[] = "bandwidth";
2194
		$reqdfieldsn[] = "Bandwidth";
2195
		$reqdfields[] = "bandwidthtype";
2196
		$reqdfieldsn[] = "Bandwidthtype";
2197

    
2198
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2199
		
2200
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2201
			$input_errors[] = "Bandwidth must be an integer.";
2202

    
2203

    
2204
		if ($data['bandwidth'] < 0)
2205
                       $input_errors[] = "Bandwidth cannot be negative.";
2206

    
2207
		if ($data['bandwidthtype'] == "%") {
2208
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2209
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2210
		}
2211

    
2212
/*
2213
		$parent =& $this->GetParent();
2214
		switch ($data['bandwidthtype']) {
2215
		case "%":
2216
			$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2217
			break;
2218
		default:
2219
			$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2220
			break;
2221
		}
2222
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2223
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2224
*/
2225
	}
2226

    
2227
	function ReadConfig(&$q) {
2228
		parent::ReadConfig($q);
2229
		if (!empty($q['borrow']))
2230
			$this->SetBorrow("on");
2231
		else
2232
			$this->SetBorrow("");
2233
	}
2234
		
2235
	function build_javascript() {
2236
		return parent::build_javascript();
2237
	}
2238

    
2239
	function build_tree() {
2240
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2241
		$tree .= "\" ";
2242
		$tmpvalue = trim($this->GetDefault());
2243
		if (!empty($tmpvalue))
2244
			$tree .= " class=\"navlnk\"";
2245
		$tree .= " >" . $this->GetQname() . "</a>";
2246
		if (is_array($this->subqueues)) {
2247
			$tree .= "<ul>";
2248
			foreach ($this->subqueues as $q)  {
2249
				$tree .= $q->build_tree();
2250
			}	
2251
			$tree .= "</ul>";
2252
		}
2253
		$tree .= "</li>";
2254
		return $tree;
2255
	}
2256
		
2257
	/* Even this should take children into consideration */
2258
	function build_rules(&$default = false) {
2259
		$pfq_rule = "queue ". $this->qname;
2260
		if ($this->GetInterface())
2261
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2262
		if ($this->GetBandwidth() && $this->GetBwscale())
2263
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2264
		$tmpvalue = $this->GetQpriority();
2265
		if (!empty($tmpvalue))
2266
			$pfq_rule .= " priority " . $this->GetQpriority();
2267
		$tmpvalue = trim($this->GetQlimit());
2268
		if (!empty($tmpvalue))
2269
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2270
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow()) {
2271
			$pfq_rule .= " cbq ( ";
2272
			$tmpvalue = trim($this->GetRed());
2273
			if (!empty($tmpvalue)) {
2274
				$comma = 1;
2275
				$pfq_rule .= " red ";
2276
			}
2277
			$tmpvalue = trim($this->GetRio());
2278
			if (!empty($tmpvalue)) {
2279
				if ($comma) 
2280
					$pfq_rule .= " ,";
2281
				$comma = 1;
2282
				$pfq_rule .= " rio ";
2283
			}
2284
			$tmpvalue = trim($this->GetEcn());
2285
			if (!empty($tmpvalue)) {
2286
				if ($comma) 
2287
					$pfq_rule .= " ,";
2288
				$comma = 1;
2289
				$pfq_rule .= " ecn ";
2290
			}
2291
			$tmpvalue = trim($this->GetDefault());
2292
			if (!empty($tmpvalue)) {
2293
				if ($comma)
2294
					$pfq_rule .= " ,";
2295
				$comma = 1;
2296
				$pfq_rule .= " default ";
2297
				$default = true;
2298
			}
2299
			$tmpvalue = trim($this->GetBorrow());
2300
			if (!empty($tmpvalue)) {
2301
				if ($comma)
2302
					$pfq_rule .= ", ";
2303
				$pfq_rule .= " borrow ";
2304
			}
2305
			$pfq_rule .= " ) ";
2306
		} 
2307
		if (count($this->subqueues)) {
2308
			$i = count($this->subqueues);
2309
			$pfq_rule .= " { ";
2310
			foreach ($this->subqueues as $qkey => $qnone) {
2311
				if ($i > 1) {
2312
					$i--;
2313
					$pfq_rule .= " {$qkey}, ";
2314
				} else
2315
					$pfq_rule .= " {$qkey} ";
2316
			}
2317
			$pfq_rule .= " } \n";
2318
			foreach ($this->subqueues as $q)
2319
				$pfq_rule .= $q->build_rules($default);
2320
		}
2321

    
2322
		$pfq_rule .= " \n";
2323
		return $pfq_rule;
2324
	}
2325

    
2326
	function build_form() {
2327
		$form = parent::build_form();
2328
		$form .= "<tr>";
2329
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2330
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2331
		if ($this->GetBandwidth() > 0)
2332
			$form .= htmlspecialchars($this->GetBandwidth());
2333
		$form .= "\">";
2334
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2335
		$form .= "<option value=\"Gb\"";
2336
		if ($this->GetBwscale() == "Gb")
2337
			$form .= " selected=\"yes\"";
2338
		$form .= ">Gbit/s</option>";
2339
		$form .= "<option value=\"Mb\"";
2340
		if ($this->GetBwscale() == "Mb")
2341
			$form .= " selected=\"yes\"";
2342
		$form .= ">Mbit/s</option>";
2343
		$form .= "<option value=\"Kb\"";
2344
		if ($this->GetBwscale() == "Kb")
2345
			$form .= " selected=\"yes\"";
2346
		$form .= ">Kbit/s</option>";
2347
		$form .= "<option value=\"\"";
2348
		if ($this->GetBwscale() == "b")
2349
			$form .= " selected=\"yes\"";
2350
		$form .= ">Bit/s</option>";
2351
		$form .= "<option value=\"%\"";
2352
		if ($this->GetBwscale() == "%")
2353
			$form .= " selected=\"yes\"";
2354
		$form .= ">%</option>";
2355
		$form .= "</select> <br>";
2356
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2357
		$form .= "</span></td></tr>";
2358
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2359
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2360
		if($this->GetBorrow() == "on") 
2361
			$form .=  " CHECKED ";
2362
		$form .= "> Borrow from other queues when available<br></td></tr>";
2363

    
2364
		return $form;
2365
	}
2366

    
2367
	function update_altq_queue_data(&$data) { 
2368
		$this->ReadConfig($data);
2369
	}
2370

    
2371
	function wconfig() {
2372
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2373
		if (!is_array($cflink))
2374
			$cflink = array();
2375
		$cflink['interface'] = $this->GetInterface();
2376
		$cflink['qlimit'] = trim($this->GetQlimit());
2377
		if (empty($cflink['qlimit']))
2378
			unset($cflink['qlimit']);
2379
		$cflink['priority'] = $this->GetQpriority();
2380
		if (empty($cflink['priority']))
2381
			unset($cflink['priority']);
2382
		$cflink['name'] = $this->GetQname();
2383
		$cflink['description'] = $this->GetDescription();
2384
		if (empty($cflink['description']))
2385
			unset($cflink['description']);
2386
		$cflink['bandwidth'] = $this->GetBandwidth();
2387
		$cflink['bandwidthtype'] = $this->GetBwscale();
2388
		$cflink['enabled'] = trim($this->GetEnabled());
2389
		if (empty($cflink['enabled']))
2390
			unset($cflink['enabled']);
2391
		$cflink['default'] = trim($this->GetDefault());
2392
		if (empty($cflink['default']))
2393
			unset($cflink['default']);
2394
		$cflink['red'] = trim($this->GetRed());
2395
		if (empty($cflink['red']))
2396
			unset($cflink['red']);
2397
		$cflink['rio'] = trim($this->GetRio());
2398
		if (empty($cflink['rio']))
2399
			unset($cflink['rio']);
2400
		$cflink['ecn'] = trim($this->GetEcn());
2401
		if (empty($cflink['ecn']))
2402
			unset($cflink['ecn']);
2403
		$cflink['borrow'] = trim($this->GetBorrow());
2404
		if (empty($cflink['borrow']))
2405
			unset($cflink['borrow']);
2406
	}
2407
}
2408

    
2409
class fairq_queue extends priq_queue {
2410
	var $hogs;
2411
	var $buckets;
2412

    
2413
	function GetBuckets() {
2414
		return $this->buckets;
2415
	}
2416
	function SetBuckets($buckets) {
2417
		$this->buckets = $buckets;
2418
	}
2419
	function GetHogs() {
2420
		return $this->hogs;
2421
	}
2422
	function SetHogs($hogs) {
2423
		$this->hogs = $hogs;
2424
	}
2425
	function CanHaveChildren() {
2426
		return false;
2427
	}
2428

    
2429

    
2430
	function copy_queue($interface, &$cflink) {
2431
                $cflink['interface'] = $interface;
2432
                $cflink['qlimit'] = $this->GetQlimit();
2433
                $cflink['priority'] = $this->GetQpriority();
2434
                $cflink['name'] = $this->GetQname();
2435
                $cflink['description'] = $this->GetDescription();
2436
                $cflink['bandwidth'] = $this->GetBandwidth();
2437
                $cflink['bandwidthtype'] = $this->GetBwscale();
2438
                $cflink['enabled'] = $this->GetEnabled();
2439
                $cflink['default'] = $this->GetDefault();
2440
                $cflink['red'] = $this->GetRed();
2441
                $cflink['rio'] = $this->GetRio();
2442
                $cflink['ecn'] = $this->GetEcn();
2443
                $cflink['buckets'] = $this->GetBuckets();
2444
		$cflink['hogs'] = $this->GetHogs();
2445
	}
2446
	
2447
	/*
2448
	 * Should search even its children
2449
	 */
2450
	function &find_queue($interface, $qname) {
2451
		if ($qname == $this->GetQname())
2452
			return $this;
2453
	}
2454

    
2455
	function find_parentqueue($interface, $qname) { return; }
2456

    
2457
	function delete_queue() {
2458
		unref_on_altq_queue_list($this->GetQname());
2459
		cleanup_queue_from_rules($this->GetQname());
2460
		unset_object_by_reference($this->GetLink());
2461
	}
2462
	
2463
	function validate_input($data, &$input_errors) {
2464
		parent::validate_input($data, $input_errors);
2465
		
2466
		if ($data['priority'] > 255)
2467
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2468
		$reqdfields[] = "bandwidth";
2469
		$reqdfieldsn[] = "Bandwidth";
2470
		$reqdfields[] = "bandwidthtype";
2471
		$reqdfieldsn[] = "Bandwidthtype";
2472

    
2473
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2474
		
2475
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2476
	                 $input_errors[] = "Bandwidth must be an integer.";
2477

    
2478

    
2479
	        if ($data['bandwidth'] < 0)
2480
                       $input_errors[] = "Bandwidth cannot be negative.";
2481

    
2482

    
2483
        	if ($data['bandwidthtype'] == "%") {
2484
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2485
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2486
           	}
2487

    
2488
/*
2489
           	$parent =& $this->GetParent();
2490
           	switch ($data['bandwidthtype']) {
2491
                       case "%":
2492
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2493
                       default:
2494
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2495
                             break;
2496
           	}
2497
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2498
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2499
*/
2500
	}
2501
	
2502
	function ReadConfig(&$q) {
2503
		parent::ReadConfig($q);
2504
		if (!empty($q['buckets']))
2505
			$this->SetBuckets($q['buckets']);
2506
		else
2507
			$this->SetBuckets("");
2508
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2509
			$this->SetHogs($q['hogs']);
2510
		else
2511
			$this->SetHogs("");
2512
	}
2513
		
2514
	function build_javascript() {
2515
		return parent::build_javascript();
2516
	}
2517

    
2518
	function build_tree() {
2519
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2520
		$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2521
		$tree .= "\" ";
2522
		$tmpvalue = trim($this->GetDefault());
2523
		if (!empty($tmpvalue))
2524
			$tree .= " class=\"navlnk\"";
2525
		$tree .= " >" . $this->GetQname() . "</a>";
2526
		$tree .= "</li>";
2527
		return $tree;
2528
	}
2529
		
2530
	/* Even this should take children into consideration */
2531
	function build_rules(&$default = false) {
2532
		$pfq_rule = "queue ". $this->qname;
2533
		if ($this->GetInterface())
2534
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2535
		if ($this->GetBandwidth() && $this->GetBwscale())
2536
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2537
		$tmpvalue = trim($this->GetQpriority());
2538
		if (!empty($tmpvalue))
2539
			$pfq_rule .= " priority " . $this->GetQpriority();
2540
		$tmpvalue = trim($this->GetQlimit());
2541
		if (!empty($tmpvalue))
2542
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2543
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2544
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2545
			$pfq_rule .= " fairq ( ";
2546
			$tmpvalue = trim($this->GetRed());
2547
			if (!empty($tmpvalue)) {
2548
				$comma = 1;
2549
				$pfq_rule .= " red ";
2550
			}
2551
			$tmpvalue = trim($this->GetRio());
2552
			if (!empty($tmpvalue)) {
2553
				if ($comma) 
2554
					$pfq_rule .= " ,";
2555
				$comma = 1;
2556
				$pfq_rule .= " rio ";
2557
			}
2558
			$tmpvalue = trim($this->GetEcn());
2559
			if (!empty($tmpvalue)) {
2560
				if ($comma) 
2561
					$pfq_rule .= " ,";
2562
				$comma = 1;
2563
				$pfq_rule .= " ecn ";
2564
			}
2565
			$tmpvalue = trim($this->GetDefault());
2566
			if (!empty($tmpvalue)) {
2567
				if ($comma)
2568
					$pfq_rule .= " ,";
2569
				$comma = 1;
2570
				$pfq_rule .= " default ";
2571
				$default = true;
2572
			}
2573
			$tmpvalue = trim($this->GetBuckets());
2574
			if (!empty($tmpvalue)) {
2575
				if ($comma)
2576
					$pfq_rule .= ", ";
2577
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2578
			}
2579
			$tmpvalue = trim($this->GetHogs());
2580
			if (!empty($tmpvalue)) {
2581
				if ($comma)
2582
					$pfq_rule .= ", ";
2583
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2584
			}
2585
				$pfq_rule .= " ) ";
2586
		} 
2587

    
2588
		$pfq_rule .= " \n";
2589
		return $pfq_rule;
2590
	}
2591

    
2592
	function build_form() {
2593
		$form = parent::build_form();
2594
		$form .= "<tr>";
2595
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2596
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2597
		if ($this->GetBandwidth() > 0)
2598
			$form .= htmlspecialchars($this->GetBandwidth());
2599
		$form .= "\">";
2600
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2601
		$form .= "<option value=\"Gb\"";
2602
		if ($this->GetBwscale() == "Gb")
2603
			$form .= " selected=\"yes\"";
2604
		$form .= ">Gbit/s</option>";
2605
		$form .= "<option value=\"Mb\"";
2606
		if ($this->GetBwscale() == "Mb")
2607
			$form .= " selected=\"yes\"";
2608
		$form .= ">Mbit/s</option>";
2609
		$form .= "<option value=\"Kb\"";
2610
		if ($this->GetBwscale() == "Kb")
2611
			$form .= " selected=\"yes\"";
2612
		$form .= ">Kbit/s</option>";
2613
		$form .= "<option value=\"\"";
2614
		if ($this->GetBwscale() == "b")
2615
			$form .= " selected=\"yes\"";
2616
		$form .= ">Bit/s</option>";
2617
		$form .= "<option value=\"%\"";
2618
		if ($this->GetBwscale() == "%")
2619
			$form .= " selected=\"yes\"";
2620
		$form .= ">%</option>";
2621
		$form .= "</select> <br>";
2622
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2623
		$form .= "</span></td></tr>";
2624
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2625
		$form .= "<td class=\"vtable\"><table><tr><td>";
2626
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2627
		$tmpvalue = trim($this->GetBuckets());
2628
		if(!empty($tmpvalue)) 
2629
			$form .=  $this->GetBuckets();
2630
		$form .= "\"> Number of buckets available.<br></td></tr>";
2631
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2632
		$tmpvalue = trim($this->GetHogs());
2633
		if(!empty($tmpvalue)) 
2634
			$form .=  $this->GetHogs();
2635
		$form .= "\"> Bandwidth limit for hosts to not saturate link.<br></td></tr>";
2636
		$form .= "</table></td></tr>";
2637
		return $form;
2638
	}
2639

    
2640
	function update_altq_queue_data(&$data) { 
2641
		$this->ReadConfig($data);
2642
	}
2643

    
2644
	function wconfig() {
2645
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2646
		if (!is_array($cflink))
2647
			$cflink = array();
2648
		$cflink['interface'] = $this->GetInterface();
2649
		$cflink['qlimit'] = trim($this->GetQlimit());
2650
		if (empty($cflink['qlimit']))
2651
			unset($cflink['qlimit']);
2652
		$cflink['priority'] = trim($this->GetQpriority());
2653
		if (empty($cflink['priority']))
2654
			unset($cflink['priority']);
2655
		$cflink['name'] = $this->GetQname();
2656
		$cflink['description'] = trim($this->GetDescription());
2657
		if (empty($cflink['description']))
2658
			unset($cflink['description']);
2659
		$cflink['bandwidth'] = $this->GetBandwidth();
2660
		$cflink['bandwidthtype'] = $this->GetBwscale();
2661
		$cflink['enabled'] = $this->GetEnabled();
2662
		if (empty($cflink['enabled']))
2663
			unset($cflink['enabled']);
2664
		$cflink['default'] = trim($this->GetDefault());
2665
		if (empty($cflink['default']))
2666
			unset($cflink['default']);
2667
		$cflink['red'] = trim($this->GetRed());
2668
		if (empty($cflink['red']))
2669
			unset($cflink['red']);
2670
		$cflink['rio'] = trim($this->GetRio());
2671
		if (empty($cflink['rio']))
2672
			unset($cflink['rio']);
2673
		$cflink['ecn'] = trim($this->GetEcn());
2674
		if (empty($cflink['ecn']))
2675
			unset($cflink['ecn']);
2676
		$cflink['buckets'] = trim($this->GetBuckets());
2677
		if (empty($cflink['buckets']))
2678
			unset($cflink['buckets']);
2679
		$cflink['hogs'] = trim($this->GetHogs());
2680
		if (empty($cflink['hogs']))
2681
			unset($cflink['hogs']);
2682
	}
2683
}
2684

    
2685

    
2686
/*
2687
 * dummynet(4) wrappers.
2688
 */
2689

    
2690

    
2691
/*
2692
 * List of respective objects!
2693
 */
2694
$dummynet_pipe_list = array();
2695

    
2696
class dummynet_class {
2697
        var $qname;
2698
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2699
        var $qlimit;
2700
        var $description;
2701
	var $qenabled;
2702
	var $link;
2703
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2704
        var $plr;
2705

    
2706
        var $buckets;
2707
        /* mask parameters */
2708
        var $mask;
2709
        var $noerror;
2710

    
2711
        /* Accessor functions */
2712
        function SetLink($link) {
2713
                $this->link = $link;
2714
        }
2715
        function GetLink() {
2716
                return $this->link;
2717
        }
2718
	function Getmask() {
2719
		return $this->mask;
2720
	}
2721
	function SetMask($mask) {
2722
		$this->mask = $mask;
2723
	}
2724
	function &GetParent() {
2725
		return $this->qparent;
2726
	}
2727
	function SetParent(&$parent) {
2728
		$this->qparent = &$parent;
2729
	}
2730
        function GetEnabled() {
2731
                return $this->qenabled;
2732
        }
2733
        function SetEnabled($value) {
2734
                $this->qenabled = $value;
2735
        }
2736
	function CanHaveChildren() {
2737
		return false;
2738
        }
2739
	function CanBeDeleted() {
2740
                return true;
2741
        }
2742
        function GetQname() {
2743
                return $this->qname;
2744
        }
2745
        function SetQname($name) {
2746
                $this->qname = trim($name);
2747
        }
2748
        function GetQlimit() {
2749
                return $this->qlimit;
2750
        }
2751
        function SetQlimit($limit) {
2752
               	$this->qlimit = $limit;
2753
        }
2754
        function GetDescription() {
2755
                return $this->description;
2756
        }
2757
        function SetDescription($str) {
2758
                $this->description = trim($str);
2759
        }
2760
        function GetFirstime() {
2761
                return $this->firsttime;
2762
        }
2763
        function SetFirsttime($number) {
2764
                $this->firsttime = $number;
2765
        }
2766
        function GetBuckets() {
2767
                return $this->buckets;
2768
        }
2769
        function SetBuckets($buckets) {
2770
                $this->buckets = $buckets;
2771
        }
2772
	function SetNumber($number) {
2773
		$this->qnumber = $number;
2774
	}
2775
	function GetNumber() {
2776
		return $this->qnumber;
2777
	}
2778
        function GetPlr() {
2779
                return $this->plr;
2780
        }
2781
        function SetPlr($plr) {
2782
                $this->plr = $plr;
2783
        }
2784

    
2785
	function build_javascript() { return; } /* Do not remove */
2786

    
2787
	function validate_input($data, &$input_errors) {
2788
		$reqdfields[] = "bandwidth";
2789
		$reqdfieldsn[] = "Bandwidth";
2790
		$reqdfields[] = "bandwidthtype";
2791
		$reqdfieldsn[] = "Bandwidthtype";
2792
		$reqdfields[] = "newname";
2793
		$reqdfieldsn[] = "Name";
2794
	
2795
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2796

    
2797
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2798
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2799
            		$input_errors[] = "Plr must be an integer between 1 and 100.";
2800
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2801
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2802
            		$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2803
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2804
            		$input_errors[] = "Queue limit must be an integer";
2805
        	if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]+$/", $data['newname']))
2806
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2807
        	if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2808
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2809
	}
2810
}
2811

    
2812
class dnpipe_class extends dummynet_class {
2813
        var $delay;
2814
	var $qbandwidth;
2815
	var $qbandwidthtype;
2816

    
2817
		/* This is here to help on form building and building rules/lists */
2818
        var $subqueues = array();
2819

    
2820
	function CanHaveChildren() {
2821
	        return true;
2822
        }
2823
	function SetDelay($delay) {
2824
		$this->delay = $delay;
2825
	}
2826
	function GetDelay() {
2827
		return $this->delay;
2828
	}
2829
	function GetBwscale() {
2830
                return $this->qbandwidthtype;
2831
        }
2832
        function SetBwscale($scale) {
2833
               	$this->qbandwidthtype = $scale;
2834
        }		
2835
	function delete_queue() {
2836
		cleanup_dnqueue_from_rules($this->GetQname());
2837
		foreach ($this->subqueues as $q)
2838
			$q->delete_queue();
2839
		unset_dn_object_by_reference($this->GetLink());
2840
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2841
        }
2842
        function GetBandwidth() {
2843
                return $this->qbandwidth;
2844
        }
2845
        function SetBandwidth($bandwidth) {
2846
                $this->qbandwidth = $bandwidth;
2847
        }
2848

    
2849
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2850

    
2851
		if (!is_array($this->subqueues))
2852
			$this->subqueues = array();
2853
			
2854
		$q =& new dnqueue_class();
2855
		$q->SetLink($path);
2856
		$q->SetEnabled("on");
2857
		$q->SetPipe($this->GetQname());
2858
		$q->SetParent(&$this);
2859
		$q->ReadConfig($queue);
2860
		$q->validate_input($queue, $input_errors);
2861
		if (count($input_errors)) {
2862
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2863
			return $q;
2864
		}
2865
		$this->subqueues[$q->GetQname()] = &$q;
2866
            
2867
		return $q;
2868
	}
2869

    
2870
	function &get_queue_list($q = null) {
2871
		$qlist = array();
2872

    
2873
		$qlist[$this->GetQname()] = $this->GetNumber();
2874
		if (is_array($this->subqueues)) {
2875
			foreach ($this->subqueues as $queue)
2876
				$queue->get_queue_list(&$qlist);
2877
		}
2878
		return $qlist;
2879
	}
2880
		
2881
        /*
2882
         * Should search even its children
2883
         */
2884
        function &find_queue($pipe, $qname) {
2885
                if ($qname == $this->GetQname()) 
2886
                        return $this;
2887
               	foreach ($this->subqueues as $q) {
2888
                       	$result =& $q->find_queue("", $qname);
2889
						if ($result)
2890
                       	        return $result;
2891
               	}
2892
        }
2893

    
2894
	function &find_parentqueue($pipe, $qname) {
2895
		return NULL;
2896
       	}
2897

    
2898
	function validate_input($data, &$input_errors) {
2899
		parent::validate_input($data, $input_errors);
2900

    
2901
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2902
       		     	$input_errors[] = "Bandwidth must be an integer.";
2903
		if ($data['delay'] && (!is_numeric($data['delay'])))
2904
            		$input_errors[] = "Delay must be an integer.";
2905
		}
2906

    
2907
	function ReadConfig(&$q) {
2908
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
2909
			$this->SetQname($q['newname']);
2910
		} else if (!empty($q['newname'])) {
2911
			$this->SetQname($q['newname']);
2912
		} else {
2913
			$this->SetQname($q['name']);
2914
		}
2915
		$this->SetNumber($q['number']);
2916
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2917
			$this->SetBandwidth($q['bandwidth']);
2918
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2919
				$this->SetBwscale($q['bandwidthtype']);
2920
		}
2921
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2922
              		$this->SetQlimit($q['qlimit']);
2923
		else
2924
              		$this->SetQlimit("");
2925
		if (isset($q['mask']) && $q['mask'] <> "")
2926
              		$this->SetMask($q['mask']);
2927
		else
2928
              		$this->SetMask("");
2929
		if (isset($q['buckets']) && $q['buckets'] <> "")
2930
              		$this->SetBuckets($q['buckets']);
2931
		else
2932
              		$this->SetBuckets("");
2933
            	if (isset($q['plr']) && $q['plr'] <> "")
2934
            		$this->SetPlr($q['plr']);
2935
		else
2936
            		$this->SetPlr("");
2937
		if (isset($q['delay']) && $q['delay'] <> "")
2938
            		$this->SetDelay($q['delay']);
2939
		else
2940
			$this->SetDelay(0);
2941
            	if (isset($q['description']) && $q['description'] <> "")
2942
			$this->SetDescription($q['description']);
2943
		else
2944
			$this->SetDescription("");
2945
		$this->SetEnabled($q['enabled']);
2946

    
2947
        }
2948

    
2949
	function build_tree() {
2950
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2951
		$tree .= $this->GetQname() . "</a>";
2952
		if (is_array($this->subqueues)) {
2953
			$tree .= "<ul>";
2954
			foreach ($this->subqueues as $q)  {
2955
				$tree .= $q->build_tree();
2956
			}	
2957
			$tree .= "</ul>";
2958
		}
2959
		$tree .= "</li>";
2960
		
2961
		return $tree;
2962
	}
2963

    
2964
        function build_rules() {
2965
		if ($this->GetEnabled() == "")
2966
			return;
2967

    
2968
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2969
		if ($this->GetBandwidth() && $this->GetBwscale())
2970
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2971
		if ($this->GetQlimit())
2972
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2973
		if ($this->GetPlr())
2974
			$pfq_rule .= " plr " . $this->GetPlr();
2975
		if ($this->GetBuckets())
2976
			$pfq_rule .= " buckets " . $this->GetBuckets();
2977
		if ($this->GetDelay())
2978
			$pfq_rule .= " delay " . $this->GetDelay();
2979

    
2980
		$mask = $this->GetMask();
2981
		if (!empty($mask)) {
2982
			/* XXX TODO extend this to support more complicated masks */
2983
			switch ($mask) {
2984
			case 'srcaddress':
2985
				$pfq_rule .= " mask src-ip 0xffffffff ";
2986
				break;
2987
			case 'dstaddress':
2988
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2989
				break;
2990
			default:
2991
				break;
2992
			}
2993
    		}            
2994
		$pfq_rule .= "\n";
2995

    
2996
		if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2997
			foreach ($this->subqueues as $q)
2998
			$pfq_rule .= $q->build_rules();
2999
		}
3000
		$pfq_rule .= " \n";
3001

    
3002
		return $pfq_rule;
3003
        }
3004

    
3005
	function update_dn_data(&$data) { 
3006
		$this->ReadConfig($data);
3007
	}
3008

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

    
3088
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3089
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3090
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3091
		$form .= $this->GetDelay() . "\">";
3092
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3093
		$form .= "should specify 0 here (or leave the field empty)</span>";
3094
		$form .= "</td></tr><br/>";
3095
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3096
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3097
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3098
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3099
		$form .= $this->GetPlr() . "\">";
3100
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3101
        	$form .= "should specify 0 here (or leave the field empty).";
3102
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3103
		$form .= "</td></tr>";
3104
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3105
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3106
		$form .= "<td class=\"vncellreq\">";
3107
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3108
		$form .= $this->GetQlimit() . "\">";
3109
		$form .= "&nbsp;slots<br>";
3110
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3111
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
3112
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
3113
		$form .= "are delivered to their destination.</span>";
3114
		$form .= "</td></tr>";
3115
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3116
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3117
                $form .= "<td class=\"vncellreq\">";
3118
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3119
                $form .= $this->GetBuckets() . "\">";
3120
                $form .= "&nbsp;slots<br>";
3121
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3122
                $form .= "should leave the field empty. It increases the hash size set.";
3123
                $form .= "</td></tr>";
3124

    
3125
		return $form;
3126
			
3127
		}
3128

    
3129
	function wconfig() {
3130
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3131
            	if (!is_array($cflink))
3132
            		$cflink = array();
3133
		$cflink['name'] = $this->GetQname();
3134
		$cflink['number'] = $this->GetNumber();
3135
            	$cflink['qlimit'] = $this->GetQlimit();
3136
            	$cflink['plr'] = $this->GetPlr();
3137
            	$cflink['description'] = $this->GetDescription();
3138
		$cflink['bandwidth'] = $this->GetBandwidth();
3139
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3140
		$cflink['enabled'] = $this->GetEnabled();
3141
		$cflink['buckets'] = $this->GetBuckets();
3142
		$cflink['mask'] = $this->GetMask();
3143
		$cflink['delay'] = $this->GetDelay();
3144
	}
3145

    
3146
}
3147

    
3148
class dnqueue_class extends dummynet_class {
3149
        var $pipeparent;
3150
        var $weight;
3151

    
3152
        function GetWeight() {
3153
                return $this->weight;
3154
        }
3155
        function SetWeight($weight) {
3156
                $this->weight = $weight;
3157
        }
3158
	function GetPipe() {
3159
		return $this->pipeparent;
3160
	}
3161
	function SetPipe($pipe) {
3162
		$this->pipeparent = $pipe;
3163
	}
3164

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

    
3168
	function delete_queue() {
3169
		cleanup_dnqueue_from_rules($this->GetQname());
3170
		unset_dn_object_by_reference($this->GetLink());
3171
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3172
        }
3173

    
3174
	function validate_input($data, &$input_errors) {
3175
		parent::validate_input($data, $input_errors);
3176

    
3177
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3178
			($data['weight'] < 1 && $data['weight'] > 100))) 
3179
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3180
	}
3181

    
3182
        /*
3183
         * Should search even its children
3184
         */
3185
        function &find_queue($pipe, $qname) {
3186
                if ($qname == $this->GetQname()) 
3187
                	return $this;
3188
		else
3189
			return NULL;
3190
        }
3191

    
3192
	function &find_parentqueue($pipe, $qname) {
3193
		return $this->qparent;
3194
        }
3195

    
3196
        function &get_queue_list(&$qlist) {
3197
		if ($this->GetEnabled() == "")
3198
			return;
3199
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3200
        }		
3201

    
3202
	function ReadConfig(&$q) {
3203
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
3204
			$this->SetQname($q['newname']);
3205
		} else if (!empty($q['newname'])) {
3206
			$this->SetQname($q['newname']);
3207
		} else {
3208
			$this->SetQname($q['name']);
3209
		}
3210
		$this->SetNumber($q['number']);
3211
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3212
       		       	$this->SetQlimit($q['qlimit']);
3213
		else
3214
       		       	$this->SetQlimit("");
3215
		if (isset($q['mask']) && $q['mask'] <> "")
3216
              		$this->SetMask($q['mask']);
3217
		else
3218
              		$this->SetMask("");
3219
       		if (isset($q['weight']) && $q['weight'] <> "")
3220
            		$this->SetWeight($q['weight']);
3221
		else
3222
            		$this->SetWeight("");
3223
            	if (isset($q['description']) && $q['description'] <> "")
3224
			$this->SetDescription($q['description']);
3225
		else
3226
			$this->SetDescription("");
3227
		$this->SetEnabled($q['enabled']);
3228
        }
3229

    
3230
	function build_tree() {
3231
		$parent =& $this->GetParent();
3232
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3233
		$tree .= $this->GetQname() . "</a>";
3234
		$tree .= "</li>";
3235
		
3236
		return $tree;
3237
	}
3238

    
3239
        function build_rules() {
3240
		if ($this->GetEnabled() == "")
3241
			return; 
3242

    
3243
		$parent =& $this->GetParent();
3244
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3245
		if ($this->GetQlimit())
3246
                    	$pfq_rule .= " queue " . $this->GetQlimit();
3247
		if ($this->GetWeight())
3248
			$pfq_rule .= " weight " . $this->GetWeight();
3249
		if ($this->GetBuckets())
3250
			$pfq_rule .= " buckets " . $this->GetBuckets();
3251
		$mask = $this->GetMask();
3252
		if (!empty($mask)) {
3253
			/* XXX TODO extend this to support more complicated masks */
3254
			switch ($mask) {
3255
			case 'srcaddress':
3256
				$pfq_rule .= " mask src-ip 0xffffffff ";
3257
				break;
3258
			case 'dstaddress':
3259
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3260
				break;
3261
			default:
3262
				break;
3263
			}
3264
			$pfq_rule .= "\n";
3265
		}
3266

    
3267
		return $pfq_rule;
3268
	}
3269

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

    
3362
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3363
		$form .= " value=\"" . $this->GetPipe() . "\">";
3364

    
3365
		return $form;
3366
			
3367
	}
3368

    
3369
        function update_dn_data(&$data) { 
3370
		$this->ReadConfig($data);
3371
	}
3372

    
3373
	function wconfig() {
3374
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3375
            	if (!is_array($cflink))
3376
            		$cflink = array();
3377
		$cflink['name'] = $this->GetQname();
3378
		$cflink['number'] = $this->GetNumber();
3379
            	$cflink['qlimit'] = $this->GetQlimit();
3380
            	$cflink['description'] = $this->GetDescription();
3381
		$cflink['weight'] = $this->GetWeight();
3382
		$cflink['enabled'] = $this->GetEnabled();
3383
		$cflink['buckets'] = $this->GetBuckets();
3384
		$cflink['mask'] = $this->GetMask();
3385
	}
3386
}
3387

    
3388
// List of layer7 objects
3389
$layer7_rules_list = array();
3390

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

    
3588
class l7rule {
3589
    
3590
    var $rprotocol; //protocol
3591
    var $rstructure; //action, limiter, queue
3592
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3593
    
3594
    //Auxiliary Functions
3595
    
3596
    function GetRProtocol() {
3597
        return $this->rprotocol;
3598
    }
3599
    function SetRProtocol($rprotocol) {
3600
        $this->rprotocol = $rprotocol;
3601
    }
3602
    function GetRStructure() {
3603
        return $this->rstructure;
3604
    }
3605
    function SetRStructure($rstructure) {
3606
        $this->rstructure = $rstructure;
3607
    }
3608
    function GetRBehaviour() {
3609
        return $this->rbehaviour;
3610
    }
3611
    function SetRBehaviour($rbehaviour) {
3612
        $this->rbehaviour = $rbehaviour;
3613
    }
3614
    
3615
    //XXX Do we need to test any particularity for AltQ queues?
3616
    function build_rules() {
3617
	global $dummynet_pipe_list;
3618
	switch ($this->GetRStructure()) {
3619
		case "limiter":
3620
			read_dummynet_config();
3621
			$dn_list =& get_unique_dnqueue_list();
3622
			$found = false;
3623
			if(is_array($dn_list)) {
3624
				foreach($dn_list as $key => $value) {
3625
					if($key == $this->GetRBehaviour()) {
3626
						if($value[0] == "?")
3627
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3628
						else
3629
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3630
						$found = true;
3631
					}
3632
					if($found)
3633
						break;
3634
				}
3635
			}
3636
			break;
3637
		default: //This is for action and for altq
3638
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3639
			break;
3640
	}
3641
        return $l7rule;
3642
    }
3643
}
3644

    
3645
/*
3646
 * This function allows to return an array with all the used divert socket ports
3647
 */
3648
function get_divert_ports() {
3649
    global $layer7_rules_list;
3650
    $dports = array();
3651
    
3652
    foreach($layer7_rules_list as $l7r)
3653
        $dports[] = $l7r->GetRPort();
3654
    
3655
    return $dports;
3656
}
3657

    
3658
function &get_l7c_reference_to_me_in_config(&$name) {
3659
	global $config;
3660
	
3661
	$ptr = NULL;
3662
	
3663
	if(is_array($config['l7shaper']['container'])) {
3664
		foreach($config['l7shaper']['container'] as $key => $value) {
3665
			if($value['name'] == $name)
3666
				$ptr =& $config['l7shaper']['container'][$key];
3667
		}
3668
	}	
3669
	return $ptr;
3670
// $ptr can be null. has to be checked later
3671
}
3672

    
3673
function unset_l7_object_by_reference(&$name) {
3674
	global $config;
3675
        
3676
	if(is_array($config['l7shaper']['container'])) {
3677
		foreach($config['l7shaper']['container'] as $key => $value) {
3678
			if($value['name'] == $name) {
3679
				unset($config['l7shaper']['container'][$key]['l7rules']);
3680
				unset($config['l7shaper']['container'][$key]);
3681
				break;
3682
			}
3683
		}
3684
	}
3685
}
3686

    
3687
function read_layer7_config() {
3688
    global $layer7_rules_list, $config;
3689
    
3690
    $l7cs = &$config['l7shaper']['container'];
3691
    
3692
    $layer7_rules_list = array();
3693
    
3694
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3695
	return;
3696
    
3697
    foreach ($l7cs as $conf) {
3698
	if (empty($conf['name']))
3699
		continue; /* XXX: grrrrrr at php */ 
3700
        $root =& new layer7();
3701
        $root->ReadConfig($conf['name'],$conf);
3702
        $layer7_rules_list[$root->GetRName()] = &$root;
3703
    }
3704
}
3705

    
3706
function generate_layer7_files() {
3707
    global $layer7_rules_list, $g;
3708
    
3709
    read_layer7_config();
3710
    
3711
    if (!empty($layer7_rules_list)) {
3712
	if (!is_module_loaded("ipdivert.ko"))
3713
		mwexec("/sbin/kldload ipdivert.ko");
3714

    
3715
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3716
    }
3717
    
3718
    foreach($layer7_rules_list as $l7rules) {
3719
        if($l7rules->GetREnabled()) {
3720
            $filename = $l7rules->GetRName() . ".l7";
3721
            $path = "{$g['tmp_path']}/" . $filename;
3722
        
3723
            $rules = $l7rules->build_l7_rules();
3724
        
3725
            $fp = fopen($path,'w');
3726
            fwrite($fp,$rules);
3727
            fclose($fp);
3728
        }
3729
    }
3730
}
3731

    
3732
function layer7_start_l7daemon() {
3733
    global $layer7_rules_list, $g;
3734

    
3735
    /*
3736
     * XXX: ermal - Needed ?!
3737
     * read_layer7_config();
3738
     */
3739

    
3740
    foreach($layer7_rules_list as $l7rules) {
3741
        if($l7rules->GetREnabled()) {
3742
            $filename = $l7rules->GetRName() . ".l7";
3743
            $path = "{$g['tmp_path']}/" . $filename;
3744

    
3745
	    unset($l7pid);
3746
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3747
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3748
	    if (count($l7pid) > 0) {
3749
		log_error("Sending HUP signal to {$l7pid[0]}");
3750
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3751
	    } else {
3752
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3753
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 8 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3754
		mwexec_bg($ipfw_classifyd_init);
3755
	    }
3756
        }
3757
    }
3758
}
3759

    
3760
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3761
function generate_protocols_array() {
3762
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3763
	$protocols_new = array();
3764
	if(is_array($protocols)) {
3765
		foreach($protocols as $key => $proto) {
3766
			if (strstr($proto, ".pat"))
3767
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3768
		}
3769
		sort($protocols_new);
3770
	}		
3771
	return $protocols_new;
3772
}
3773

    
3774
function get_l7_unique_list() {
3775
	global $layer7_rules_list;
3776
	
3777
	$l7list = array();
3778
	if(is_array($layer7_rules_list)) 
3779
		foreach($layer7_rules_list as $l7c)
3780
			if($l7c->GetREnabled())
3781
				$l7list[] = $l7c->GetRName();
3782
	
3783
	return $l7list;
3784
}
3785

    
3786
// Disable a removed l7 container from the filter
3787
function cleanup_l7_from_rules(&$name) {
3788
	global $config;
3789

    
3790
	if(is_array($config['filter']['rule']))
3791
		foreach ($config['filter']['rule'] as $key => $rule) {
3792
			if ($rule['l7container'] == $name)
3793
				unset($config['filter']['rule'][$key]['l7container']);
3794
		}
3795
}
3796

    
3797
function get_dummynet_name_list() {
3798
	
3799
	$dn_name_list =& get_unique_dnqueue_list();
3800
	$dn_name = array();
3801
	if(is_array($dn_name_list))
3802
		foreach($dn_name_list as $key => $value)
3803
			$dn_name[] = $key;
3804
	
3805
	return $dn_name;
3806
	
3807
}
3808

    
3809
function get_altq_name_list() {
3810
	$altq_name_list =& get_unique_queue_list();
3811
	$altq_name = array();
3812
	if(is_array($altq_name_list))
3813
		foreach($altq_name_list as $key => $aqobj)
3814
			$altq_name[] = $key;
3815
		
3816
	return $altq_name;
3817
}
3818

    
3819
/*
3820
 * XXX: TODO Make a class shaper to hide all these function
3821
 * from the global namespace.
3822
 */
3823

    
3824
/* 
3825
 * This is a layer violation but for now there is no way 
3826
 * i can find to properly do this with PHP.
3827
 */
3828
function altq_get_default_queue($interface) {
3829
	global $altq_list_queues;
3830

    
3831
	$altq_tmp = $altq_list_queues[$interface];
3832
	if ($altq_tmp)
3833
		return $altq_tmp->GetDefaultQueuePresent(); 
3834
	else
3835
		return false;
3836
}
3837

    
3838
function altq_check_default_queues() {
3839
	global $altq_list_queues;
3840

    
3841
	$count = 0;
3842
	if (is_array($altq_list_queues)) {
3843
		foreach($altq_list_queues as $altq) {
3844
			if ($altq->GetDefaultQueuePresent())
3845
				$count++;
3846
		}
3847
	}
3848
	else  $count++;;
3849
	
3850
	return 0;
3851
}
3852

    
3853
function &get_unique_queue_list() {
3854
	global $altq_list_queues;
3855
	
3856
	$qlist = array();
3857
	if (is_array($altq_list_queues)) {
3858
		foreach ($altq_list_queues as $altq) {
3859
			if ($altq->GetEnabled() == "")
3860
				continue;
3861
			$tmplist =& $altq->get_queue_list();
3862
			foreach ($tmplist as $qname => $link) {
3863
				if ($link->GetEnabled() <> "")
3864
					$qlist[$qname] = $link;	
3865
			}
3866
		}
3867
	}
3868
	return $qlist;
3869
}
3870

    
3871
function &get_unique_dnqueue_list() {
3872
	global $dummynet_pipe_list;
3873
	
3874
	$qlist = array();
3875
	if (is_array($dummynet_pipe_list)) {
3876
		foreach ($dummynet_pipe_list as $dn) {
3877
			if ($dn->GetEnabled() == "")
3878
				continue;
3879
			$tmplist =& $dn->get_queue_list();
3880
			foreach ($tmplist as $qname => $link) {
3881
				$qlist[$qname] = $link;	
3882
			}
3883
		}
3884
	}
3885
	return $qlist;
3886
}
3887

    
3888
function ref_on_altq_queue_list($parent, $qname) {
3889
	if (isset($GLOBALS['queue_list'][$qname]))
3890
		$GLOBALS['queue_list'][$qname]++;
3891
	else
3892
		$GLOBALS['queue_list'][$qname] = 1;
3893

    
3894
	unref_on_altq_queue_list($parent);
3895
}
3896

    
3897
function unref_on_altq_queue_list($qname) {
3898
	$GLOBALS['queue_list'][$qname]--;
3899
	if ($GLOBALS['queue_list'][$qname] <= 1)
3900
		unset($GLOBALS['queue_list'][$qname]);	
3901
}
3902

    
3903
function read_altq_config() {
3904
	global $altq_list_queues, $config;
3905
	$path = array();
3906
	
3907
	if (!is_array($config['shaper']))
3908
		$config['shaper'] = array();
3909
	if (!is_array($config['shaper']['queue']))
3910
		$config['shaper']['queue'] = array();
3911
	$a_int = &$config['shaper']['queue'];
3912

    
3913
	$altq_list_queues = array();
3914
	
3915
	if (!is_array($config['shaper']['queue']))
3916
		return;
3917

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

    
3941
function read_dummynet_config() {
3942
	global $dummynet_pipe_list, $config;
3943
	$path = array();
3944
	$dnqueuenumber = 1;
3945
	$dnpipenumber = 1;
3946

    
3947
	if (!is_array($config['dnshaper']))
3948
		$config['dnshaper'] = array();
3949
	if (!is_array($config['dnshaper']['queue']))
3950
		$config['dnshaper']['queue'] = array();
3951
	$a_int = &$config['dnshaper']['queue'];
3952

    
3953
	$dummynet_pipe_list = array();
3954
	
3955
	if (!is_array($config['dnshaper']['queue'])
3956
		|| !count($config['dnshaper']['queue']))
3957
		return;
3958

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

    
3980
				$dnqueuenumber++;
3981
			} 	
3982
		}
3983
		array_pop($path);
3984
			
3985
		$dnpipenumber++;
3986
	}
3987
}
3988

    
3989
function get_interface_list_to_show() {
3990
	global $altq_list_queues, $config;
3991
	global $shaperIFlist;
3992

    
3993
	$tree = "";
3994
	foreach ($shaperIFlist as $shif => $shDescr) {
3995
		if ($altq_list_queues[$shif]) {
3996
			continue;
3997
		} else  {
3998
			if (!is_altq_capable(get_real_interface($shif)))
3999
				continue;
4000
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
4001
		}
4002
	}
4003
	
4004
	return $tree;
4005
}
4006

    
4007
function filter_generate_altq_queues() {
4008
	global $altq_list_queues;
4009
	
4010
	read_altq_config();
4011

    
4012
	$altq_rules = "";
4013
	foreach ($altq_list_queues as $altq) 
4014
		$altq_rules .= $altq->build_rules();
4015

    
4016
	return $altq_rules;
4017
}
4018

    
4019
function filter_generate_dummynet_rules() {
4020
	global $g, $dummynet_pipe_list;
4021
	
4022
	read_dummynet_config();
4023
	
4024
	if (!empty($dummynet_pipe_list)) {
4025
		if (!is_module_loaded("dummynet.ko"))
4026
			mwexec("/sbin/kldload dummynet");
4027
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
4028
		//mwexec("pfctl -F dummynet");
4029
	}
4030

    
4031
	$dn_rules = "";
4032
	foreach ($dummynet_pipe_list as $dn) 
4033
		$dn_rules .= $dn->build_rules();
4034

    
4035
	if (!empty($dn_rules)) {
4036
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
4037
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
4038
	}
4039
	//return $dn_rules;
4040
}
4041

    
4042
function build_iface_without_this_queue($iface, $qname) {
4043
	global $g, $altq_list_queues;
4044
	global $shaperIFlist;
4045

    
4046
	$altq =& $altq_list_queues[$iface];
4047
	if ($altq)
4048
		$scheduler = ": " . $altq->GetScheduler();
4049
	$form = "<tr><td width=\"20%\" >";
4050
	$form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&queue=" . $iface."&action=show\">". $shaperIFlist[$iface] . $scheduler."</a>";
4051
	$form .= "</td></tr>";
4052
	$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
4053
	$form .= "<a href=\"firewall_shaper_queues.php?interface=";
4054
	$form .= $iface . "&queue=". $qname . "&action=add\">";
4055
	$form .= "<img src=\"";
4056
	$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
4057
	$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
4058
	$form .= " Clone shaper/queue on this interface</a></td></tr>";
4059

    
4060
	return $form;
4061

    
4062
}
4063

    
4064

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

    
4072
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
4073
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
4074
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
4075
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
4076
$dn_default_shaper_msg .= " </p></strong></span>";
4077
$dn_default_shaper_msg .= "</td></tr>";
4078

    
4079
?>
(45-45/61)