Project

General

Profile

Download (125 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

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

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

    
47
	return $ptr;
48
}
49

    
50
function unset_object_by_reference(&$mypath) 
51
{
52
	global $config;
53

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

    
61
function &get_dn_reference_to_me_in_config(&$mypath) 
62
{
63
	global $config;
64

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

    
70
	return $ptr;
71
}
72

    
73
function unset_dn_object_by_reference(&$mypath) 
74
{
75
	global $config;
76

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

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

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

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

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

    
163
function get_interface_bandwidth($object) 
164
{
165
	global $altq_list_queues;
166

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

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

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

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

    
198
function cleanup_queue_from_rules($queue) 
199
{
200
	global $config;
201

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

    
210
function cleanup_dnqueue_from_rules($queue) 
211
{
212
	global $config;
213

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

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

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

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

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

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

    
376
	function &get_queue_list($q = null) {
377
		$qlist = array();
378

    
379
		$qlist[$this->GetQname()] = & $this;
380
		if (is_array($this->queues)) {
381
			foreach ($this->queues as $queue)
382
				$queue->get_queue_list(&$qlist);
383
		}
384
		return $qlist;
385
	}
386

    
387
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
388

    
389
		if (!is_array($this->queues))
390
			$this->queues = array();
391

    
392
		switch ($this->GetScheduler()) {
393
		case "PRIQ":
394
			$q =& new priq_queue();
395
			break;
396
		case "HFSC":
397
			$q =& new hfsc_queue();
398
			break;
399
		case "CBQ":
400
			$q =& new cbq_queue();
401
			break;
402
		case "FAIRQ":
403
			$q =& new fairq_queue();
404
			break;
405
		default:
406
			/* XXX: but should not happen anyway */ 
407
			return;
408
			break;
409
		}
410
		$q->SetLink($path);
411
		$q->SetInterface($this->GetInterface());
412
		$q->SetEnabled("on");
413
		$q->SetParent(&$this);
414
		$q->ReadConfig($queue);
415
		$q->validate_input($queue, $input_errors);
416
		if (count($input_errors)) {
417
			return $q;
418
		}
419

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

    
442
		return $q;
443
	}
444

    
445
	/* interface here might be optional */
446
	function &find_queue($interface, $qname) {
447
		if ($qname == $this->GetQname()) {
448
			return $this;
449
		} 
450
		foreach ($this->queues as $q) {
451
			$result =& $q->find_queue("", $qname);
452
			if ($result)
453
				return $result;
454
		}
455
	}
456

    
457
	function &find_parentqueue($interface, $qname) {
458
		if ($qname == $interface) {
459
			$result =  NULL;
460
		} else if ($this->queues[$qname])	 {
461
			$result = $this;
462
		} else if ($this->GetScheduler() <> "PRIQ") {
463
			foreach ($this->queues as $q) {
464
				$result = $q->find_parentqueue("", $qname);
465
				if ($result)
466
					return $result;
467
			}
468
		}
469
	}
470

    
471
	function build_tree() {
472
		global $shaperIFlist;
473

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

    
495
	function delete_all() {
496
                if (count($this->queues)) {
497
                        foreach ($this->queues as $q) {
498
                        	$q->delete_all();
499
                        	unset_object_by_reference($q->GetLink());
500
                                unset($q);
501
               		}
502
        	        unset($this->queues);
503
                }
504
        }
505

    
506
	/*
507
	 * First it spits:
508
	 * altq on $interface ..............
509
	 *      then it goes like
510
	 *      foreach ($queues as $qkey => $queue)
511
	 *              this->queues[$qkey]->build_rule();
512
	 */
513
	function build_rules() {
514
		if (count($this->queues) > 0 && $this->GetEnabled() == "on") {
515
			$rules = " altq on  " . get_real_interface($this->GetInterface());
516
			if ($this->GetScheduler())
517
				$rules .= " ".strtolower($this->GetScheduler());
518
			if ($this->GetBandwidth()) {
519
				$rules .= " bandwidth ".trim($this->GetBandwidth());
520
				if ($this->GetBwscale())
521
					$rules .= $this->GetBwscale();
522
			}
523
			if ($this->GetTbrConfig())
524
				$rules .= " tbrsize ".$this->GetTbrConfig();
525
			if (count($this->queues)) {
526
				$i = count($this->queues);
527
				$rules .= " queue { ";
528
				foreach ($this->queues as $qkey => $qnone) {
529
					if ($i > 1) {
530
						$i--;
531
						$rules .= " {$qkey}, ";
532
					} else
533
						$rules .= " {$qkey} ";
534
				}
535
				$rules .= " } \n";
536
				foreach ($this->queues as $q) {
537
					$rules .= $q->build_rules();
538
				}
539
			}
540
		}
541
		$rules .= " \n";
542
		return $rules;
543
	}
544

    
545
	function build_javascript() {
546
		$javascript = "<script type=\"text/javascript\">";
547
		$javascript .= "function mySuspend() {";
548
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);";
549
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';";
550
		$javascript .= "else if (document.all)";
551
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';";
552
		$javascript .= "}";
553

    
554
		$javascript .= "function myResume() {";
555
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)";
556
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';";
557
		$javascript .= "else if (document.all)";
558
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';";
559
		$javascript .= "}";
560
		$javascript .= "</script>";
561

    
562
		return $javascript;
563
	}
564
	
565
	function build_shortform() {
566
		global $g;
567

    
568
		$altq =& $this;
569
		if ($altq)
570
			$scheduler = ": " . $altq->GetScheduler();
571
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
572
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=". $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
573
		$form .= "</td></tr>";
574
		$form .= "<tr>";
575
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
576
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
577
		$form .= "</td><td width=\"50%\"></td></tr>";
578
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
579
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
580
		$form .= $this->GetInterface() . "&queue=";
581
		$form .= $this->GetQname() . "&action=delete\">";
582
		$form .= "<img src=\"";
583
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
584
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Disable shaper on interface\">";
585
		$form .= "<span>Disable shaper on interface</span></a></td></tr>";
586

    
587
		return $form;
588

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

    
676

    
677
		return $form;
678
	}
679

    
680
	function update_altq_queue_data(&$data) { 
681
		$this->ReadConfig($data);
682
	}
683
	
684
	/*
685
	 * Should call on each of it queues and subqueues
686
	 * the same function much like build_rules();
687
	 */
688
	function wconfig() { 
689
		$cflink = &get_reference_to_me_in_config($this->GetLink());
690
		if (!is_array($cflink))
691
			$cflink = array();
692
		$cflink['interface'] = $this->GetInterface();	
693
		$cflink['name'] = $this->GetQname();
694
		$cflink['scheduler'] = $this->GetScheduler();
695
		$cflink['bandwidth'] = $this->GetBandwidth();
696
		$cflink['bandwidthtype'] = $this->GetBwscale();
697
		$cflink['qlimit'] = trim($this->GetQlimit());
698
		if (empty($cflink['qlimit']))
699
			unset($cflink['qlimit']);
700
		$cflink['tbrconfig'] = trim($this->GetTbrConfig());
701
		if (empty($cflink['tbrconfig']))
702
			unset($cflink['tbrconfig']);
703
		$cflink['enabled'] = $this->GetEnabled();
704
		if (empty($cflink['enabled']))
705
			unset($cflink['enabled']);
706
	}
707

    
708
}
709

    
710
class priq_queue {
711
	var $qname;
712
	var $qinterface; 
713
	var $qlimit;
714
	var $qpriority;
715
	var $description;
716
	var $isparent;
717
	var $qbandwidth;
718
	var $qbandwidthtype;
719
	var $qdefault = "";
720
	var $qrio = "";
721
	var $qred = "";
722
	var $qecn = "";
723
	var $qack;
724
	var $qenabled = "";
725
	var $qparent;
726
	var $link;
727
	var $available_bw; /* in b/s */
728

    
729
	/* This is here to help with form building and building rules/lists */
730
		var $subqueues = array();
731

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

    
843
	function build_javascript() {
844
		$javascript = "<script type=\"text/javascript\">";
845
		$javascript .= "function mySuspend() { \n";
846
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);\n";
847
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
848
		$javascript .= "else if (document.all)\n";
849
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
850
		$javascript .= "}\n";
851

    
852
		$javascript .= "function myResume() {\n";
853
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
854
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
855
		$javascript .= "else if (document.all)\n";
856
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
857
		$javascript .= "}\n";
858
		$javascript .= "</script>";
859
		
860
		return $javascript;
861
	}
862
	
863
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
864

    
865
	/* 
866
	 * Currently this will not be called unless we decide to clone a whole 
867
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
868
	 */
869
	 function copy_queue($interface, &$cflink) {
870

    
871
 		$cflink['name'] = $this->GetQname();
872
                $cflink['interface'] = $interface;
873
                $cflink['qlimit'] = $this->GetQlimit();
874
                $cflink['priority'] = $this->GetQpriority();
875
                $cflink['description'] = $this->GetDescription();
876
                $cflink['enabled'] = $this->GetEnabled();
877
                $cflink['default'] = $this->GetDefault();
878
                $cflink['red'] = $this->GetRed();
879
                $cflink['rio'] = $this->GetRio();
880
                $cflink['ecn'] = $this->GetEcn();
881

    
882
                if (is_array($this->subqueues)) {
883
                        $cflinkp['queue'] = array();
884
                        foreach ($this->subqueues as $q) {
885
				 $cflink['queue'][$q->GetQname()] = array();
886
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
887
			}
888
                }
889

    
890
	 }
891

    
892
	function clean_queue($sched) {
893
		clean_child_queues($sched, $this->GetLink());
894
		if (is_array($this->subqueues)) {
895
			foreach ($this->subqueues as $q)
896
				$q->clean_queue($sched);
897
		}
898
	}
899

    
900
        function &get_queue_list(&$qlist) {
901
		$qlist[$this->GetQname()] = & $this;
902
		if (is_array($this->subqueues)) {
903
			foreach ($this->subqueues as $queue)
904
				$queue->get_queue_list($qlist);
905
		}
906
	}
907

    
908
	function delete_queue() {
909
		unref_on_altq_queue_list($this->GetQname());
910
		if ($this->GetDefault())
911
				altq_set_default_queue($this->GetInterface(), "false");
912
		cleanup_queue_from_rules($this->GetQname());
913
		unset_object_by_reference($this->GetLink());
914
	}
915
	
916
	function delete_all() {
917
                if (count($this->subqueues)) {
918
                        foreach ($this->subqueues as $q) {
919
                                $q->delete_all();
920
                                unset_object_by_reference($q->GetLink());
921
                                unset($q);
922
                        }
923
                        unset($this->subqueues);
924
                }
925
        }
926

    
927
	 function &find_queue($interface, $qname) { 
928
		if ($qname == $this->GetQname())
929
			return $this; 
930
	}
931
	
932
	function find_parentqueue($interface, $qname) { return; }
933
		
934
	function validate_input($data, &$input_errors) {
935
	
936
		$reqdfields[] = "name";
937
		$reqdfieldsn[] = "Name";
938
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
939

    
940
		if ($data['priority'] && (!is_numeric($data['priority'])
941
						|| ($data['priority'] < 1) || ($data['priority'] > 15))) {
942
					$input_errors[] = "The priority must be an integer between 1 and 15.";
943
		}
944
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
945
				$input_errors[] = "Queue limit must be an integer";
946
		if ($data['qlimit'] < 0)
947
				$input_errors[] = "Queue limit must be positive";
948
		if (!preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
949
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
950
		
951
	}
952

    
953
	function ReadConfig(&$q) {
954
		if (isset($q['name']))
955
				$this->SetQname($q['name']);
956
		if (isset($q['interface']))
957
				$this->SetInterface($q['interface']);
958
		$this->SetBandwidth($q['bandwidth']);
959
		if ($q['bandwidthtype'] <> "")
960
			$this->SetBwscale($q['bandwidthtype']);
961
		if (!empty($q['qlimit']))
962
			$this->SetQlimit($q['qlimit']);
963
		else
964
			$this->SetQlimit(""); // Default
965
		if (!empty($q['priority']))
966
			$this->SetQPriority($q['priority']);
967
		else
968
			$this->SetQpriority("");
969
		if (!empty($q['description']))
970
			$this->SetDescription($q['description']);
971
		else
972
			$this->SetDescription("");
973
		if (!empty($q['red']))
974
			$this->SetRed($q['red']);
975
		else
976
			$this->SetRed();
977
		if (!empty($q['rio']))
978
			$this->SetRio($q['rio']);
979
		else
980
			$this->SetRio();
981
		if (!empty($q['ecn']))
982
			$this->SetEcn($q['ecn']);
983
		else
984
			$this->SetEcn();
985
		if (!empty($q['default']))
986
			$this->SetDefault($q['default']);
987
		else
988
			$this->SetDefault();
989
		if (!empty($q['enabled']))
990
			$this->SetEnabled($q['enabled']);
991
		else
992
			$this->SetEnabled("");
993

    
994
	}
995

    
996
	function build_tree() {
997
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
998
		$tree .= "\" ";
999
		$tmpvalue = $this->GetDefault();
1000
		if (!empty($tmpvalue))
1001
			$tree .= " class=\"navlnk\"";
1002
		$tree .= " >" . $this->GetQname() . "</a>";
1003
		/* 
1004
		 * Not needed here!
1005
		 * if (is_array($queues) {
1006
		 *	  $tree .= "<ul>";
1007
		 *	  foreach ($q as $queues) 
1008
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1009
		 *	  endforeach	
1010
		 *	  $tree .= "</ul>";
1011
		 * }
1012
		 */
1013

    
1014
		$tree .= "</li>"; 
1015

    
1016
		return $tree;
1017
	}
1018
		
1019
	/* Should return something like:
1020
	 * queue $qname on $qinterface bandwidth ....
1021
	 */
1022
	function build_rules() {
1023
		$pfq_rule = " queue ". $this->qname;
1024
		if ($this->GetInterface())
1025
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1026
		$tmpvalue = $this->GetQpriority();
1027
		if (!empty($tmpvalue))
1028
			$pfq_rule .= " priority ".$this->GetQpriority();
1029
		$tmpvalue = $this->GetQlimit();
1030
		if (!empty($tmpvalue))
1031
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1032
		if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
1033
			$pfq_rule .= " priq ( ";
1034
			$tmpvalue = $this->GetRed();
1035
			if (!empty($tmpvalue)) {
1036
				$comma = 1;
1037
				$pfq_rule .= " red ";
1038
			}
1039
			$tmpvalue = $this->GetRio();
1040
			if (!empty($tmpvalue)) {
1041
				if ($comma) 
1042
					$pfq_rule .= " ,";
1043
				$comma = 1;
1044
				$pfq_rule .= " rio ";
1045
			}
1046
			$tmpvalue = $this->GetEcn();
1047
			if (!empty($tmpvalue)) {
1048
				if ($comma) 
1049
					$pfq_rule .= " ,";
1050
				$comma = 1;
1051
				$pfq_rule .= " ecn ";
1052
			}
1053
			$tmpvalue = $this->GetDefault();
1054
			if (!empty($tmpvalue)) {
1055
				if ($comma)
1056
					$pfq_rule .= " ,";
1057
				$pfq_rule .= " default ";
1058
			}
1059
			$pfq_rule .= " ) ";
1060
		}
1061

    
1062
		$pfq_rule .= " \n";
1063

    
1064
		return $pfq_rule;
1065
	}
1066

    
1067
	/*
1068
	 * To return the html form to show to user
1069
	 * for getting the parameters.
1070
	 * Should do even for first time when the
1071
	 * object is created and later when we may
1072
	 * need to update it.
1073
	 */
1074
	function build_form() {
1075
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
1076
                $form .= "Enable/Disable";
1077
                $form .= "<br/></td><td class=\"vncellreq\">";
1078
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
1079
                if ($this->GetEnabled() == "on")
1080
                        $form .=  " CHECKED";
1081
                $form .= " ><span class=\"vexpl\"> Enable/Disable queue and its children</span>";
1082
                $form .= "</td></tr>";
1083
		$form .= "<tr>";
1084
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">";
1085
		$form .= "Queue Name</td><td width=\"78%\" class=\"vtable\">";
1086
		$form .= "<input name=\"name\" type=\"text\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1087
		$form .= htmlspecialchars($this->GetQname());
1088
		$form .= "\">";
1089
		$form .= "<br /> <span class=\"vexpl\">Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.";
1090
		$form .= "</span><br /></td>";
1091
		$form .= "</tr><tr>";
1092
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Priority</td>";
1093
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
1094
		$form .= htmlspecialchars($this->GetQpriority());
1095
		$form .= "\">";
1096
		$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>";
1097
		$form .= "</tr>";
1098
		$form .= "<tr>";
1099
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Queue limit</td>";
1100
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"8\" value=\"";
1101
		$form .= htmlspecialchars($this->GetQlimit());
1102
		$form .= "\">";
1103
		$form .= "<br> <span class=\"vexpl\">Queue limit in packets per second."; 
1104
		$form .= "</span></td>";
1105
		$form .= "<tr>";
1106
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncell\">Scheduler options</td>";
1107
		$form .= "<td width=\"78%\" class=\"vtable\">";
1108
		$tmpvalue = $this->GetDefault();	
1109
		if (!empty($tmpvalue)) { 
1110
			$form .= "<input type=\"checkbox\" id=\"default\" CHECKED name=\"default\" value=\"default\"";
1111
			$form .= "> Default queue<br>";
1112
		} else {
1113
			$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\" value=\"default\"";
1114
			$form .= "> Default queue<br>";
1115
		}
1116
		$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\" value=\"red\" ";
1117
		$tmpvalue = $this->GetRed();
1118
		if(!empty($tmpvalue)) 
1119
			$form .=  " CHECKED";
1120
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">Random Early Detection</a><br>";
1121
		$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\" value=\"rio\"";
1122
		$tmpvalue = $this->GetRio();
1123
		if(!empty($tmpvalue)) 
1124
			$form .=  " CHECKED";
1125
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">Random Early Detection In and Out</a><br>";
1126
		$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\" value=\"ecn\"";
1127
		$tmpvalue = $this->GetEcn();
1128
		if(!empty($tmpvalue)) 
1129
			$form .=  " CHECKED";
1130
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">Explicit Congestion Notification</a><br>";
1131
		$form .= "<span class=\"vexpl\"><br>Select options for this queue";
1132
		$form .= "</tr><tr>";
1133
		$form .= "<td width=\"22%\" class=\"vncellreq\">Description</td>";
1134
		$form .= "<td width=\"78%\" class=\"vtable\">";
1135
		$form .= "<input type=\"text\" name=\"description\" size=\"50%\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\"  >";
1136
		$form .= "</td></tr>";
1137
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1138
		$form .= " value=\"".$this->GetInterface()."\">";
1139

    
1140
		return $form;
1141
	}
1142

    
1143
	function build_shortform() {
1144
		/* XXX: Hacks in site. Mostly layer violations!  */
1145
		global $g, $altq_list_queues;
1146

    
1147
		$altq =& $altq_list_queues[$this->GetInterface()];
1148
		if ($altq)
1149
			$scheduler = ": " . $altq->GetScheduler();
1150
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
1151
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=" . $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
1152
		$form .= "</td></tr>";
1153
		/* 
1154
		 * XXX: Hack in sight maybe fix with a class that wraps all
1155
		 * of this layer violations
1156
		 */
1157
		$form .= "<tr>";
1158
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1159
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
1160
		$form .= "</td><td width=\"50%\"></td></tr>";
1161
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1162
		$tmpvalue = $this->GetQpriority();
1163
		if (!empty($tmpvalue))
1164
			$form .= "Priority: on </td></tr>";
1165
		$tmpvalue = $this->GetDefault();
1166
		if (!empty($tmpvalue))
1167
			$form .= "<tr><td class=\"vncellreq\">Default: on </td></tr>";
1168
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1169
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1170
		$form .= $this->GetInterface() . "&queue=";
1171
		$form .= $this->GetQname() . "&action=delete\">";
1172
		$form .= "<img src=\"";
1173
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1174
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Delete queue from interface\">";
1175
		$form .= "<span>Delete queue from interface</span></a></td></tr>";
1176
		
1177
		return $form;
1178

    
1179
	}
1180

    
1181
		function update_altq_queue_data(&$q) { 
1182
		$this->ReadConfig($q);
1183
	}
1184

    
1185
	function wconfig() {
1186
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1187
		if (!is_array($cflink))
1188
			$cflink = array();
1189
		$cflink['name'] = $this->GetQname();
1190
		$cflink['interface'] = $this->GetInterface();
1191
		$cflink['qlimit'] = trim($this->GetQlimit());
1192
		if (empty($cflink['qlimit']))
1193
			unset($cflink['qlimit']);
1194
		$cflink['priority'] = trim($this->GetQpriority());
1195
		if (empty($cflink['priority']))
1196
			unset($cflink['priority']);
1197
		$cflink['description'] = trim($this->GetDescription());
1198
		if (empty($cflink['description']))
1199
			unset($cflink['description']);
1200
		$cflink['enabled'] = trim($this->GetEnabled());
1201
		if (empty($cflink['enabled']))
1202
			unset($cflink['enabled']);
1203
		$cflink['default'] = trim($this->GetDefault());
1204
		if (empty($cflink['default']))
1205
			unset($cflink['default']);
1206
		$cflink['red'] = trim($this->GetRed());
1207
		if (empty($cflink['red']))
1208
			unset($cflink['red']);
1209
		$cflink['rio'] = trim($this->GetRio());
1210
		if (empty($cflink['rio']))
1211
			unset($cflink['rio']);
1212
		$cflink['ecn'] = trim($this->GetEcn());
1213
		if (empty($cflink['ecn']))
1214
			unset($cflink['ecn']);
1215
	}
1216
}
1217

    
1218
class hfsc_queue extends priq_queue {
1219
	/* realtime */
1220
	var $realtime;
1221
	var $r_m1;
1222
	var $r_d;
1223
	var $r_m2;
1224
	/* linkshare */
1225
	var $linkshare;
1226
	var $l_m1;
1227
	var $l_d;
1228
	var $l_m2;
1229
	/* upperlimit */
1230
	var $upperlimit;
1231
	var $u_m1;
1232
	var $u_d;
1233
	var $u_m2;
1234

    
1235
	/*
1236
	 * HFSC can have nested queues.
1237
	 */
1238

    
1239
	function CanHaveChildren() {
1240
		return true;
1241
	}
1242
	function GetRealtime() {
1243
           return $this->realtime;
1244
	}
1245
	function GetR_m1() {
1246
		return $this->r_m1;
1247
	}
1248
	function GetR_d() {
1249
		return $this->r_d;
1250
	}
1251
	function GetR_m2() {
1252
		return $this->r_m2;
1253
	}
1254
	function SetRealtime() {
1255
		$this->realtime = "on";
1256
	}
1257
	function DisableRealtime() {
1258
		$this->realtime = "";
1259
	}
1260
	function SetR_m1($value) {
1261
		$this->r_m1 = $value;
1262
	}
1263
	function SetR_d($value) {
1264
		$this->r_d = $value;
1265
	}
1266
	function SetR_m2($value) {
1267
		$this->r_m2 = $value;
1268
	}
1269
	function GetLinkshare() {
1270
		return $this->linkshare;
1271
	}
1272
	function DisableLinkshare() {
1273
		$this->linkshare = "";
1274
	}
1275
	function GetL_m1() {
1276
		return $this->l_m1;
1277
	}
1278
	function GetL_d() {
1279
		return $this->l_d;
1280
	}
1281
	function GetL_m2() {
1282
		return $this->l_m2;
1283
	}
1284
	function SetLinkshare() {
1285
		$this->linkshare = "on";
1286
	}
1287
	function SetL_m1($value) {
1288
		$this->l_m1 = $value;
1289
	}
1290
	function SetL_d($value) {
1291
		$this->l_d = $value;
1292
	}
1293
	function SetL_m2($value) {
1294
		$this->l_m2 = $value;
1295
	}
1296
	function GetUpperlimit() {
1297
		return $this->upperlimit;
1298
	}
1299
	function GetU_m1() {
1300
		return $this->u_m1;
1301
	}
1302
	function GetU_d() {
1303
		return $this->u_d;
1304
	}
1305
	function GetU_m2() {
1306
		return $this->u_m2;
1307
	}
1308
	function SetUpperlimit() {
1309
		$this->upperlimit = "on";
1310
	}
1311
	function DisableUpperlimit() {
1312
		$this->upperlimit = "";
1313
	}
1314
	function SetU_m1($value) {
1315
		$this->u_m1 = $value;
1316
	}
1317
	function SetU_d($value) {
1318
		$this->u_d = $value;
1319
	}
1320
	function SetU_m2($value) {
1321
		$this->u_m2 = $value;
1322
	}
1323

    
1324
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1325

    
1326
		if (!is_array($this->subqueues))
1327
			$this->subqueues = array();
1328
		$q =& new hfsc_queue();
1329
		$q->SetInterface($this->GetInterface());
1330
		$q->SetParent(&$this);
1331
		$q->ReadConfig($qname);
1332
		$q->validate_input($qname, $input_errors);
1333
		if (count($input_errors)) {
1334
			return $q;
1335
		}
1336

    
1337
		$q->SetEnabled("on");
1338
		$q->SetLink($path);
1339
		switch ($q->GetBwscale()) {
1340
		case "%":
1341
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1342
			break;
1343
		default:
1344
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1345
			break;
1346
		}
1347
		$q->SetAvailableBandwidth($myBw);
1348
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1349

    
1350
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1351
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1352
		if (is_array($qname['queue'])) {
1353
			foreach ($qname['queue'] as $key1 => $que) {
1354
				array_push($path, $key1);
1355
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1356
				array_pop($path);
1357
			}
1358
		}
1359
	
1360
		return $q;
1361
	}
1362

    
1363
        function copy_queue($interface, &$cflink) {
1364

    
1365
		$cflink['name'] = $this->GetQname();
1366
		$cflink['interface'] = $interface;
1367
		$cflink['qlimit'] = trim($this->GetQlimit());
1368
		if (empty($cflink['qlimit']))
1369
			unset($cflink['qlimit']);
1370
		$cflink['priority'] = trim($this->GetQpriority());
1371
		if (empty($cflink['priority']))
1372
			unset($cflink['priority']);
1373
		$cflink['description'] = trim($this->GetDescription());
1374
		if (empty($cflink['description']))
1375
			unset($cflink['description']);
1376
		$cflink['bandwidth'] = $this->GetBandwidth();
1377
		$cflink['bandwidthtype'] = $this->GetBwscale();
1378
		$cflink['enabled'] = trim($this->GetEnabled());
1379
		if (empty($cflink['enabled']))
1380
			unset($cflink['enabled']);
1381
		$cflink['default'] = trim($this->GetDefault());
1382
		if (empty($cflink['default']))
1383
			unset($cflink['default']);
1384
		$cflink['red'] = trim($this->GetRed());
1385
		if (empty($cflink['red']))
1386
			unset($cflink['red']);
1387
		$cflink['rio'] = trim($this->GetRio());
1388
		if (empty($cflink['rio']))
1389
			unset($cflink['rio']);
1390
		$cflink['ecn'] = trim($this->GetEcn());
1391
		if (empty($cflink['ecn']))
1392
			unset($cflink['ecn']);
1393
		if ($this->GetLinkshare() <> "") {
1394
			if ($this->GetL_m1() <> "") {
1395
				$cflink['linkshare1'] = $this->GetL_m1();
1396
				$cflink['linkshare2'] = $this->GetL_d();
1397
				$cflink['linkshare'] = "on";
1398
			} else {
1399
				unset($cflink['linkshare1']);
1400
				unset($cflink['linkshare2']);
1401
				unset($cflink['linkshare']);
1402
			}
1403
			if ($this->GetL_m2() <> "") {
1404
				$cflink['linkshare3'] = $this->GetL_m2();
1405
				$cflink['linkshare'] = "on";
1406
			} else {
1407
				unset($cflink['linkshare3']);
1408
				unset($cflink['linkshare']);
1409
			}
1410
		}
1411
		if ($this->GetRealtime() <> "") {
1412
			if ($this->GetR_m1() <> "") {
1413
				$cflink['realtime1'] = $this->GetR_m1();
1414
				$cflink['realtime2'] = $this->GetR_d();
1415
				$cflink['realtime'] = "on";
1416
			} else {
1417
				unset($cflink['realtime1']);
1418
                                unset($cflink['realtime2']);
1419
                                unset($cflink['realtime']);
1420
			}
1421
			if ($this->GetR_m2() <> "") {
1422
				$cflink['realtime3'] = $this->GetR_m2();
1423
				$cflink['realtime'] = "on";
1424
			} else {
1425
				unset($cflink['realtime3']);
1426
				unset($cflink['realtime']);
1427
			}
1428
		}
1429
		if ($this->GetUpperlimit() <> "") {
1430
			if ($this->GetU_m1() <> "") {
1431
				$cflink['upperlimit1'] = $this->GetU_m1();
1432
				$cflink['upperlimit2'] = $this->GetU_d();
1433
				$cflink['upperlimit'] = "on";
1434
			} else {
1435
				unset($cflink['upperlimit']);
1436
				unset($cflink['upperlimit1']);
1437
				unset($cflink['upperlimit2']);
1438
			}
1439
			if ($this->GetU_m2() <> "") {
1440
				$cflink['upperlimit3'] = $this->GetU_m2();
1441
				$cflink['upperlimit'] = "on";
1442
			} else {
1443
				unset($cflink['upperlimit3']);
1444
				unset($cflink['upperlimit']);
1445
			}
1446
		}
1447

    
1448
		if (is_array($this->subqueues)) {
1449
			$cflinkp['queue'] = array();
1450
			foreach ($this->subqueues as $q) {
1451
				$cflink['queue'][$q->GetQname()] = array();
1452
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1453
			}
1454
		}
1455
	}
1456

    
1457
	function delete_queue() { 
1458
		unref_on_altq_queue_list($this->GetQname());
1459
		$tmpvalue = $this->GetDefault();
1460
		if (!empty($tmpvalue)) 
1461
			altq_set_default_queue($this->GetInterface(), "false");
1462
		cleanup_queue_from_rules($this->GetQname());
1463
		$parent =& $this->GetParent();
1464
		foreach ($this->subqueues as $q)  {
1465
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1466
			$q->delete_queue();
1467
		}
1468
		unset_object_by_reference($this->GetLink());
1469
	}
1470

    
1471
	/*
1472
	 * Should search even its children
1473
	 */
1474
	function &find_queue($interface, $qname) {
1475
		if ($qname == $this->GetQname()) 
1476
			return $this;
1477

    
1478
		foreach ($this->subqueues as $q) {
1479
			$result =& $q->find_queue("", $qname);
1480
			if ($result)
1481
				return $result;
1482
		}
1483
	}
1484

    
1485
	function &find_parentqueue($interface, $qname) {
1486
		if ($this->subqueues[$qname]) 
1487
			return $this;
1488
		foreach ($this->subqueues as $q) {
1489
			$result = $q->find_parentqueue("", $qname);
1490
			if ($result)
1491
				return $result;
1492
		}
1493
	}
1494
	
1495
	function validate_input($data, &$input_errors) {
1496
		parent::validate_input($data, $input_errors);
1497
		
1498
		$reqdfields[] = "bandwidth";
1499
		$reqdfieldsn[] = "Bandwidth";
1500
		$reqdfields[] = "bandwidthtype";
1501
		$reqdfieldsn[] = "Bandwidthtype";
1502

    
1503
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1504
		
1505
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1506
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1507
                        	$input_errors[] = "Bandwidth must be an integer.";
1508

    
1509
                	if ($data['bandwidth'] < 0)
1510
                        	$input_errors[] = "Bandwidth cannot be negative.";
1511

    
1512
			if ($data['bandwidthtype'] == "%") {
1513
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1514
					$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1515
			}
1516
		/*
1517
			$parent =& $this->GetParent();
1518
			switch ($data['bandwidthtype']) {
1519
			case "%":
1520
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1521
			default:
1522
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1523
				break;
1524
			}
1525
			if ($parent->GetAvailableBandwidth() < $myBw)
1526
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1527
		*/
1528
		}
1529

    
1530
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1531
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1532
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1533
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1534
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1535
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1536
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1537
			$input_errors[] = ("upperlimit d value needs to be numeric");
1538
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1539
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1540

    
1541
		/*
1542
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1543
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1544
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1545
			if (floatval($bw_1) < floatval($bw_2)) 
1546
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1547

    
1548
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1549
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1550
		}
1551
		*/
1552
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1553
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1554
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1555
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1556
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1557
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1558
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1559
			$input_errors[] = ("linkshare d value needs to be numeric");
1560
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1561
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1562
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1563
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1564
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1565
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1566

    
1567
		/*
1568
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1569
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1570
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1571
                	if (floatval($bw_1) < floatval($bw_2))
1572
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1573

    
1574
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1575
                        	$input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1576
		}
1577
		*/
1578

    
1579
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1580
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1581
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1582
			$input_errors[] = ("realtime d value needs to be numeric");
1583
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1584
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1585

    
1586
		/*
1587
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1588
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1589
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1590
                	if (floatval($bw_1) < floatval($bw_2))
1591
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1592

    
1593
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1594
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1595
		}
1596
		*/
1597

    
1598
	}
