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
		if ($conf['bandwidth'] <> "") {
337
			$this->SetBandwidth($conf['bandwidth']);
338
			if ($conf['bandwidthtype'] <> "")
339
				$this->SetBwscale($conf['bandwidthtype']);
340
		}
341
		if (isset($conf['scheduler'])) {
342
			if ($this->GetScheduler() != $conf['scheduler']) {
343
				foreach ($this->queues as $q) {
344
					clean_child_queues($conf['scheduler'], $this->GetLink());
345
					$q->clean_queue($conf['scheduler']);
346
				}
347
			}
348
			$this->SetScheduler($conf['scheduler']);
349
		}
350
		if (isset($conf['qlimit']) && $conf['qlimit'] <> "")
351
			$this->SetQlimit($conf['qlimit']);
352
		if (isset($conf['name']))
353
			$this->SetQname($conf['name']);		
354
		if (!empty($conf['enabled']))
355
			$this->SetEnabled($conf['enabled']);
356
		else
357
			$this->SetEnabled("");
358
	}
359

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

    
378
	function &get_queue_list($q = null) {
379
		$qlist = array();
380

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

    
389
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
390

    
391
		if (!is_array($this->queues))
392
			$this->queues = array();
393

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

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

    
444
		return $q;
445
	}
446

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

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

    
473
	function build_tree() {
474
		global $shaperIFlist;
475

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

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

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

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

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

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

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

    
588
		return $form;
589

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

    
677

    
678
		return $form;
679
	}
680

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

    
709
}
710

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

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

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

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

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

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

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

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

    
891
	 }
892

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

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

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

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

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

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

    
997
	}
998

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

    
1017
		$tree .= "</li>"; 
1018

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

    
1065
		$pfq_rule .= " \n";
1066

    
1067
		return $pfq_rule;
1068
	}
1069

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

    
1143
		return $form;
1144
	}
1145

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

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

    
1182
	}
1183

    
1184
		function update_altq_queue_data(&$q) { 
1185
		$this->ReadConfig($q);
1186
	}
1187

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

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

    
1238
	/*
1239
	 * HFSC can have nested queues.
1240
	 */
1241

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

    
1327
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1328

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

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

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

    
1366
        function copy_queue($interface, &$cflink) {
1367

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

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

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

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

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

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

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

    
1512
                	if ($data['bandwidth'] < 0)
1513
                        	$input_errors[] = "Bandwidth cannot be negative.";
1514

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

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

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

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

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

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

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

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

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

    
1601
	}
1602

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

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

    
1661
	/* Even this should take children into consideration */
1662
	function build_rules() {
1663

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

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

    
1746
		 $pfq_rule .= " \n";
1747
			
1748
		return $pfq_rule;
1749
	}
1750

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

    
1790
		return $javascript;
1791
	}
1792

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

    
1894
		return $form;
1895
	}
1896

    
1897
	function update_altq_queue_data(&$data) { 
1898
		$this->ReadConfig($data);
1899
	}
1900

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

    
2005
class cbq_queue extends priq_queue {
2006
	var $qborrow = "";
2007

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

    
2018
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2019

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

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

    
2053
		return $q;
2054
	}
2055

    
2056
	function copy_queue($interface, &$cflink) {
2057

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

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

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

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

    
2148

    
2149
		if ($data['bandwidth'] < 0)
2150
                       $input_errors[] = "Bandwidth cannot be negative.";
2151

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

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

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

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

    
2263
		$pfq_rule .= " \n";
2264
		return $pfq_rule;
2265
	}
2266

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

    
2305
		return $form;
2306
	}
2307

    
2308
	function update_altq_queue_data(&$data) { 
2309
		$this->ReadConfig($data);
2310
	}
2311

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

    
2350
class fairq_queue extends priq_queue {
2351
	var $hogs;
2352
	var $buckets;
2353

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

    
2370

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

    
2396
	function find_parentqueue($interface, $qname) { return; }
2397

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

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

    
2421

    
2422
	        if ($data['bandwidth'] < 0)
2423
                       $input_errors[] = "Bandwidth cannot be negative.";
2424

    
2425

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

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

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

    
2526
		$pfq_rule .= " \n";
2527
		return $pfq_rule;
2528
	}
2529

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

    
2578
	function update_altq_queue_data(&$data) { 
2579
		$this->ReadConfig($data);
2580
	}
2581

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

    
2623

    
2624
/*
2625
 * dummynet(4) wrappers.
2626
 */
2627

    
2628

    
2629
/*
2630
 * List of respective objects!
2631
 */
2632
$dummynet_pipe_list = array();
2633

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

    
2644
        var $buckets;
2645
        /* mask parameters */
2646
        var $mask;
2647
        var $noerror;
2648

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

    
2723
	function build_javascript() { return; } /* Do not remove */