1599

    
1600
	function ReadConfig(&$cflink) {
1601
		if (!empty($cflink['linkshare'])) {
1602
			if (!empty($cflink['linkshare1'])) {
1603
				$this->SetL_m1($cflink['linkshare1']);
1604
                                $this->SetL_d($cflink['linkshare2']);
1605
				$this->SetLinkshare();
1606
			}
1607
			if (!empty($cflink['linkshare3'])) {
1608
                                $this->SetL_m2($cflink['linkshare3']);
1609
				$this->SetLinkshare();
1610
			}
1611
		} else
1612
			$this->DisableLinkshare();
1613
		if (!empty($cflink['realtime'])) {
1614
                        if (!empty($cflink['realtime1'])) {
1615
                                $this->SetR_m1($cflink['realtime1']);
1616
                                $this->SetR_d($cflink['realtime2']);
1617
				$this->SetRealtime();
1618
			}
1619
                        if (!empty($cflink['realtime3'])) {
1620
                                $this->SetR_m2($cflink['realtime3']);
1621
				$this->SetRealtime();
1622
			}
1623
		} else
1624
			$this->DisableRealtime(); 
1625
		if (!empty($cflink['upperlimit'])) {
1626
                        if (!empty($cflink['upperlimit1'])) {
1627
                                $this->SetU_m1($cflink['upperlimit1']);
1628
                                $this->SetU_d($cflink['upperlimit2']);
1629
				$this->SetUpperlimit();
1630
			}
1631
                        if (!empty($cflink['upperlimit3'])) {
1632
                                $this->SetU_m2($cflink['upperlimit3']);
1633
				$this->SetUpperlimit();
1634
			}
1635
		} else
1636
			$this->DisableUpperlimit();
1637
		parent::ReadConfig($cflink);
1638
	}
1639

    
1640
	function build_tree() {
1641
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1642
		$tree .= "\" ";
1643
		$tmpvalue = $this->GetDefault();
1644
		if (!empty($tmpvalue))
1645
			$tree .= " class=\"navlnk\"";
1646
		$tree .= " >" . $this->GetQname() . "</a>";
1647
		if (is_array($this->subqueues)) {
1648
			$tree .= "<ul>";
1649
			foreach ($this->subqueues as $q)  {
1650
				$tree .= $q->build_tree();
1651
			}	
1652
			$tree .= "</ul>";
1653
		}
1654
		$tree .= "</li>";
1655
		return $tree;
1656
	}
1657

    
1658
	/* Even this should take children into consideration */
1659
	function build_rules() {
1660

    
1661
		$pfq_rule = " queue ". $this->qname;
1662
		if ($this->GetInterface())
1663
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1664
		if ($this->GetBandwidth() && $this->GetBwscale())
1665
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1666
				
1667
		$tmpvalue = $this->GetQlimit();
1668
		if (!empty($tmpvalue))
1669
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1670
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1671
			$pfq_rule .= " hfsc ( ";
1672
			$tmpvalue = $this->GetRed();
1673
			if (!empty($tmpvalue)) {
1674
				$comma = 1;
1675
				$pfq_rule .= " red ";
1676
			}
1677
			
1678
			$tmpvalue = $this->GetRio();
1679
			if (!empty($tmpvalue)) {
1680
				if ($comma) 
1681
					$pfq_rule .= " ,";
1682
				$comma = 1;
1683
				$pfq_rule .= " rio ";
1684
			}
1685
			$tmpvalue = $this->GetEcn();
1686
			if (!empty($tmpvalue)) {
1687
				if ($comma) 
1688
					$pfq_rule .= " ,";
1689
				$comma = 1;
1690
				$pfq_rule .= " ecn ";
1691
			}
1692
			$tmpvalue = $this->GetDefault();
1693
			if (!empty($tmpvalue)) {
1694
				if ($comma)
1695
					$pfq_rule .= " ,";
1696
				$comma = 1;
1697
				$pfq_rule .= " default ";
1698
			}
1699

    
1700
			if ($this->GetRealtime() <> "")  {
1701
				if ($comma) 
1702
					$pfq_rule .= " , ";
1703
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1704
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1705
				else  if ($this->GetR_m2() <> "")
1706
					$pfq_rule .= " realtime " . $this->GetR_m2();
1707
				$comma = 1;
1708
			}
1709
			if ($this->GetLinkshare() <> "") {
1710
				if ($comma)
1711
					$pfq_rule .= " ,";
1712
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1713
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1714
				else if ($this->GetL_m2() <> "")
1715
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1716
				$comma = 1;
1717
			}
1718
			if ($this->GetUpperlimit() <> "") {
1719
				if ($comma)
1720
					$pfq_rule .= " ,";
1721
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1722
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1723
				else if ($this->GetU_m2() <> "")
1724
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1725
			}
1726
			$pfq_rule .= " ) ";
1727
		}
1728
		if (count($this->subqueues)) {
1729
			$i = count($this->subqueues);
1730
			$pfq_rule .= " { ";
1731
			foreach ($this->subqueues as $qkey => $qnone) {
1732
				if ($i > 1) {
1733
					$i--;
1734
					$pfq_rule .= " {$qkey}, ";
1735
				} else
1736
					$pfq_rule .= " {$qkey} ";
1737
			}
1738
			$pfq_rule .= " } \n";
1739
			foreach ($this->subqueues as $q)
1740
				$pfq_rule .= $q->build_rules();
1741
		}
1742

    
1743
		 $pfq_rule .= " \n";
1744
			
1745
		return $pfq_rule;
1746
	}
1747

    
1748
	function build_javascript() {
1749
		$javascript = parent::build_javascript();
1750
		$javascript .= "<script type=\"text/javascript\">";
1751
		$javascript .= "function enable_realtime(enable_over) { \n";
1752
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1753
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1754
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1755
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1756
		$javascript .= " } else { \n";
1757
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1758
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1759
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1760
		$javascript .= " } \n";
1761
		$javascript .= " } \n";
1762
		$javascript .= "function enable_linkshare(enable_over) { \n";
1763
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1764
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1765
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1766
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1767
		$javascript .= " } else { \n";
1768
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1769
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1770
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1771
		$javascript .= " } \n";
1772
		$javascript .= " } \n";
1773
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1774
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1775
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1776
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1777
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1778
		$javascript .= " } else { \n";
1779
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1780
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1781
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1782
		$javascript .= " } \n";
1783
			
1784
		$javascript .= "} \n";
1785
		$javascript .= "</script>";
1786

    
1787
		return $javascript;
1788
	}
1789

    
1790
	function build_form() {
1791
		$form = parent::build_form();
1792
		$form .= "<tr>";
1793
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
1794
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1795
		$form .= htmlspecialchars($this->GetBandwidth());
1796
		$form .= "\">";
1797
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1798
		$form .= "<option value=\"Gb\"";
1799
		if ($this->GetBwscale() == "Gb")
1800
			$form .= " selected=\"yes\"";
1801
		$form .= ">Gbit/s</option>";
1802
		$form .= "<option value=\"Mb\"";
1803
		if ($this->GetBwscale() == "Mb")
1804
			$form .= " selected=\"yes\"";
1805
		$form .= ">Mbit/s</option>";
1806
		$form .= "<option value=\"Kb\"";
1807
		if ($this->GetBwscale() == "Kb")
1808
			$form .= " selected=\"yes\"";
1809
		$form .= ">Kbit/s</option>";
1810
		$form .= "<option value=\"\"";
1811
		if ($this->GetBwscale() == "b")
1812
			$form .= " selected=\"yes\"";
1813
		$form .= ">Bit/s</option>";
1814
		$form .= "<option value=\"%\"";
1815
		if ($this->GetBwscale() == "%")
1816
			$form .= " selected=\"yes\"";
1817
		$form .= ">%</option>";
1818
		$form .= "</select> <br>";
1819
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
1820
		$form .= "</span></td></tr>";
1821
		$form .= "<tr>";
1822
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Service Curve (sc)</td>";
1823
		$form .= "<td width=\"78%\" class=\"vtable\">";
1824
		$form .= "<table>";
1825
		$form .= "<tr><td>&nbsp;</td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>";
1826
		$form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\"";
1827
		if($this->GetUpperlimit()<> "") 
1828
			$form .=  " CHECKED ";
1829
		$form .= "onChange=\"enable_upperlimit()\"> Upperlimit:</td><td><input size=\"6\" value=\"";
1830
		$form .= htmlspecialchars($this->GetU_m1());
1831
		$form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" ";
1832
		if ($this->GetUpperlimit() == "")
1833
			$form .= " disabled";
1834
		$form .= "></td><td><input size=\"6\" value=\"";
1835
		$form .= htmlspecialchars($this->GetU_d());
1836
		$form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" ";
1837
		if ($this->GetUpperlimit() == "")
1838
			$form .= " disabled";
1839
		$form .= "></td><td><input size=\"6\" value=\"";
1840
		$form .= htmlspecialchars($this->GetU_m2());
1841
		$form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" ";
1842
		if ($this->GetUpperlimit() == "")
1843
			$form .= " disabled";
1844
		$form .= "></td><td>The maximum allowed bandwidth for the queue.</td></tr>";
1845
		$form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\"";
1846
		if($this->GetRealtime() <> "") 
1847
			$form .=  " CHECKED ";
1848
		$form .= "onChange=\"enable_realtime()\"> Real time:</td><td><input size=\"6\" value=\"";
1849
		$form .= htmlspecialchars($this->GetR_m1());
1850
		$form .= "\" id=\"realtime1\" name=\"realtime1\" ";
1851
		if ($this->GetRealtime() == "")
1852
			$form .= " disabled";
1853
		$form .= "></td><td><input size=\"6\" value=\"";
1854
		$form .= htmlspecialchars($this->GetR_d());
1855
		$form .= "\" id=\"realtime2\" name=\"realtime2\" ";
1856
		if ($this->GetRealtime() == "")
1857
			$form .= " disabled";
1858
		$form .= "></td><td><input size=\"6\" value=\"";
1859
		$form .= htmlspecialchars($this->GetR_m2());
1860
		$form .= "\" id=\"realtime3\" name=\"realtime3\" ";
1861
		if ($this->GetRealtime() == "")
1862
			$form .= " disabled";
1863
		$form .= "></td><td>The minimum required bandwidth for the queue.</td></tr>";
1864
		$form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" id=\"linkshare\" name=\"linkshare\"";
1865
		if($this->GetLinkshare() <> "") 
1866
			$form .=  " CHECKED ";
1867
		$form .= "onChange=\"enable_linkshare()\"> Link share:</td><td><input size=\"6\" value=\"";
1868
		$form .= htmlspecialchars($this->GetL_m1());
1869
		$form .= "\" id=\"linkshare1\" name=\"linkshare1\" ";
1870
		if ($this->GetLinkshare() == "")
1871
			$form .= " disabled";
1872
		$form .= "></td><td><input size=\"6\" value=\"";
1873
		$form .= htmlspecialchars($this->GetL_d());
1874
		$form .= "\" id=\"linkshare2\" name=\"linkshare2\" ";
1875
		if ($this->GetLinkshare() == "")
1876
			$form .= " disabled";
1877
		$form .= "></td><td><input size=\"6\" value=\"";
1878
		$form .= htmlspecialchars($this->GetL_m2());
1879
		$form .= "\" id=\"linkshare3\" name=\"linkshare3\" ";
1880
		if ($this->GetLinkshare() == "")
1881
			$form .= " disabled";
1882
		$form .= "></td><td>The bandwidth share of a backlogged queue - this overrides priority.</td></tr>";
1883
		$form .= "</table><br>";
1884
		$form .= "The format for service curve specifications is (m1, d, m2).  m2 controls";
1885
		$form .= "the bandwidth assigned to the queue.  m1 and d are optional and can be";
1886
		$form .= "used to control the initial bandwidth assignment.  For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value";
1887
		$form .= "given in m2.";
1888
		$form .= "</span></td>";
1889
		$form .= "</tr>";
1890

    
1891
		return $form;
1892
	}