2724

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

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

    
2748
class dnpipe_class extends dummynet_class {
2749
        var $delay;
2750
	var $qbandwidth;
2751
	var $qbandwidthtype;
2752

    
2753
		/* This is here to help on form building and building rules/lists */
2754
        var $subqueues = array();
2755

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

    
2785
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2786

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

    
2804
	function &get_queue_list($q = null) {
2805
		$qlist = array();
2806

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

    
2828
	function &find_parentqueue($pipe, $qname) {
2829
		return NULL;
2830
       	}
2831

    
2832
	function validate_input($data, &$input_errors) {
2833
		parent::validate_input($data, $input_errors);
2834

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

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

    
2863
        }
2864

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

    
2880
        function build_rules() {
2881
		if ($this->GetEnabled() == "")
2882
			return;
2883

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

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

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

    
2918
		return $pfq_rule;
2919
        }
2920

    
2921
	function update_dn_data(&$data) { 
2922
		$this->ReadConfig($data);
2923
	}
2924

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

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

    
3039
		return $form;
3040
			
3041
		}
3042

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

    
3060
}
3061

    
3062
class dnqueue_class extends dummynet_class {
3063
        var $pipeparent;
3064
        var $weight;
3065

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

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

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

    
3088
	function validate_input($data, &$input_errors) {
3089
		parent::validate_input($data, $input_errors);
3090

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

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

    
3106
	function &find_parentqueue($pipe, $qname) {
3107
		return $this->qparent;
3108
        }
3109

    
3110
        function &get_queue_list(&$qlist) {
3111
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3112
        }		
3113

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

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

    
3137
        function build_rules() {
3138
		if ($this->GetEnabled() == "")
3139
			return; 
3140

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

    
3165
		return $pfq_rule;
3166
	}
3167

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

    
3258
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3259
		$form .= " value=\"" . $this->GetPipe() . "\">";
3260

    
3261
		return $form;
3262
			
3263
	}
3264

    
3265
        function update_dn_data(&$data) { 
3266
		$this->ReadConfig($data);
3267
	}
3268

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

    
3284
// List of layer7 objects
3285
$layer7_rules_list = array();
3286

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

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

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

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

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

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

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

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

    
3628
function layer7_start_l7daemon() {
3629
    global $layer7_rules_list, $g;
3630

    
3631
    /*
3632
     * XXX: ermal - Needed ?!
3633
     * read_layer7_config();
3634
     */
3635

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

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

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

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

    
3682
// Disable a removed l7 container from the filter
3683
function cleanup_l7_from_rules(&$name) {
3684
	global $config;
3685

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

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

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

    
3715
/*
3716
 * XXX: TODO Make a class shaper to hide all these function
3717
 * from the global namespace.
3718
 */
3719

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

    
3738
function altq_get_default_queue($interface) {
3739
	global $altq_list_queues;
3740

    
3741
	$altq_tmp = $altq_list_queues[$interface];
3742
	if ($altq_tmp)  
3743
		return $altq_tmp->GetDefaultQueuePresent(); 
3744
}
3745

    
3746
function altq_check_default_queues() {
3747
	global $altq_list_queues;
3748

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

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

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

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

    
3795
	unref_on_altq_queue_list($parent);
3796
}
3797

    
3798
function unref_on_altq_queue_list($qname) {
3799
	$GLOBALS['queue_list'][$qname]--;
3800
	if ($GLOBALS['queue_list'][$qname] <= 1)
3801
		unset($GLOBALS['queue_list'][$qname]);	
3802
}
3803

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

    
3814
	$altq_list_queues = array();
3815
	
3816
	if (!is_array($config['shaper']['queue']))
3817
		return;
3818

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

    
3842
function read_dummynet_config() {
3843
	global $dummynet_pipe_list, $config;
3844
	$path = array();
3845
	$dnqueuenumber = 1;
3846
	$dnpipenumber = 1;
3847

    
3848
	if (!is_array($config['dnshaper']))
3849
		$config['dnshaper'] = array();
3850
	if (!is_array($config['dnshaper']['queue']))
3851
		$config['dnshaper']['queue'] = array();
3852
	$a_int = &$config['dnshaper']['queue'];
3853

    
3854
	$dummynet_pipe_list = array();
3855
	
3856
	if (!is_array($config['dnshaper']['queue'])
3857
		|| !count($config['dnshaper']['queue']))
3858
		return;
3859

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

    
3881
				$dnqueuenumber++;
3882
			} 	
3883
		}
3884
		array_pop($path);
3885
			
3886
		$dnpipenumber++;
3887
	}
3888
}
3889

    
3890
function get_interface_list_to_show() {
3891
	global $altq_list_queues, $config;
3892
	global $shaperIFlist;
3893

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

    
3908
function filter_generate_altq_queues() {
3909
	global $altq_list_queues;
3910
	
3911
	read_altq_config();
3912

    
3913
	$altq_rules = "";
3914
	foreach ($altq_list_queues as $altq) 
3915
		$altq_rules .= $altq->build_rules();
3916

    
3917
	return $altq_rules;
3918
}
3919

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

    
3932
	$dn_rules = "";
3933
	foreach ($dummynet_pipe_list as $dn) 
3934
		$dn_rules .= $dn->build_rules();
3935

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

    
3943
function build_iface_without_this_queue($iface, $qname) {
3944
	global $g, $altq_list_queues;
3945

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

    
3960
		return $form;
3961

    
3962
}
3963

    
3964

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

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

    
3979

    
3980

    
3981
?>
(37-37/50)