1893

    
1894
	function update_altq_queue_data(&$data) { 
1895
		$this->ReadConfig($data);
1896
	}
1897

    
1898
	function wconfig() {
1899
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1900
		if (!is_array($cflink))
1901
			$cflink = array();
1902
		$cflink['name'] = $this->GetQname();
1903
		$cflink['interface'] = $this->GetInterface();
1904
		$cflink['qlimit'] = trim($this->GetQlimit());
1905
		if (empty($cflink['qlimit']))
1906
			unset($cflink['qlimit']);
1907
		$cflink['priority'] = $this->GetQpriority();
1908
		if (empty($cflink['priority']))
1909
			unset($cflink['priority']);
1910
		$cflink['description'] = $this->GetDescription();
1911
		if (empty($cflink['description']))
1912
			unset($cflink['description']);
1913
		$cflink['bandwidth'] = $this->GetBandwidth();
1914
		$cflink['bandwidthtype'] = $this->GetBwscale();
1915
		$cflink['enabled'] = $this->GetEnabled();
1916
		if (empty($cflink['enabled']))
1917
			unset($cflink['enabled']);
1918
		$cflink['default'] = $this->GetDefault();
1919
		if (empty($cflink['default']))
1920
			unset($cflink['default']);
1921
		$cflink['red'] = trim($this->GetRed());
1922
		if (empty($cflink['red']))
1923
			unset($cflink['red']);
1924
		$cflink['rio'] = $this->GetRio();
1925
		if (empty($cflink['rio']))
1926
			unset($cflink['rio']);
1927
		$cflink['ecn'] = trim($this->GetEcn());
1928
		if (empty($cflink['ecn']))
1929
			unset($cflink['ecn']);
1930
		if ($this->GetLinkshare() <> "") {
1931
			if ($this->GetL_m1() <> "") {
1932
				$cflink['linkshare1'] = $this->GetL_m1();
1933
				$cflink['linkshare2'] = $this->GetL_d();
1934
				$cflink['linkshare'] = "on";
1935
			} else {
1936
				unset($cflink['linkshare']);
1937
				unset($cflink['linkshare1']);
1938
				unset($cflink['linkshare2']);
1939
			}
1940
			if ($this->GetL_m2() <> "") {
1941
				$cflink['linkshare3'] = $this->GetL_m2();
1942
				$cflink['linkshare'] = "on";
1943
			} else {
1944
				unset($cflink['linkshare']);
1945
				unset($cflink['linkshare3']);
1946
			}
1947
		} else {
1948
			unset($cflink['linkshare']);
1949
			unset($cflink['linkshare1']);
1950
			unset($cflink['linkshare2']);
1951
			unset($cflink['linkshare3']);
1952
		}
1953
		if ($this->GetRealtime() <> "") {
1954
			if ($this->GetR_m1() <> "") {
1955
				$cflink['realtime1'] = $this->GetR_m1();
1956
				$cflink['realtime2'] = $this->GetR_d();
1957
				$cflink['realtime'] = "on";
1958
			} else {
1959
				unset($cflink['realtime']);
1960
				unset($cflink['realtime1']);
1961
				unset($cflink['realtime2']);
1962
			}
1963
			if ($this->GetR_m2() <> "") {
1964
				$cflink['realtime3'] = $this->GetR_m2();
1965
				$cflink['realtime'] = "on";
1966
			} else {
1967
				unset($cflink['realtime']);
1968
				unset($cflink['realtime3']);
1969
			}
1970
		} else {
1971
			unset($cflink['realtime']);
1972
			unset($cflink['realtime1']);
1973
			unset($cflink['realtime2']);
1974
			unset($cflink['realtime3']);
1975
		}
1976
		if ($this->GetUpperlimit() <> "") {
1977
			if ($this->GetU_m1() <> "") {
1978
				$cflink['upperlimit1'] = $this->GetU_m1();
1979
				$cflink['upperlimit2'] = $this->GetU_d();
1980
				$cflink['upperlimit'] = "on";
1981
			} else {
1982
				unset($cflink['upperlimit']);
1983
				unset($cflink['upperlimit1']);
1984
				unset($cflink['upperlimit2']);
1985
			}
1986
			if ($this->GetU_m2() <> "") {
1987
				$cflink['upperlimit3'] = $this->GetU_m2();
1988
				$cflink['upperlimit'] = "on";
1989
			} else {
1990
				unset($cflink['upperlimit']);
1991
				unset($cflink['upperlimit3']);
1992
			}
1993
		} else {
1994
			unset($cflink['upperlimit']);
1995
			unset($cflink['upperlimit1']);
1996
			unset($cflink['upperlimit2']);
1997
			unset($cflink['upperlimit3']);
1998
		}
1999
	}
2000
}
2001

    
2002
class cbq_queue extends priq_queue {
2003
	var $qborrow = "";
2004

    
2005
	function GetBorrow() {
2006
		return $this->qborrow;
2007
	}
2008
	function SetBorrow($borrow) {
2009
		$this->qborrow = $borrow;
2010
	}
2011
	function CanHaveChildren() {
2012
		return true;
2013
	}
2014

    
2015
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2016

    
2017
		if (!is_array($this->subqueues))
2018
			$this->subqueues = array();
2019
		$q =& new cbq_queue();
2020
		$q->SetInterface($this->GetInterface());
2021
		$q->SetParent(&$this);
2022
		$q->ReadConfig($qname);
2023
                $q->validate_input($qname, $input_errors);
2024
                if (count($input_errors)) {
2025
                        return $q;
2026
                }
2027
                switch ($q->GetBwscale()) {
2028
                case "%":
2029
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2030
                        break;
2031
                default:
2032
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2033
                        break;
2034
                }
2035
                $q->SetAvailableBandwidth($myBw);
2036
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2037

    
2038
		$q->SetEnabled("on");
2039
		$q->SetLink($path);
2040
		$this->subqueues[$q->GetQName()] = &$q;
2041
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2042
		if (is_array($qname['queue'])) {
2043
			foreach ($qname['queue'] as $key1 => $que) {
2044
				array_push($path, $key1);
2045
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2046
				array_pop($path);
2047
			}
2048
		}
2049

    
2050
		return $q;
2051
	}
2052

    
2053
	function copy_queue($interface, &$cflink) {
2054

    
2055
		$cflink['interface'] = $interface;
2056
		$cflink['qlimit'] = trim($this->GetQlimit());
2057
		if (empty($clink['qlimit']))
2058
			unset($cflink['qlimit']);
2059
		$cflink['priority'] = trim($this->GetQpriority());
2060
		if (empty($cflink['priority']))
2061
			unset($cflink['priority']);
2062
		$cflink['name'] = $this->GetQname();
2063
		$cflink['description'] = trim($this->GetDescription());
2064
		if (empty($cflink['description']))
2065
			unset($cflink['description']);
2066
		$cflink['bandwidth'] = $this->GetBandwidth();
2067
		$cflink['bandwidthtype'] = $this->GetBwscale();
2068
		$cflink['enabled'] = trim($this->GetEnabled());
2069
		if (empty($cflink['enabled']))
2070
			unset($cflink['enabled']);
2071
		$cflink['default'] = trim($this->GetDefault());
2072
		if (empty($cflink['default']))
2073
			unset($cflink['default']);
2074
		$cflink['red'] = trim($this->GetRed());
2075
		if (empty($cflink['red']))
2076
			unset($cflink['red']);
2077
		$cflink['rio'] = trim($this->GetRio());
2078
		if (empty($cflink['rio']))
2079
			unset($cflink['rio']);
2080
		$cflink['ecn'] = trim($this->GetEcn());
2081
		if (empty($cflink['ecn']))
2082
			unset($cflink['ecn']);
2083
		$cflink['borrow'] = trim($this->GetBorrow());
2084
		if (empty($cflink['borrow']))
2085
			unset($cflink['borrow']);
2086
		if (is_array($this->queues)) {
2087
			$cflinkp['queue'] = array();
2088
			foreach ($this->subqueues as $q) {
2089
				$cflink['queue'][$q->GetQname()] = array();
2090
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
2091
			}
2092
		}
2093
	}
2094
	
2095
	/*
2096
	 * Should search even its children
2097
	 */
2098
	function &find_queue($interface, $qname) {
2099
		if ($qname == $this->GetQname())
2100
			return $this;
2101
		foreach ($this->subqueues as $q) {
2102
			$result =& $q->find_queue("", $qname);
2103
			if ($result)
2104
				return $result;
2105
		}
2106
	}
2107

    
2108
	function &find_parentqueue($interface, $qname) {
2109
		if ($this->subqueues[$qname])
2110
			return $this;
2111
		foreach ($this->subqueues as $q) {
2112
			$result = $q->find_parentqueue("", $qname);
2113
			if ($result)
2114
				return $result;
2115
		}
2116
	}
2117

    
2118
	function delete_queue() {
2119
		unref_on_altq_queue_list($this->GetQname());
2120
		if ($this->GetDefault())
2121
			altq_set_default_queue($this->GetInterface(), "false");
2122
		cleanup_queue_from_rules($this->GetQname());
2123
		foreach ($this->subqueues as $q) {
2124
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2125
			$q->delete_queue();
2126
		}
2127
		unset_object_by_reference($this->GetLink());
2128
	}
2129
	
2130
	function validate_input($data, &$input_errors) {
2131
		parent::validate_input($data, $input_errors);
2132
		
2133
		if ($data['priority'] > 7)
2134
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2135
		$reqdfields[] = "bandwidth";
2136
		$reqdfieldsn[] = "Bandwidth";
2137
		$reqdfields[] = "bandwidthtype";
2138
		$reqdfieldsn[] = "Bandwidthtype";
2139

    
2140
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2141
		
2142
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2143
			$input_errors[] = "Bandwidth must be an integer.";
2144

    
2145

    
2146
		if ($data['bandwidth'] < 0)
2147
                       $input_errors[] = "Bandwidth cannot be negative.";
2148

    
2149
		if ($data['bandwidthtype'] == "%") {
2150
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2151
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2152
		}
2153

    
2154
/*
2155
           $parent =& $this->GetParent();
2156
           switch ($data['bandwidthtype']) {
2157
                       case "%":
2158
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2159
                       default:
2160
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2161
                             break;
2162
           }
2163
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2164
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2165
*/
2166
	}
2167

    
2168
	function ReadConfig(&$q) {
2169
		parent::ReadConfig($q);
2170
		if (!empty($q['borrow']))
2171
			$this->SetBorrow("on");
2172
	}
2173
		
2174
	function build_javascript() {
2175
		return parent::build_javascript();
2176
	}
2177

    
2178
	function build_tree() {
2179
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2180
		$tree .= "\" ";
2181
		$tmpvalue = trim($this->GetDefault());
2182
		if (!empty($tmpvalue))
2183
			$tree .= " class=\"navlnk\"";
2184
		$tree .= " >" . $this->GetQname() . "</a>";
2185
		if (is_array($this->subqueues)) {
2186
			$tree .= "<ul>";
2187
			foreach ($this->subqueues as $q)  {
2188
				$tree .= $q->build_tree();
2189
			}	
2190
			$tree .= "</ul>";
2191
		}
2192
		$tree .= "</li>";
2193
		return $tree;
2194
	}
2195
		
2196
	/* Even this should take children into consideration */
2197
	function build_rules() {
2198
		$pfq_rule = "queue ". $this->qname;
2199
		if ($this->GetInterface())
2200
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2201
		if ($this->GetBandwidth() && $this->GetBwscale())
2202
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2203
		$tmpvalue = $this->GetQpriority();
2204
		if (!empty($tmpvalue))
2205
			$pfq_rule .= " priority " . $this->GetQpriority();
2206
		$tmpvalue = trim($this->GetQlimit());
2207
		if (!empty($tmpvalue))
2208
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2209
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow()) {
2210
			$pfq_rule .= " cbq ( ";
2211
			$tmpvalue = trim($this->GetRed());
2212
			if (!empty($tmpvalue)) {
2213
				$comma = 1;
2214
				$pfq_rule .= " red ";
2215
			}
2216
			$tmpvalue = trim($this->GetRio());
2217
			if (!empty($tmpvalue)) {
2218
				if ($comma) 
2219
					$pfq_rule .= " ,";
2220
				$comma = 1;
2221
				$pfq_rule .= " rio ";
2222
			}
2223
			$tmpvalue = trim($this->GetEcn());
2224
			if (!empty($tmpvalue)) {
2225
				if ($comma) 
2226
					$pfq_rule .= " ,";
2227
				$comma = 1;
2228
				$pfq_rule .= " ecn ";
2229
			}
2230
			$tmpvalue = trim($this->GetDefault());
2231
			if (!empty($tmpvalue)) {
2232
				if ($comma)
2233
					$pfq_rule .= " ,";
2234
				$comma = 1;
2235
				$pfq_rule .= " default ";
2236
			}
2237
			$tmpvalue = trim($this->GetBorrow());
2238
			if (!empty($tmpvalue)) {
2239
				if ($comma)
2240
					$pfq_rule .= ", ";
2241
				$pfq_rule .= " borrow ";
2242
			}
2243
			$pfq_rule .= " ) ";
2244
		} 
2245
		if (count($this->subqueues)) {
2246
			$i = count($this->subqueues);
2247
			$pfq_rule .= " { ";
2248
			foreach ($this->subqueues as $qkey => $qnone) {
2249
				if ($i > 1) {
2250
					$i--;
2251
					$pfq_rule .= " {$qkey}, ";
2252
				} else
2253
					$pfq_rule .= " {$qkey} ";
2254
			}
2255
			$pfq_rule .= " } \n";
2256
			foreach ($this->subqueues as $q)
2257
				$pfq_rule .= $q->build_rules();
2258
		}
2259

    
2260
		$pfq_rule .= " \n";
2261
		return $pfq_rule;
2262
	}
2263

    
2264
	function build_form() {
2265
		$form = parent::build_form();
2266
		$form .= "<tr>";
2267
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2268
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2269
		if ($this->GetBandwidth() > 0)
2270
			$form .= htmlspecialchars($this->GetBandwidth());
2271
		$form .= "\">";
2272
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2273
		$form .= "<option value=\"Gb\"";
2274
		if ($this->GetBwscale() == "Gb")
2275
			$form .= " selected=\"yes\"";
2276
		$form .= ">Gbit/s</option>";
2277
		$form .= "<option value=\"Mb\"";
2278
		if ($this->GetBwscale() == "Mb")
2279
			$form .= " selected=\"yes\"";
2280
		$form .= ">Mbit/s</option>";
2281
		$form .= "<option value=\"Kb\"";
2282
		if ($this->GetBwscale() == "Kb")
2283
			$form .= " selected=\"yes\"";
2284
		$form .= ">Kbit/s</option>";
2285
		$form .= "<option value=\"\"";
2286
		if ($this->GetBwscale() == "b")
2287
			$form .= " selected=\"yes\"";
2288
		$form .= ">Bit/s</option>";
2289
		$form .= "<option value=\"%\"";
2290
		if ($this->GetBwscale() == "%")
2291
			$form .= " selected=\"yes\"";
2292
		$form .= ">%</option>";
2293
		$form .= "</select> <br>";
2294
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2295
		$form .= "</span></td></tr>";
2296
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2297
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2298
		if($this->GetBorrow() == "on") 
2299
			$form .=  " CHECKED ";
2300
		$form .= "> Borrow from other queues when available<br></td></tr>";
2301

    
2302
		return $form;
2303
	}
2304

    
2305
	function update_altq_queue_data(&$data) { 
2306
		$this->ReadConfig($data);
2307
	}
2308

    
2309
	function wconfig() {
2310
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2311
		if (!is_array($cflink))
2312
			$cflink = array();
2313
		$cflink['interface'] = $this->GetInterface();
2314
		$cflink['qlimit'] = trim($this->GetQlimit());
2315
		if (empty($cflink['qlimit']))
2316
			unset($cflink['qlimit']);
2317
		$cflink['priority'] = $this->GetQpriority();
2318
		if (empty($cflink['priority']))
2319
			unset($cflink['priority']);
2320
		$cflink['name'] = $this->GetQname();
2321
		$cflink['description'] = $this->GetDescription();
2322
		if (empty($cflink['description']))
2323
			unset($cflink['description']);
2324
		$cflink['bandwidth'] = $this->GetBandwidth();
2325
		$cflink['bandwidthtype'] = $this->GetBwscale();
2326
		$cflink['enabled'] = trim($this->GetEnabled());
2327
		if (empty($cflink['enabled']))
2328
			unset($cflink['enabled']);
2329
		$cflink['default'] = trim($this->GetDefault());
2330
		if (empty($cflink['default']))
2331
			unset($cflink['default']);
2332
		$cflink['red'] = trim($this->GetRed());
2333
		if (empty($cflink['red']))
2334
			unset($cflink['red']);
2335
		$cflink['rio'] = trim($this->GetRio());
2336
		if (empty($cflink['rio']))
2337
			unset($cflink['rio']);
2338
		$cflink['ecn'] = trim($this->GetEcn());
2339
		if (empty($cflink['ecn']))
2340
			unset($cflink['ecn']);
2341
		$cflink['borrow'] = trim($this->GetBorrow());
2342
		if (empty($cflink['borrow']))
2343
			unset($cflink['borrow']);
2344
	}
2345
}
2346

    
2347
class fairq_queue extends priq_queue {
2348
	var $hogs;
2349
	var $buckets;
2350

    
2351
	function GetBuckets() {
2352
		return $this->buckets;
2353
	}
2354
	function SetBuckets($buckets) {
2355
		$this->buckets = $buckets;
2356
	}
2357
	function GetHogs() {
2358
		return $this->hogs;
2359
	}
2360
	function SetHogs($hogs) {
2361
		$this->hogs = $hogs;
2362
	}
2363
	function CanHaveChildren() {
2364
		return false;
2365
	}
2366

    
2367

    
2368
	function copy_queue($interface, &$cflink) {
2369
                $cflink['interface'] = $interface;
2370
                $cflink['qlimit'] = $this->GetQlimit();
2371
                $cflink['priority'] = $this->GetQpriority();
2372
                $cflink['name'] = $this->GetQname();
2373
                $cflink['description'] = $this->GetDescription();
2374
                $cflink['bandwidth'] = $this->GetBandwidth();
2375
                $cflink['bandwidthtype'] = $this->GetBwscale();
2376
                $cflink['enabled'] = $this->GetEnabled();
2377
                $cflink['default'] = $this->GetDefault();
2378
                $cflink['red'] = $this->GetRed();
2379
                $cflink['rio'] = $this->GetRio();
2380
                $cflink['ecn'] = $this->GetEcn();
2381
                $cflink['buckets'] = $this->GetBuckets();
2382
		$cflink['hogs'] = $this->GetHogs();
2383
	}
2384
	
2385
	/*
2386
	 * Should search even its children
2387
	 */
2388
	function &find_queue($interface, $qname) {
2389
		if ($qname == $this->GetQname())
2390
			return $this;
2391
	}
2392

    
2393
	function find_parentqueue($interface, $qname) { return; }
2394

    
2395
	function delete_queue() {
2396
		unref_on_altq_queue_list($this->GetQname());
2397
		if ($this->GetDefault())
2398
			altq_set_default_queue($this->GetInterface(), "false");
2399
		cleanup_queue_from_rules($this->GetQname());
2400
		unset_object_by_reference($this->GetLink());
2401
	}
2402
	
2403
	function validate_input($data, &$input_errors) {
2404
		parent::validate_input($data, $input_errors);
2405
		
2406
		if ($data['priority'] > 255)
2407
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2408
		$reqdfields[] = "bandwidth";
2409
		$reqdfieldsn[] = "Bandwidth";
2410
		$reqdfields[] = "bandwidthtype";
2411
		$reqdfieldsn[] = "Bandwidthtype";
2412

    
2413
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2414
		
2415
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2416
	                 $input_errors[] = "Bandwidth must be an integer.";
2417

    
2418

    
2419
	        if ($data['bandwidth'] < 0)
2420
                       $input_errors[] = "Bandwidth cannot be negative.";
2421

    
2422

    
2423
        	if ($data['bandwidthtype'] == "%") {
2424
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2425
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2426
           	}
2427

    
2428
/*
2429
           	$parent =& $this->GetParent();
2430
           	switch ($data['bandwidthtype']) {
2431
                       case "%":
2432
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2433
                       default:
2434
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2435
                             break;
2436
           	}
2437
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2438
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2439
*/
2440
	}
2441
	
2442
	function ReadConfig(&$q) {
2443
		parent::ReadConfig($q);
2444
		if (!empty($q['buckets']))
2445
			$this->SetBuckets($q['buckets']);
2446
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2447
			$this->SetHogs($q['hogs']);
2448
	}
2449
		
2450
	function build_javascript() {
2451
		return parent::build_javascript();
2452
	}
2453

    
2454
	function build_tree() {
2455
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2456
		$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2457
		$tree .= "\" ";
2458
		$tmpvalue = trim($this->GetDefault());
2459
		if (!empty($tmpvalue))
2460
			$tree .= " class=\"navlnk\"";
2461
		$tree .= " >" . $this->GetQname() . "</a>";
2462
		$tree .= "</li>";
2463
		return $tree;
2464
	}
2465
		
2466
	/* Even this should take children into consideration */
2467
	function build_rules() {
2468
		$pfq_rule = "queue ". $this->qname;
2469
		if ($this->GetInterface())
2470
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2471
		if ($this->GetBandwidth() && $this->GetBwscale())
2472
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2473
		$tmpvalue = trim($this->GetQpriority());
2474
		if (!empty($tmpvalue))
2475
			$pfq_rule .= " priority " . $this->GetQpriority();
2476
		$tmpvalue = trim($this->GetQlimit());
2477
		if (!empty($tmpvalue))
2478
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2479
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2480
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2481
			$pfq_rule .= " fairq ( ";
2482
			$tmpvalue = trim($this->GetRed());
2483
			if (!empty($tmpvalue)) {
2484
				$comma = 1;
2485
				$pfq_rule .= " red ";
2486
			}
2487
			$tmpvalue = trim($this->GetRio());
2488
			if (!empty($tmpvalue)) {
2489
				if ($comma) 
2490
					$pfq_rule .= " ,";
2491
				$comma = 1;
2492
				$pfq_rule .= " rio ";
2493
			}
2494
			$tmpvalue = trim($this->GetEcn());
2495
			if (!empty($tmpvalue)) {
2496
				if ($comma) 
2497
					$pfq_rule .= " ,";
2498
				$comma = 1;
2499
				$pfq_rule .= " ecn ";
2500
			}
2501
			$tmpvalue = trim($this->GetDefault());
2502
			if (!empty($tmpvalue)) {
2503
				if ($comma)
2504
					$pfq_rule .= " ,";
2505
				$comma = 1;
2506
				$pfq_rule .= " default ";
2507
			}
2508
			$tmpvalue = trim($this->GetBuckets());
2509
			if (!empty($tmpvalue)) {
2510
				if ($comma)
2511
					$pfq_rule .= ", ";
2512
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2513
			}
2514
			$tmpvalue = trim($this->GetHogs());
2515
			if (!empty($tmpvalue)) {
2516
				if ($comma)
2517
					$pfq_rule .= ", ";
2518
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2519
			}
2520
				$pfq_rule .= " ) ";
2521
		} 
2522

    
2523
		$pfq_rule .= " \n";
2524
		return $pfq_rule;
2525
	}
2526

    
2527
	function build_form() {
2528
		$form = parent::build_form();
2529
		$form .= "<tr>";
2530
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2531
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2532
		if ($this->GetBandwidth() > 0)
2533
			$form .= htmlspecialchars($this->GetBandwidth());
2534
		$form .= "\">";
2535
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2536
		$form .= "<option value=\"Gb\"";
2537
		if ($this->GetBwscale() == "Gb")
2538
			$form .= " selected=\"yes\"";
2539
		$form .= ">Gbit/s</option>";
2540
		$form .= "<option value=\"Mb\"";
2541
		if ($this->GetBwscale() == "Mb")
2542
			$form .= " selected=\"yes\"";
2543
		$form .= ">Mbit/s</option>";
2544
		$form .= "<option value=\"Kb\"";
2545
		if ($this->GetBwscale() == "Kb")
2546
			$form .= " selected=\"yes\"";
2547
		$form .= ">Kbit/s</option>";
2548
		$form .= "<option value=\"\"";
2549
		if ($this->GetBwscale() == "b")
2550
			$form .= " selected=\"yes\"";
2551
		$form .= ">Bit/s</option>";
2552
		$form .= "<option value=\"%\"";
2553
		if ($this->GetBwscale() == "%")
2554
			$form .= " selected=\"yes\"";
2555
		$form .= ">%</option>";
2556
		$form .= "</select> <br>";
2557
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2558
		$form .= "</span></td></tr>";
2559
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2560
		$form .= "<td class=\"vtable\"><table><tr><td>";
2561
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2562
		$tmpvalue = trim($this->GetBuckets());
2563
		if(!empty($tmpvalue)) 
2564
			$form .=  $this->GetBuckets();
2565
		$form .= "\"> Number of buckets available.<br></td></tr>";
2566
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2567
		$tmpvalue = trim($this->GetHogs());
2568
		if(!empty($tmpvalue)) 
2569
			$form .=  $this->GetHogs();
2570
		$form .= "\"> Bandwidth limit for hosts to not saturate link.<br></td></tr>";
2571
		$form .= "</table></td></tr>";
2572
		return $form;
2573
	}
2574

    
2575
	function update_altq_queue_data(&$data) { 
2576
		$this->ReadConfig($data);
2577
	}
2578

    
2579
	function wconfig() {
2580
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2581
		if (!is_array($cflink))
2582
			$cflink = array();
2583
		$cflink['interface'] = $this->GetInterface();
2584
		$cflink['qlimit'] = trim($this->GetQlimit());
2585
		if (empty($cflink['qlimit']))
2586
			unset($cflink['qlimit']);
2587
		$cflink['priority'] = trim($this->GetQpriority());
2588
		if (empty($cflink['priority']))
2589
			unset($cflink['priority']);
2590
		$cflink['name'] = $this->GetQname();
2591
		$cflink['description'] = trim($this->GetDescription());
2592
		if (empty($cflink['description']))
2593
			unset($cflink['description']);
2594
		$cflink['bandwidth'] = $this->GetBandwidth();
2595
		$cflink['bandwidthtype'] = $this->GetBwscale();
2596
		$cflink['enabled'] = $this->GetEnabled();
2597
		if (empty($cflink['enabled']))
2598
			unset($cflink['enabled']);
2599
		$cflink['default'] = trim($this->GetDefault());
2600
		if (empty($cflink['default']))
2601
			unset($cflink['default']);
2602
		$cflink['red'] = trim($this->GetRed());
2603
		if (empty($cflink['red']))
2604
			unset($cflink['red']);
2605
		$cflink['rio'] = trim($this->GetRio());
2606
		if (empty($cflink['rio']))
2607
			unset($cflink['rio']);
2608
		$cflink['ecn'] = trim($this->GetEcn());
2609
		if (empty($cflink['ecn']))
2610
			unset($cflink['ecn']);
2611
		$cflink['buckets'] = trim($this->GetBuckets());
2612
		if (empty($cflink['buckets']))
2613
			unset($cflink['buckets']);
2614
		$cflink['hogs'] = trim($this->GetHogs());
2615
		if (empty($cflink['hogs']))
2616
			unset($cflink['hogs']);
2617
	}
2618
}
2619

    
2620

    
2621
/*
2622
 * dummynet(4) wrappers.
2623
 */
2624

    
2625

    
2626
/*
2627
 * List of respective objects!
2628
 */
2629
$dummynet_pipe_list = array();
2630

    
2631
class dummynet_class {
2632
        var $qname;
2633
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2634
        var $qlimit;
2635
        var $description;
2636
	var $qenabled;
2637
	var $link;
2638
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2639
        var $plr;
2640

    
2641
        var $buckets;
2642
        /* mask parameters */
2643
        var $mask;
2644
        var $noerror;
2645

    
2646
        /* Accessor functions */
2647
        function SetLink($link) {
2648
                $this->link = $link;
2649
        }
2650
        function GetLink() {
2651
                return $this->link;
2652
        }
2653
	function Getmask() {
2654
		return $this->mask;
2655
	}
2656
	function SetMask($mask) {
2657
		$this->mask = $mask;
2658
	}
2659
	function &GetParent() {
2660
		return $this->qparent;
2661
	}
2662
	function SetParent(&$parent) {
2663
		$this->qparent = &$parent;
2664
	}
2665
        function GetEnabled() {
2666
                return $this->qenabled;
2667
        }
2668
        function SetEnabled($value) {
2669
                $this->qenabled = $value;
2670
        }
2671
	function CanHaveChildren() {
2672
		return false;
2673
        }
2674
	function CanBeDeleted() {
2675
                return true;
2676
        }
2677
        function GetQname() {
2678
                return $this->qname;
2679
        }
2680
        function SetQname($name) {
2681
                $this->qname = trim($name);
2682
        }
2683
        function GetQlimit() {
2684
                return $this->qlimit;
2685
        }
2686
        function SetQlimit($limit) {
2687
               	$this->qlimit = $limit;
2688
        }
2689
        function GetDescription() {
2690
                return $this->description;
2691
        }
2692
        function SetDescription($str) {
2693
                $this->description = trim($str);
2694
        }
2695
        function GetFirstime() {
2696
                return $this->firsttime;
2697
        }
2698
        function SetFirsttime($number) {
2699
                $this->firsttime = $number;
2700
        }
2701
        function GetBuckets() {
2702
                return $this->buckets;
2703
        }
2704
        function SetBuckets($buckets) {
2705
                $this->buckets = $buckets;
2706
        }
2707
	function SetNumber($number) {
2708
		$this->qnumber = $number;
2709
	}
2710
	function GetNumber() {
2711
		return $this->qnumber;
2712
	}
2713
        function GetPlr() {
2714
                return $this->plr;
2715
        }
2716
        function SetPlr($plr) {
2717
                $this->plr = $plr;
2718
        }
2719

    
2720
	function build_javascript() { return; } /* Do not remove */
2721

    
2722
	function validate_input($data, &$input_errors) {
2723
		$reqdfields[] = "bandwidth";
2724
		$reqdfieldsn[] = "Bandwidth";
2725
		$reqdfields[] = "bandwidthtype";
2726
		$reqdfieldsn[] = "Bandwidthtype";
2727
		$reqdfields[] = "name";
2728
		$reqdfieldsn[] = "Name";
2729
	
2730
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2731

    
2732
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2733
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2734
            		$input_errors[] = "Plr must be an integer between 1 and 100.";
2735
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2736
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2737
            		$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2738
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2739
            		$input_errors[] = "Queue limit must be an integer";
2740
        	if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2741
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2742
	}
2743
}
2744

    
2745
class dnpipe_class extends dummynet_class {
2746
        var $delay;
2747
	var $qbandwidth;
2748
	var $qbandwidthtype;
2749

    
2750
		/* This is here to help on form building and building rules/lists */
2751
        var $subqueues = array();
2752

    
2753
	function CanHaveChildren() {
2754
	        return true;
2755
        }
2756
	function SetDelay($delay) {
2757
		$this->delay = $delay;
2758
	}
2759
	function GetDelay() {
2760
		return $this->delay;
2761
	}
2762
	function GetBwscale() {
2763
                return $this->qbandwidthtype;
2764
        }
2765
        function SetBwscale($scale) {
2766
               	$this->qbandwidthtype = $scale;
2767
        }		
2768
	function delete_queue() {
2769
		cleanup_dnqueue_from_rules($this->GetQname());
2770
		foreach ($this->subqueues as $q)
2771
			$q->delete_queue();
2772
		unset_dn_object_by_reference($this->GetLink());
2773
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2774
        }
2775
        function GetBandwidth() {
2776
                return $this->qbandwidth;
2777
        }
2778
        function SetBandwidth($bandwidth) {
2779
                $this->qbandwidth = $bandwidth;
2780
        }
2781

    
2782
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2783

    
2784
		if (!is_array($this->subqueues))
2785
			$this->subqueues = array();
2786
			
2787
		$q =& new dnqueue_class();
2788
		$q->SetLink($path);
2789
		$q->SetEnabled("on");
2790
		$q->SetPipe($this->GetQname());
2791
		$q->SetParent(&$this);
2792
		$q->ReadConfig($queue);
2793
		$q->validate_input($queue, $input_errors);
2794
		if (count($input_errors))
2795
			return $q;
2796
		$this->subqueues[$q->GetQname()] = &$q;
2797
            
2798
		return $q;
2799
	}
2800

    
2801
	function &get_queue_list($q = null) {
2802
		$qlist = array();
2803

    
2804
		$qlist[$this->GetQname()] = $this->GetNumber();
2805
		if (is_array($this->subqueues)) {
2806
			foreach ($this->subqueues as $queue)
2807
				$queue->get_queue_list(&$qlist);
2808
		}
2809
		return $qlist;
2810
	}
2811
		
2812
        /*
2813
         * Should search even its children
2814
         */
2815
        function &find_queue($pipe, $qname) {
2816
                if ($qname == $this->GetQname()) 
2817
                        return $this;
2818
               	foreach ($this->subqueues as $q) {
2819
                       	$result =& $q->find_queue("", $qname);
2820
						if ($result)
2821
                       	        return $result;
2822
               	}
2823
        }
2824

    
2825
	function &find_parentqueue($pipe, $qname) {
2826
		return NULL;
2827
       	}
2828

    
2829
	function validate_input($data, &$input_errors) {
2830
		parent::validate_input($data, $input_errors);
2831

    
2832
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2833
       		     	$input_errors[] = "Bandwidth must be an integer.";
2834
		if ($data['delay'] && (!is_numeric($data['delay'])))
2835
            		$input_errors[] = "Delay must be an integer.";
2836
		}
2837

    
2838
	function ReadConfig(&$q) {
2839
           	$this->SetQname($q['name']);
2840
		$this->SetNumber($q['number']);
2841
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2842
			$this->SetBandwidth($q['bandwidth']);
2843
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2844
				$this->SetBwscale($q['bandwidthtype']);
2845
		}
2846
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2847
              		$this->SetQlimit($q['qlimit']);
2848
		if (isset($q['mask']) && $q['mask'] <> "")
2849
              		$this->SetMask($q['mask']);
2850
		if (isset($q['buckets']) && $q['buckets'] <> "")
2851
              		$this->SetBuckets($q['buckets']);
2852
            	if (isset($q['plr']) && $q['plr'] <> "")
2853
            		$this->SetPlr($q['plr']);
2854
		if (isset($q['delay']) && $q['delay'] <> "")
2855
            		$this->SetDelay($q['delay']);
2856
            	if (isset($q['description']) && $q['description'] <> "")
2857
			$this->SetDescription($q['description']);
2858
		$this->SetEnabled($q['enabled']);
2859

    
2860
        }
2861

    
2862
	function build_tree() {
2863
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2864
		$tree .= $this->GetQname() . "</a>";
2865
		if (is_array($this->subqueues)) {
2866
			$tree .= "<ul>";
2867
			foreach ($this->subqueues as $q)  {
2868
				$tree .= $q->build_tree();
2869
			}	
2870
			$tree .= "</ul>";
2871
		}
2872
		$tree .= "</li>";
2873
		
2874
		return $tree;
2875
	}
2876

    
2877
        function build_rules() {
2878
		if ($this->GetEnabled() == "")
2879
			return;
2880

    
2881
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2882
		if ($this->GetBandwidth() && $this->GetBwscale())
2883
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2884
		if ($this->GetQlimit())
2885
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2886
		if ($this->GetPlr())
2887
			$pfq_rule .= " plr " . $this->GetPlr();
2888
		if ($this->GetBuckets())
2889
			$pfq_rule .= " buckets " . $this->GetBuckets();
2890
		if ($this->GetDelay())
2891
			$pfq_rule .= " delay " . $this->GetDelay();
2892

    
2893
		$mask = $this->GetMask();
2894
		if (!empty($mask)) {
2895
			/* XXX TODO extend this to support more complicated masks */
2896
			switch ($mask) {
2897
			case 'srcaddress':
2898
				$pfq_rule .= " mask src-ip 0xffffffff ";
2899
				break;
2900
			case 'dstaddress':
2901
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2902
				break;
2903
			default:
2904
				break;
2905
			}
2906
			$pfq_rule .= "\n";
2907

    
2908
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2909
       			        foreach ($this->subqueues as $q)
2910
				$pfq_rule .= $q->build_rules();
2911
               		}
2912
    		}            
2913
		$pfq_rule .= " \n";
2914

    
2915
		return $pfq_rule;
2916
        }
2917

    
2918
	function update_dn_data(&$data) { 
2919
		$this->ReadConfig($data);
2920
	}
2921

    
2922
        function build_form() { 
2923
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
2924
                $form .= "Enable/Disable";
2925
                $form .= "</td><td class=\"vncellreq\">";
2926
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
2927
                if ($this->GetEnabled() == "on")
2928
                        $form .=  " CHECKED";
2929
                $form .= " ><span class=\"vexpl\"> Enable/Disable limiter and its children</span>";
2930
                $form .= "</td></tr>";
2931
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
2932
		$form .= "<td class=\"vncellreq\">";
2933
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
2934
		$form .= $this->GetQname()."\">";
2935
		$form .= "</td></tr>";
2936
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Bandwidth";
2937
		$form .= "</td><td class=\"vncellreq\">";
2938
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
2939
		$form .= $this->GetBandwidth() . "\">"; 
2940
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
2941
		$form .= "<option value=\"Kb\"";
2942
		if ($this->GetBwscale() == "Kb")
2943
			$form .= " selected=\"yes\"";
2944
		$form .= ">Kbit/s</option>";
2945
		$form .= "<option value=\"Mb\"";
2946
		if ($this->GetBwscale() == "Mb")
2947
			$form .= " selected=\"yes\"";
2948
		$form .= ">Mbit/s</option>";
2949
		$form .= "<option value=\"Gb\"";
2950
		if ($this->GetBwscale() == "Gb")
2951
			$form .= " selected=\"yes\"";
2952
		$form .= ">Gbit/s</option>";		
2953
		$form .= "<option value=\"\"";
2954
		if ($this->GetBwscale() == "b")
2955
			$form .= " selected=\"yes\"";
2956
		$form .= ">Bit/s</option>";
2957
		$form .= "</select>";
2958
		$form .= "</td></tr>";
2959
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Mask</td>";
2960
		$form .= "<td class=\"vncellreq\">";
2961
		$form .= "<select name=\"mask\" class=\"formselect\">";
2962
		$form .= "<option value=\"none\"";
2963
		if ($this->GetMask() == "none")
2964
			$form .= " selected=\"yes\"";
2965
		$form .= ">none</option>";
2966
		$form .= "<option value=\"srcaddress\"";
2967
		if ($this->GetMask() == "srcaddress")
2968
			$form .= " selected=\"yes\"";
2969
		$form .= ">Source addresses</option>";
2970
		$form .= "<option value=\"dstaddress\"";
2971
		if ($this->GetMask() == "dstaddress")
2972
			$form .= " selected=\"yes\"";
2973
		$form .= ">Destination addresses</option>";
2974
		$form .= "</select>";
2975
		$form .= "&nbsp;<br>";
2976
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
2977
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
2978
		$form .= "be created for each source/destination IP address encountered, \n";
2979
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
2980
		$form .= "limits per host.</span>";
2981
		$form .= "</td></tr>";
2982
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
2983
		$form .= "<td class=\"vncellreq\">";
2984
		$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
2985
		$form .= $this->GetDescription();
2986
		$form .= "\">";
2987
		$form .= "<br> <span class=\"vexpl\">";
2988
		$form .= "You may enter a description here ";
2989
		$form .= "for your reference (not parsed).</span>";
2990
		$form .= "</td></tr>";
2991
      		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
2992
		$form .= "<td></td>";
2993
                $form .= "<td><div id=\"showadvancedboxspr\">";
2994
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
2995
		$form .= " value=\"Show advanced options\"></input></a>";
2996
                $form .= "</div></td></tr>";
2997
                $form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
2998

    
2999
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3000
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3001
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3002
		$form .= $this->GetDelay() . "\">";
3003
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3004
		$form .= "should specify 0 here (or leave the field empty)</span>";
3005
		$form .= "</td></tr><br/>";
3006
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3007
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3008
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3009
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3010
		$form .= $this->GetPlr() . "\">";
3011
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3012
        	$form .= "should specify 0 here (or leave the field empty).";
3013
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3014
		$form .= "</td></tr>";
3015
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3016
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3017
		$form .= "<td class=\"vncellreq\">";
3018
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3019
		$form .= $this->GetQlimit() . "\">";
3020
		$form .= "&nbsp;slots<br>";
3021
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3022
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
3023
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
3024
		$form .= "are delivered to their destination.</span>";
3025
		$form .= "</td></tr>";
3026
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3027
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3028
                $form .= "<td class=\"vncellreq\">";
3029
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3030
                $form .= $this->GetBuckets() . "\">";
3031
                $form .= "&nbsp;slots<br>";
3032
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3033
                $form .= "should leave the field empty. It increases the hash size set.";
3034
                $form .= "</td></tr>";
3035

    
3036
		return $form;
3037
			
3038
		}
3039

    
3040
	function wconfig() {
3041
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3042
            	if (!is_array($cflink))
3043
            		$cflink = array();
3044
		$cflink['name'] = $this->GetQname();
3045
		$cflink['number'] = $this->GetNumber();
3046
            	$cflink['qlimit'] = $this->GetQlimit();
3047
            	$cflink['plr'] = $this->GetPlr();
3048
            	$cflink['description'] = $this->GetDescription();
3049
		$cflink['bandwidth'] = $this->GetBandwidth();
3050
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3051
		$cflink['enabled'] = $this->GetEnabled();
3052
		$cflink['buckets'] = $this->GetBuckets();
3053
		$cflink['mask'] = $this->GetMask();
3054
		$cflink['delay'] = $this->GetDelay();
3055
	}
3056

    
3057
}
3058

    
3059
class dnqueue_class extends dummynet_class {
3060
        var $pipeparent;
3061
        var $weight;
3062

    
3063
        function GetWeight() {
3064
                return $this->weight;
3065
        }
3066
        function SetWeight($weight) {
3067
                $this->weight = $weight;
3068
        }
3069
	function GetPipe() {
3070
		return $this->pipeparent;
3071
	}
3072
	function SetPipe($pipe) {
3073
		$this->pipeparent = $pipe;
3074
	}
3075

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

    
3079
	function delete_queue() {
3080
		cleanup_dnqueue_from_rules($this->GetQname());
3081
		unset_dn_object_by_reference($this->GetLink());
3082
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3083
        }
3084

    
3085
	function validate_input($data, &$input_errors) {
3086
		parent::validate_input($data, $input_errors);
3087

    
3088
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3089
			($data['weight'] < 1 && $data['weight'] > 100))) 
3090
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3091
	}
3092

    
3093
        /*
3094
         * Should search even its children
3095
         */
3096
        function &find_queue($pipe, $qname) {
3097
                if ($qname == $this->GetQname()) 
3098
                	return $this;
3099
		else
3100
			return NULL;
3101
        }
3102

    
3103
	function &find_parentqueue($pipe, $qname) {
3104
		return $this->qparent;
3105
        }
3106

    
3107
        function &get_queue_list(&$qlist) {
3108
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3109
        }		
3110

    
3111
	function ReadConfig(&$q) {
3112
          	$this->SetQname($q['name']);
3113
		$this->SetNumber($q['number']);
3114
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3115
       		       	$this->SetQlimit($q['qlimit']);
3116
		if (isset($q['mask']) && $q['mask'] <> "")
3117
              		$this->SetMask($q['mask']);
3118
       		if (isset($q['weight']) && $q['weight'] <> "")
3119
            		$this->SetWeight($q['weight']);
3120
            	if (isset($q['description']) && $q['description'] <> "")
3121
			$this->SetDescription($q['description']);
3122
		$this->SetEnabled($q['enabled']);
3123
        }
3124

    
3125
	function build_tree() {
3126
		$parent =& $this->GetParent();
3127
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3128
		$tree .= $this->GetQname() . "</a>";
3129
		$tree .= "</li>";
3130
		
3131
		return $tree;
3132
	}
3133

    
3134
        function build_rules() {
3135
		if ($this->GetEnabled() == "")
3136
			return; 
3137

    
3138
		$parent =& $this->GetParent();
3139
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3140
		if ($this->GetQlimit())
3141
                    	$pfq_rule .= " queue " . $this->GetQimit();
3142
		if ($this->GetWeight())
3143
			$pfq_rule .= " weight " . $this->GetWeight();
3144
		if ($this->GetBuckets())
3145
			$pfq_rule .= " buckets " . $this->GetBuckets();
3146
		$mask = $this->GetMask();
3147
		if (!empty($mask)) {
3148
			/* XXX TODO extend this to support more complicated masks */
3149
			switch ($mask) {
3150
			case 'srcaddress':
3151
				$pfq_rule .= " mask src-ip 0xffffffff ";
3152
				break;
3153
			case 'dstaddress':
3154
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3155
				break;
3156
			default:
3157
				break;
3158
			}
3159
			$pfq_rule .= "\n";
3160
		}
3161

    
3162
		return $pfq_rule;
3163
	}
3164

    
3165
        function build_form() { 
3166
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
3167
                $form .= "Enable/Disable";
3168
                $form .= "</td><td class=\"vncellreq\">";
3169
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
3170
                if ($this->GetEnabled() == "on")
3171
                        $form .=  " CHECKED";
3172
                $form .= " ><span class=\"vexpl\"> Enable/Disable queue and its children</span>";
3173
                $form .= "</td></tr>";
3174
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
3175
		$form .= "<td class=\"vncellreq\">";
3176
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
3177
		$form .= $this->GetQname()."\">";
3178
		$form .= "</td></tr>";
3179
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Mask</td>";
3180
		$form .= "<td class=\"vncellreq\">";
3181
		$form .= "<select name=\"mask\" class=\"formselect\">";
3182
		$form .= "<option value=\"none\"";
3183
		if ($this->GetMask() == "none")
3184
			$form .= " selected=\"yes\"";
3185
		$form .= ">none</option>";
3186
		$form .= "<option value=\"srcaddress\"";
3187
		if ($this->GetMask() == "srcaddress")
3188
			$form .= " selected=\"yes\"";
3189
		$form .= ">Source addresses</option>";
3190
		$form .= "<option value=\"dstaddress\"";
3191
		if ($this->GetMask() == "dstaddress")
3192
			$form .= " selected=\"yes\"";
3193
		$form .= ">Destination addresses</option>";
3194
		$form .= "</select>";
3195
		$form .= "&nbsp;slots<br>";
3196
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
3197
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
3198
		$form .= "be created for each source/destination IP address encountered, \n";
3199
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
3200
		$form .= "limits per host.</span>";
3201
		$form .= "</td></tr>";
3202
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
3203
		$form .= "<td class=\"vncellreq\">";
3204
		$form .= "<input type=\"text\" id=\"description\" class=\"formfld unknown\" size=\"50%\" name=\"description\" value=\"";
3205
		$form .= $this->GetDescription();
3206
		$form .= "\">";
3207
		$form .= "<br> <span class=\"vexpl\">";
3208
		$form .= "You may enter a description here ";
3209
		$form .= "for your reference (not parsed).</span>";
3210
		$form .= "</td></tr>";
3211
		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3212
		$form .= "<td></td>";
3213
                $form .= "<td><div id=\"showadvancedboxspr\">";
3214
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3215
		$form .= " value=\"Show advanced options\"></input></a>";
3216
                $form .= "</div></td></tr>";
3217
		$form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3218
		$form .= "<td valign=\"center\" class=\"vncellreq\">Weight</td>";
3219
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3220
		$form .= "<input name=\"weight\" type=\"text\" id=\"weight\" size=\"5\" value=\"";
3221
		$form .= $this->GetWeight() . "\">";
3222
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: For queues under the same parent "; 
3223
		$form .= "this specifies the share that a queue gets(values range from 1 to 100, you can leave it blank otherwise)</span>";
3224
		$form .= "</td></tr>";
3225
		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3226
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3227
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3228
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3229
		$form .= $this->GetPlr() . "\">";
3230
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3231
        	$form .= "should specify 0 here (or leave the field empty).";
3232
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3233
		$form .= "</td></tr>";
3234
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3235
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3236
		$form .= "<td class=\"vncellreq\">";
3237
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3238
		$form .= $this->GetQlimit() . "\">";
3239
		$form .= "&nbsp;slots<br>";
3240
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3241
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, ";
3242
        	$form .= "then they are delayed by value specified in the Delay field, and then they ";
3243
		$form .= "are delivered to their destination.</span>";
3244
		$form .= "</td></tr>";
3245
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3246
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3247
                $form .= "<td class=\"vncellreq\">";
3248
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3249
                $form .= $this->GetBuckets() . "\">";
3250
                $form .= "&nbsp;slots<br>";
3251
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3252
                $form .= "should leave the field empty. It increases the hash size set.";
3253
                $form .= "</td></tr>";
3254

    
3255
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3256
		$form .= " value=\"" . $this->GetPipe() . "\">";
3257

    
3258
		return $form;
3259
			
3260
	}
3261

    
3262
        function update_dn_data(&$data) { 
3263
		$this->ReadConfig($data);
3264
	}
3265

    
3266
	function wconfig() {
3267
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3268
            	if (!is_array($cflink))
3269
            		$cflink = array();
3270
		$cflink['name'] = $this->GetQname();
3271
		$cflink['number'] = $this->GetNumber();
3272
            	$cflink['qlimit'] = $this->GetQlimit();
3273
            	$cflink['description'] = $this->GetDescription();
3274
		$cflink['weight'] = $this->GetWeight();
3275
		$cflink['enabled'] = $this->GetEnabled();
3276
		$cflink['buckets'] = $this->GetBuckets();
3277
		$cflink['mask'] = $this->GetMask();
3278
	}
3279
}
3280

    
3281
// List of layer7 objects
3282
$layer7_rules_list = array();
3283

    
3284
class layer7 {
3285
    
3286
    var $rname; //alias
3287
    var $rdescription; //alias description
3288
    var $rport; //divert port
3289
    var $renabled; //rule enabled
3290
    var $rsets = array(); //array of l7 associations
3291
    
3292
    // Auxiliary functions
3293
    
3294
    function GetRName() {
3295
        return $this->rname;
3296
    }
3297
    function SetRName($rname) {
3298
        $this->rname = $rname;
3299
    }
3300
    function GetRDescription() {
3301
        return $this->rdescription;
3302
    }
3303
    function SetRDescription($rdescription) {
3304
        $this->rdescription = $rdescription;
3305
    }
3306
    function GetRPort() {
3307
        return $this->rport;
3308
    }
3309
    function SetRPort($rport) {
3310
        $this->rport = $rport;
3311
    }
3312
    function GetREnabled() {
3313
        return $this->renabled;
3314
    }
3315
    function SetREnabled($value) {
3316
        $this->renabled = $value;
3317
    }
3318
    function GetRl7() {
3319
        return $this->rsets;
3320
    }
3321
    function SetRl7($rsets) {
3322
        $this->rsets = $rsets;
3323
    }
3324
    
3325
    //Add a tuple (rule,sctructure,element) to the $rsets
3326
    
3327
    function add_rule($l7set) {
3328
       	$this->rsets[] = $l7set;
3329
    }
3330
    
3331
    // Build the layer7 rules
3332
    function build_l7_rules() {
3333
        if($this->GetREnabled() == "") {
3334
            return;
3335
        }
3336
        //$l7rules = "#" . $this->rdescription . "\n";
3337
        foreach ($this->rsets as $rl7) {
3338
            $l7rules .= $rl7->build_rules();
3339
        }
3340
        return $l7rules;
3341
    }
3342
    
3343
    // Read the config from array
3344
    function ReadConfig(&$qname, &$q) {
3345
        $this->SetRName($qname);
3346
        $this->SetREnabled($q['enabled']);
3347
        $this->SetRPort($q['divert_port']);
3348
        if(isset($q['description']) && $q['description'] <> "")
3349
            $this->SetRDescription($q['description']);
3350
        $rsets = $q['l7rules'];
3351
        //Put individual rules in the array
3352
	if(is_array($rsets)) {
3353
	    $this->rsets = array(); // XXX: ugly hack
3354
	    foreach($rsets as $l7r) {
3355
	        $l7obj = new l7rule();
3356
	        $l7obj->SetRProtocol($l7r['protocol']);
3357
	        $l7obj->SetRStructure($l7r['structure']);
3358
	        $l7obj->SetRBehaviour($l7r['behaviour']);
3359
	        $this->add_rule($l7obj);
3360
	    }
3361
	}
3362
    }
3363
    
3364
    //Generate a random port for the divert socket
3365
    function gen_divert_port() {
3366
        $dports = get_divert_ports(); //array of used ports
3367
	$divert_port = 1; // Initialize
3368
	while (($divert_port % 2) != 0 || in_array($divert_port, $dports)) {
3369
		$divert_port = rand(40000, 60000);
3370
	}
3371
        return $divert_port;
3372
    }
3373
    
3374
    //Helps building the left tree
3375
    function build_tree() {
3376
        $tree = " <li><a href=\"firewall_shaper_layer7.php?container=" . $this->GetRName() ."&action=show\">"; 
3377
        $tree .= $this->GetRName() . "</a>";
3378
	$tree .= "</li>";
3379
		
3380
	return $tree;
3381
    }
3382
    
3383
    function build_form() {
3384
        $form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
3385
	$form .= "Enable/Disable";
3386
	$form .= "</td><td class=\"vncellreq\">";
3387
	$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\" ";
3388
	if ($this->GetREnabled() == "on") {
3389
       	    $form .=  "checked = \"CHECKED\"";
3390
	}
3391
	$form .= " ><span class=\"vexpl\"> Enable/Disable layer7 Container</span>";
3392
	$form .= "</td></tr>";
3393
        $form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
3394
	$form .= "<td class=\"vncellreq\">";
3395
	$form .= "<input type=\"text\" id=\"container\" name=\"container\" value=\"";
3396
	$form .= $this->GetRName()."\">";
3397
	$form .= "</td></tr>";
3398
	$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
3399
	$form .= "<td class=\"vncellreq\">";
3400
	$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3401
	$form .= $this->GetRDescription();
3402
	$form .= "\">";
3403
	$form .= "<br> <span class=\"vexpl\">";
3404
	$form .= "You may enter a description here ";
3405
	$form .= "for your reference (not parsed).</span>";
3406
	$form .= "</td></tr>";
3407
	
3408
	return $form;
3409
    }
3410
    
3411
    //Write the setting to the $config array
3412
    function wconfig() {
3413
	global $config;
3414
	
3415
	if(!is_array($config['l7shaper']['container'])) {
3416
		$config['l7shaper']['container'] = array();
3417
	}
3418
        //
3419
        $cflink =& get_l7c_reference_to_me_in_config($this->GetRName());
3420
	// Test if this rule does exists already
3421
	if(!$cflink) {
3422
		$cflink =& $config['l7shaper']['container'][];
3423
	}
3424
	$cflink['name'] = $this->GetRName();
3425
        $cflink['enabled'] = $this->GetREnabled();
3426
        $cflink['description'] = $this->GetRDescription();
3427
        $cflink['divert_port'] = $this->GetRPort();
3428
        
3429
	//Destroy previously existent rules
3430
	if(is_array($cflink['rules'])) {
3431
		unset($cflink['l7rules']);
3432
	}
3433
	
3434
        $cflink['l7rules'] = array();
3435
	
3436
        $i = 0;
3437
        foreach($this->rsets as $rulel7) {
3438
            $cflink['l7rules'][$i]['protocol'] = $rulel7->GetRProtocol();
3439
            $cflink['l7rules'][$i]['structure'] = $rulel7->GetRStructure();
3440
            $cflink['l7rules'][$i]['behaviour'] = $rulel7->GetRBehaviour();
3441
            $i++;
3442
        }
3443
    }
3444
    
3445
    //This function is necessary to help producing the overload options for keep state
3446
    function get_unique_structures() {
3447
        
3448
        $unique_structures = array("action" => false, "dummynet" => false, "altq" => false);
3449
        foreach($this->rsets as $l7rule) {
3450
		if($l7rule->GetRStructure() == "action")
3451
			$unique_structures['action'] = true;
3452
		else if($l7rule->GetRStructure() == "limiter")
3453
			$unique_structures['dummynet'] = true;
3454
		else
3455
			$unique_structures['altq'] = true;
3456
        }
3457
	//Delete non used structures so we don't have to check this in filter.inc
3458
	foreach($unique_structures as $key => $value)
3459
		if(!$value)
3460
			unset($unique_structures[$key]);
3461
        return $unique_structures;
3462
    }
3463
    
3464
    function validate_input($data, &$input_errors) {
3465
	$reqdfields[] = "container";
3466
	$reqdfieldsn[] = "Name";
3467
		
3468
	shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
3469
        
3470
        if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['container']))
3471
            $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
3472
    }
3473
    
3474
    function delete_l7c() {
3475
	mwexec("/bin/pkill -f 'ipfw-classifyd .* -p ". $this->GetRPort() . "'", true);
3476
	unset_l7_object_by_reference($this->GetRName());
3477
	cleanup_l7_from_rules($this->GetRName());
3478
    }
3479
}
3480

    
3481
class l7rule {
3482
    
3483
    var $rprotocol; //protocol
3484
    var $rstructure; //action, limiter, queue
3485
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3486
    
3487
    //Auxiliary Functions
3488
    
3489
    function GetRProtocol() {
3490
        return $this->rprotocol;
3491
    }
3492
    function SetRProtocol($rprotocol) {
3493
        $this->rprotocol = $rprotocol;
3494
    }
3495
    function GetRStructure() {
3496
        return $this->rstructure;
3497
    }
3498
    function SetRStructure($rstructure) {
3499
        $this->rstructure = $rstructure;
3500
    }
3501
    function GetRBehaviour() {
3502
        return $this->rbehaviour;
3503
    }
3504
    function SetRBehaviour($rbehaviour) {
3505
        $this->rbehaviour = $rbehaviour;
3506
    }
3507
    
3508
    //XXX Do we need to test any particularity for AltQ queues?
3509
    function build_rules() {
3510
	global $dummynet_pipe_list;
3511
	switch ($this->GetRStructure()) {
3512
		case "limiter":
3513
			read_dummynet_config();
3514
			$dn_list =& get_unique_dnqueue_list();
3515
			$found = false;
3516
			if(is_array($dn_list)) {
3517
				foreach($dn_list as $key => $value) {
3518
					if($key == $this->GetRBehaviour()) {
3519
						if($value[0] == "?")
3520
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3521
						else
3522
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3523
						$found = true;
3524
					}
3525
					if($found)
3526
						break;
3527
				}
3528
			}
3529
			break;
3530
		default: //This is for action and for altq
3531
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3532
			break;
3533
	}
3534
        return $l7rule;
3535
    }
3536
}
3537

    
3538
/*
3539
 * This function allows to return an array with all the used divert socket ports
3540
 */
3541
function get_divert_ports() {
3542
    global $layer7_rules_list;
3543
    $dports = array();
3544
    
3545
    foreach($layer7_rules_list as $l7r)
3546
        $dports[] = $l7r->GetRPort();
3547
    
3548
    return $dports;
3549
}
3550

    
3551
function &get_l7c_reference_to_me_in_config(&$name) {
3552
	global $config;
3553
	
3554
	$ptr = NULL;
3555
	
3556
	if(is_array($config['l7shaper']['container'])) {
3557
		foreach($config['l7shaper']['container'] as $key => $value) {
3558
			if($value['name'] == $name)
3559
				$ptr =& $config['l7shaper']['container'][$key];
3560
		}
3561
	}	
3562
	return $ptr;
3563
// $ptr can be null. has to be checked later
3564
}
3565

    
3566
function unset_l7_object_by_reference(&$name) {
3567
	global $config;
3568
        
3569
	if(is_array($config['l7shaper']['container'])) {
3570
		foreach($config['l7shaper']['container'] as $key => $value) {
3571
			if($value['name'] == $name) {
3572
				unset($config['l7shaper']['container'][$key]['l7rules']);
3573
				unset($config['l7shaper']['container'][$key]);
3574
				break;
3575
			}
3576
		}
3577
	}
3578
}
3579

    
3580
function read_layer7_config() {
3581
    global $layer7_rules_list, $config;
3582
    
3583
    $l7cs = &$config['l7shaper']['container'];
3584
    
3585
    $layer7_rules_list = array();
3586
    
3587
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3588
	return;
3589
    
3590
    foreach ($l7cs as $conf) {
3591
	if (empty($conf['name']))
3592
		continue; /* XXX: grrrrrr at php */ 
3593
        $root =& new layer7();
3594
        $root->ReadConfig($conf['name'],$conf);
3595
        $layer7_rules_list[$root->GetRName()] = &$root;
3596
    }
3597
}
3598

    
3599
function generate_layer7_files() {
3600
    global $layer7_rules_list, $g;
3601
    
3602
    read_layer7_config();
3603
    
3604
    if (!empty($layer7_rules_list)) {
3605
	if (!is_module_loaded("ipdivert.ko"))
3606
		mwexec("/sbin/kldload ipdivert.ko");
3607

    
3608
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3609
    }
3610
    
3611
    foreach($layer7_rules_list as $l7rules) {
3612
        if($l7rules->GetREnabled()) {
3613
            $filename = $l7rules->GetRName() . ".l7";
3614
            $path = "{$g['tmp_path']}/" . $filename;
3615
        
3616
            $rules = $l7rules->build_l7_rules();
3617
        
3618
            $fp = fopen($path,'w');
3619
            fwrite($fp,$rules);
3620
            fclose($fp);
3621
        }
3622
    }
3623
}
3624

    
3625
function layer7_start_l7daemon() {
3626
    global $layer7_rules_list, $g;
3627

    
3628
    /*
3629
     * XXX: ermal - Needed ?!
3630
     * read_layer7_config();
3631
     */
3632

    
3633
    foreach($layer7_rules_list as $l7rules) {
3634
        if($l7rules->GetREnabled()) {
3635
            $filename = $l7rules->GetRName() . ".l7";
3636
            $path = "{$g['tmp_path']}/" . $filename;
3637

    
3638
	    unset($l7pid);
3639
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3640
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3641
	    if (count($l7pid) > 0) {
3642
		log_error("Sending HUP signal to {$l7pid[0]}");
3643
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3644
	    } else {
3645
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3646
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3647
		mwexec_bg($ipfw_classifyd_init);
3648
	    }
3649
        }
3650
    }
3651
}
3652

    
3653
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3654
function generate_protocols_array() {
3655
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3656
	$protocols_new = array();
3657
	if(is_array($protocols)) {
3658
		foreach($protocols as $key => $proto) {
3659
			if (strstr($proto, ".pat"))
3660
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3661
		}
3662
		sort($protocols_new);
3663
	}		
3664
	return $protocols_new;
3665
}
3666

    
3667
function get_l7_unique_list() {
3668
	global $layer7_rules_list;
3669
	
3670
	$l7list = array();
3671
	if(is_array($layer7_rules_list)) 
3672
		foreach($layer7_rules_list as $l7c)
3673
			if($l7c->GetREnabled())
3674
				$l7list[] = $l7c->GetRName();
3675
	
3676
	return $l7list;
3677
}
3678

    
3679
// Disable a removed l7 container from the filter
3680
function cleanup_l7_from_rules(&$name) {
3681
	global $config;
3682

    
3683
	if(is_array($config['filter']['rule']))
3684
		foreach ($config['filter']['rule'] as $key => $rule) {
3685
			if ($rule['l7container'] == $name)
3686
				unset($config['filter']['rule'][$key]['l7container']);
3687
		}
3688
}
3689

    
3690
function get_dummynet_name_list() {
3691
	
3692
	$dn_name_list =& get_unique_dnqueue_list();
3693
	$dn_name = array();
3694
	if(is_array($dn_name_list))
3695
		foreach($dn_name_list as $key => $value)
3696
			$dn_name[] = $key;
3697
	
3698
	return $dn_name;
3699
	
3700
}
3701

    
3702
function get_altq_name_list() {
3703
	$altq_name_list =& get_unique_queue_list();
3704
	$altq_name = array();
3705
	if(is_array($altq_name_list))
3706
		foreach($altq_name_list as $key => $aqobj)
3707
			$altq_name[] = $key;
3708
		
3709
	return $altq_name;
3710
}
3711

    
3712
/*
3713
 * XXX: TODO Make a class shaper to hide all these function
3714
 * from the global namespace.
3715
 */
3716

    
3717
/* 
3718
 * This is a layer violation but for now there is no way 
3719
 * i can find to properly do this with PHP.
3720
 */
3721
function altq_set_default_queue($interface, $value) {
3722
	global $altq_list_queues;
3723
		
3724
	$altq_tmp =& $altq_list_queues[$interface];
3725
	if ($altq_tmp) {
3726
		if ($value) {
3727
			$altq_tmp->SetDefaultQueuePresent("true");
3728
		}
3729
		else {
3730
			$altq_tmp->SetDefaultQueuePresent("false");
3731
		}
3732
	}
3733
}
3734

    
3735
function altq_get_default_queue($interface) {
3736
	global $altq_list_queues;
3737

    
3738
	$altq_tmp = $altq_list_queues[$interface];
3739
	if ($altq_tmp)  
3740
		return $altq_tmp->GetDefaultQueuePresent(); 
3741
}
3742

    
3743
function altq_check_default_queues() {
3744
	global $altq_list_queues;
3745

    
3746
	$count = 0;
3747
	if (is_array($altq_list_queues)) {
3748
		foreach($altq_list_queues as $altq) {
3749
			if ($altq->GetDefaultQueuePresent())
3750
				$count++;
3751
		}
3752
	}
3753
	else  $count++;;
3754
	
3755
	return 0;
3756
}
3757

    
3758
function &get_unique_queue_list() {
3759
	global $altq_list_queues;
3760
	
3761
	$qlist = array();
3762
	if (is_array($altq_list_queues)) {
3763
		foreach ($altq_list_queues as $altq) {
3764
			$tmplist =& $altq->get_queue_list();
3765
			foreach ($tmplist as $qname => $link)
3766
				$qlist[$qname] = $link;	
3767
		}
3768
	}
3769
	return $qlist;
3770
}
3771

    
3772
function &get_unique_dnqueue_list() {
3773
	global $dummynet_pipe_list;
3774
	
3775
	$qlist = array();
3776
	if (is_array($dummynet_pipe_list)) {
3777
		foreach ($dummynet_pipe_list as $dn) {
3778
			$tmplist =& $dn->get_queue_list();
3779
			foreach ($tmplist as $qname => $link)
3780
				$qlist[$qname] = $link;	
3781
		}
3782
	}
3783
	return $qlist;
3784
}
3785

    
3786
function ref_on_altq_queue_list($parent, $qname) {
3787
	if (isset($GLOBALS['queue_list'][$qname]))
3788
		$GLOBALS['queue_list'][$qname]++;
3789
	else
3790
		$GLOBALS['queue_list'][$qname] = 1;
3791

    
3792
	unref_on_altq_queue_list($parent);
3793
}
3794

    
3795
function unref_on_altq_queue_list($qname) {
3796
	$GLOBALS['queue_list'][$qname]--;
3797
	if ($GLOBALS['queue_list'][$qname] <= 1)
3798
		unset($GLOBALS['queue_list'][$qname]);	
3799
}
3800

    
3801
function read_altq_config() {
3802
	global $altq_list_queues, $config;
3803
	$path = array();
3804
	
3805
	if (!is_array($config['shaper']))
3806
		$config['shaper'] = array();
3807
	if (!is_array($config['shaper']['queue']))
3808
		$config['shaper']['queue'] = array();
3809
	$a_int = &$config['shaper']['queue'];
3810

    
3811
	$altq_list_queues = array();
3812
	
3813
	if (!is_array($config['shaper']['queue']))
3814
		return;
3815

    
3816
	foreach ($a_int as $key => $conf) {
3817
				$int = $conf['interface'];
3818
				$root =& new altq_root_queue();
3819
				$root->SetInterface($int);
3820
				$altq_list_queues[$root->GetInterface()] = &$root;
3821
				$root->ReadConfig($conf);
3822
		array_push($path, $key);
3823
		$root->SetLink($path);
3824
		if (is_array($conf['queue'])) {
3825
			foreach ($conf['queue'] as $key1 => $q) {
3826
				array_push($path, $key1);
3827
				/* 
3828
				 * XXX: we compeletely ignore errors here but anyway we must have 
3829
				 *	checked them before so no harm should be come from this.
3830
				 */
3831
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3832
				array_pop($path);
3833
			} 	
3834
				}
3835
		array_pop($path);
3836
	}
3837
}
3838

    
3839
function read_dummynet_config() {
3840
	global $dummynet_pipe_list, $config;
3841
	$path = array();
3842
	$dnqueuenumber = 1;
3843
	$dnpipenumber = 1;
3844

    
3845
	if (!is_array($config['dnshaper']))
3846
		$config['dnshaper'] = array();
3847
	if (!is_array($config['dnshaper']['queue']))
3848
		$config['dnshaper']['queue'] = array();
3849
	$a_int = &$config['dnshaper']['queue'];
3850

    
3851
	$dummynet_pipe_list = array();
3852
	
3853
	if (!is_array($config['dnshaper']['queue'])
3854
		|| !count($config['dnshaper']['queue']))
3855
		return;
3856

    
3857
	foreach ($a_int as $key => $conf) {
3858
		if (empty($conf['name']))
3859
			continue; /* XXX: grrrrrr at php */ 
3860
		$root =& new dnpipe_class();
3861
		$root->ReadConfig($conf);
3862
		$root->SetNumber($dnpipenumber);	
3863
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3864
		array_push($path, $key);
3865
		$root->SetLink($path);
3866
		if (is_array($conf['queue'])) {
3867
			foreach ($conf['queue'] as $key1 => $q) {
3868
				array_push($path, $key1);
3869
				/* XXX: We cheat a little here till a better way is found. */
3870
				$q['number'] = $dnqueuenumber;
3871
				/* 
3872
				 * XXX: we compeletely ignore errors here but anyway we must have 
3873
				 *	checked them before so no harm should be come from this.
3874
				 */	
3875
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3876
				array_pop($path);
3877

    
3878
				$dnqueuenumber++;
3879
			} 	
3880
		}
3881
		array_pop($path);
3882
			
3883
		$dnpipenumber++;
3884
	}
3885
}
3886

    
3887
function get_interface_list_to_show() {
3888
	global $altq_list_queues, $config;
3889
	global $shaperIFlist;
3890

    
3891
	$tree = "";
3892
	foreach ($shaperIFlist as $shif => $shDescr) {
3893
		if ($altq_list_queues[$shif]) {
3894
			continue;
3895
		} else  {
3896
			if (!is_altq_capable(get_real_interface($shif)))
3897
				continue;
3898
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3899
		}
3900
	}
3901
	
3902
	return $tree;
3903
}
3904

    
3905
function filter_generate_altq_queues() {
3906
	global $altq_list_queues;
3907
	
3908
	read_altq_config();
3909

    
3910
	$altq_rules = "";
3911
	foreach ($altq_list_queues as $altq) 
3912
		$altq_rules .= $altq->build_rules();
3913

    
3914
	return $altq_rules;
3915
}
3916

    
3917
function filter_generate_dummynet_rules() {
3918
	global $g, $dummynet_pipe_list;
3919
	
3920
	read_dummynet_config();
3921
	
3922
	if (!empty($dummynet_pipe_list)) {
3923
		if (!is_module_loaded("dummynet.ko"))
3924
			mwexec("/sbin/kldload dummynet");
3925
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
3926
		//mwexec("pfctl -F dummynet");
3927
	}
3928

    
3929
	$dn_rules = "";
3930
	foreach ($dummynet_pipe_list as $dn) 
3931
		$dn_rules .= $dn->build_rules();
3932

    
3933
	if (!empty($dn_rules)) {
3934
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
3935
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
3936
	}
3937
	//return $dn_rules;
3938
}
3939

    
3940
function build_iface_without_this_queue($iface, $qname) {
3941
	global $g, $altq_list_queues;
3942

    
3943
	$altq =& $altq_list_queues[$iface];
3944
				if ($altq)
3945
						$scheduler = ": " . $altq->GetScheduler();
3946
	$form = "<tr><td width=\"20%\" >";
3947
	$form .= "<a href=\"firewall_shaper.php?interface" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
3948
		$form .= "</td></tr>";
3949
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
3950
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
3951
		$form .= $iface . "&queue=". $qname . "&action=add\">";
3952
		$form .= "<img src=\"";
3953
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
3954
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
3955
		$form .= " Clone shaper/queue on this interface</a></td></tr>";
3956

    
3957
		return $form;
3958

    
3959
}
3960

    
3961

    
3962
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3963
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
3964
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3965
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3966
$default_shaper_msg .= " </p></strong></span>";
3967
$default_shaper_msg .= "</td></tr>";
3968

    
3969
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3970
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
3971
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3972
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3973
$dn_default_shaper_msg .= " </p></strong></span>";
3974
$dn_default_shaper_msg .= "</td></tr>";
3975

    
3976

    
3977

    
3978
?>
(37-37/51)