Project

General

Profile

Download (126 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
		else
337
			$this->SetTbrConfig($conf['tbrconfig']);
338
		$this->SetBandwidth($conf['bandwidth']);
339
		if ($conf['bandwidthtype'] <> "")
340
			$this->SetBwscale($conf['bandwidthtype']);
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
		else
353
			$this->SetQlimit("");
354
		if (isset($conf['name']))
355
			$this->SetQname($conf['name']);		
356
		if (!empty($conf['enabled']))
357
			$this->SetEnabled($conf['enabled']);
358
		else
359
			$this->SetEnabled("");
360
	}
361

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

    
380
	function &get_queue_list($q = null) {
381
		$qlist = array();
382

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

    
391
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
392

    
393
		if (!is_array($this->queues))
394
			$this->queues = array();
395

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

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

    
446
		return $q;
447
	}
448

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

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

    
475
	function build_tree() {
476
		global $shaperIFlist;
477

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

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

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

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

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

    
566
		return $javascript;
567
	}
568
	
569
	function build_shortform() {
570
		global $g;
571

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

    
591
		return $form;
592

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

    
680

    
681
		return $form;
682
	}
683

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

    
712
}
713

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

    
733
	/* This is here to help with form building and building rules/lists */
734
		var $subqueues = array();
735

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

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

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

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

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

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

    
894
	 }
895

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

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

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

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

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

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

    
999
	}
1000

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

    
1019
		$tree .= "</li>"; 
1020

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

    
1067
		$pfq_rule .= " \n";
1068

    
1069
		return $pfq_rule;
1070
	}
1071

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

    
1145
		return $form;
1146
	}
1147

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

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

    
1184
	}
1185

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1602
	}
1603

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

    
1656
	function build_tree() {
1657
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1658
		$tree .= "\" ";
1659
		$tmpvalue = $this->GetDefault();
1660
		if (!empty($tmpvalue))
1661
			$tree .= " class=\"navlnk\"";
1662
		$tree .= " >" . $this->GetQname() . "</a>";
1663
		if (is_array($this->subqueues)) {
1664
			$tree .= "<ul>";
1665
			foreach ($this->subqueues as $q)  {
1666
				$tree .= $q->build_tree();
1667
			}	
1668
			$tree .= "</ul>";
1669
		}
1670
		$tree .= "</li>";
1671
		return $tree;
1672
	}
1673

    
1674
	/* Even this should take children into consideration */
1675
	function build_rules() {
1676

    
1677
		$pfq_rule = " queue ". $this->qname;
1678
		if ($this->GetInterface())
1679
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1680
		if ($this->GetBandwidth() && $this->GetBwscale())
1681
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1682
				
1683
		$tmpvalue = $this->GetQlimit();
1684
		if (!empty($tmpvalue))
1685
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1686
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1687
			$pfq_rule .= " hfsc ( ";
1688
			$tmpvalue = $this->GetRed();
1689
			if (!empty($tmpvalue)) {
1690
				$comma = 1;
1691
				$pfq_rule .= " red ";
1692
			}
1693
			
1694
			$tmpvalue = $this->GetRio();
1695
			if (!empty($tmpvalue)) {
1696
				if ($comma) 
1697
					$pfq_rule .= " ,";
1698
				$comma = 1;
1699
				$pfq_rule .= " rio ";
1700
			}
1701
			$tmpvalue = $this->GetEcn();
1702
			if (!empty($tmpvalue)) {
1703
				if ($comma) 
1704
					$pfq_rule .= " ,";
1705
				$comma = 1;
1706
				$pfq_rule .= " ecn ";
1707
			}
1708
			$tmpvalue = $this->GetDefault();
1709
			if (!empty($tmpvalue)) {
1710
				if ($comma)
1711
					$pfq_rule .= " ,";
1712
				$comma = 1;
1713
				$pfq_rule .= " default ";
1714
			}
1715

    
1716
			if ($this->GetRealtime() <> "")  {
1717
				if ($comma) 
1718
					$pfq_rule .= " , ";
1719
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1720
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1721
				else  if ($this->GetR_m2() <> "")
1722
					$pfq_rule .= " realtime " . $this->GetR_m2();
1723
				$comma = 1;
1724
			}
1725
			if ($this->GetLinkshare() <> "") {
1726
				if ($comma)
1727
					$pfq_rule .= " ,";
1728
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1729
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1730
				else if ($this->GetL_m2() <> "")
1731
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1732
				$comma = 1;
1733
			}
1734
			if ($this->GetUpperlimit() <> "") {
1735
				if ($comma)
1736
					$pfq_rule .= " ,";
1737
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1738
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1739
				else if ($this->GetU_m2() <> "")
1740
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1741
			}
1742
			$pfq_rule .= " ) ";
1743
		}
1744
		if (count($this->subqueues)) {
1745
			$i = count($this->subqueues);
1746
			$pfq_rule .= " { ";
1747
			foreach ($this->subqueues as $qkey => $qnone) {
1748
				if ($i > 1) {
1749
					$i--;
1750
					$pfq_rule .= " {$qkey}, ";
1751
				} else
1752
					$pfq_rule .= " {$qkey} ";
1753
			}
1754
			$pfq_rule .= " } \n";
1755
			foreach ($this->subqueues as $q)
1756
				$pfq_rule .= $q->build_rules();
1757
		}
1758

    
1759
		 $pfq_rule .= " \n";
1760
			
1761
		return $pfq_rule;
1762
	}
1763

    
1764
	function build_javascript() {
1765
		$javascript = parent::build_javascript();
1766
		$javascript .= "<script type=\"text/javascript\">";
1767
		$javascript .= "function enable_realtime(enable_over) { \n";
1768
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1769
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1770
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1771
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1772
		$javascript .= " } else { \n";
1773
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1774
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1775
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1776
		$javascript .= " } \n";
1777
		$javascript .= " } \n";
1778
		$javascript .= "function enable_linkshare(enable_over) { \n";
1779
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1780
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1781
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1782
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1783
		$javascript .= " } else { \n";
1784
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1785
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1786
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1787
		$javascript .= " } \n";
1788
		$javascript .= " } \n";
1789
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1790
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1791
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1792
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1793
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1794
		$javascript .= " } else { \n";
1795
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1796
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1797
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1798
		$javascript .= " } \n";
1799
			
1800
		$javascript .= "} \n";
1801
		$javascript .= "</script>";
1802

    
1803
		return $javascript;
1804
	}
1805

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

    
1907
		return $form;
1908
	}
1909

    
1910
	function update_altq_queue_data(&$data) { 
1911
		$this->ReadConfig($data);
1912
	}
1913

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

    
2018
class cbq_queue extends priq_queue {
2019
	var $qborrow = "";
2020

    
2021
	function GetBorrow() {
2022
		return $this->qborrow;
2023
	}
2024
	function SetBorrow($borrow) {
2025
		$this->qborrow = $borrow;
2026
	}
2027
	function CanHaveChildren() {
2028
		return true;
2029
	}
2030

    
2031
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2032

    
2033
		if (!is_array($this->subqueues))
2034
			$this->subqueues = array();
2035
		$q =& new cbq_queue();
2036
		$q->SetInterface($this->GetInterface());
2037
		$q->SetParent(&$this);
2038
		$q->ReadConfig($qname);
2039
                $q->validate_input($qname, $input_errors);
2040
                if (count($input_errors)) {
2041
                        return $q;
2042
                }
2043
                switch ($q->GetBwscale()) {
2044
                case "%":
2045
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2046
                        break;
2047
                default:
2048
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2049
                        break;
2050
                }
2051
                $q->SetAvailableBandwidth($myBw);
2052
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2053

    
2054
		$q->SetEnabled("on");
2055
		$q->SetLink($path);
2056
		$this->subqueues[$q->GetQName()] = &$q;
2057
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2058
		if (is_array($qname['queue'])) {
2059
			foreach ($qname['queue'] as $key1 => $que) {
2060
				array_push($path, $key1);
2061
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2062
				array_pop($path);
2063
			}
2064
		}
2065

    
2066
		return $q;
2067
	}
2068

    
2069
	function copy_queue($interface, &$cflink) {
2070

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

    
2124
	function &find_parentqueue($interface, $qname) {
2125
		if ($this->subqueues[$qname])
2126
			return $this;
2127
		foreach ($this->subqueues as $q) {
2128
			$result = $q->find_parentqueue("", $qname);
2129
			if ($result)
2130
				return $result;
2131
		}
2132
	}
2133

    
2134
	function delete_queue() {
2135
		unref_on_altq_queue_list($this->GetQname());
2136
		if ($this->GetDefault())
2137
			altq_set_default_queue($this->GetInterface(), "false");
2138
		cleanup_queue_from_rules($this->GetQname());
2139
		foreach ($this->subqueues as $q) {
2140
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2141
			$q->delete_queue();
2142
		}
2143
		unset_object_by_reference($this->GetLink());
2144
	}
2145
	
2146
	function validate_input($data, &$input_errors) {
2147
		parent::validate_input($data, $input_errors);
2148
		
2149
		if ($data['priority'] > 7)
2150
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2151
		$reqdfields[] = "bandwidth";
2152
		$reqdfieldsn[] = "Bandwidth";
2153
		$reqdfields[] = "bandwidthtype";
2154
		$reqdfieldsn[] = "Bandwidthtype";
2155

    
2156
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2157
		
2158
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2159
			$input_errors[] = "Bandwidth must be an integer.";
2160

    
2161

    
2162
		if ($data['bandwidth'] < 0)
2163
                       $input_errors[] = "Bandwidth cannot be negative.";
2164

    
2165
		if ($data['bandwidthtype'] == "%") {
2166
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2167
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2168
		}
2169

    
2170
/*
2171
           $parent =& $this->GetParent();
2172
           switch ($data['bandwidthtype']) {
2173
                       case "%":
2174
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2175
                       default:
2176
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2177
                             break;
2178
           }
2179
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2180
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2181
*/
2182
	}
2183

    
2184
	function ReadConfig(&$q) {
2185
		parent::ReadConfig($q);
2186
		if (!empty($q['borrow']))
2187
			$this->SetBorrow("on");
2188
		else
2189
			$this->SetBorrow("");
2190
	}
2191
		
2192
	function build_javascript() {
2193
		return parent::build_javascript();
2194
	}
2195

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

    
2278
		$pfq_rule .= " \n";
2279
		return $pfq_rule;
2280
	}
2281

    
2282
	function build_form() {
2283
		$form = parent::build_form();
2284
		$form .= "<tr>";
2285
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2286
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2287
		if ($this->GetBandwidth() > 0)
2288
			$form .= htmlspecialchars($this->GetBandwidth());
2289
		$form .= "\">";
2290
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2291
		$form .= "<option value=\"Gb\"";
2292
		if ($this->GetBwscale() == "Gb")
2293
			$form .= " selected=\"yes\"";
2294
		$form .= ">Gbit/s</option>";
2295
		$form .= "<option value=\"Mb\"";
2296
		if ($this->GetBwscale() == "Mb")
2297
			$form .= " selected=\"yes\"";
2298
		$form .= ">Mbit/s</option>";
2299
		$form .= "<option value=\"Kb\"";
2300
		if ($this->GetBwscale() == "Kb")
2301
			$form .= " selected=\"yes\"";
2302
		$form .= ">Kbit/s</option>";
2303
		$form .= "<option value=\"\"";
2304
		if ($this->GetBwscale() == "b")
2305
			$form .= " selected=\"yes\"";
2306
		$form .= ">Bit/s</option>";
2307
		$form .= "<option value=\"%\"";
2308
		if ($this->GetBwscale() == "%")
2309
			$form .= " selected=\"yes\"";
2310
		$form .= ">%</option>";
2311
		$form .= "</select> <br>";
2312
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2313
		$form .= "</span></td></tr>";
2314
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2315
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2316
		if($this->GetBorrow() == "on") 
2317
			$form .=  " CHECKED ";
2318
		$form .= "> Borrow from other queues when available<br></td></tr>";
2319

    
2320
		return $form;
2321
	}
2322

    
2323
	function update_altq_queue_data(&$data) { 
2324
		$this->ReadConfig($data);
2325
	}
2326

    
2327
	function wconfig() {
2328
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2329
		if (!is_array($cflink))
2330
			$cflink = array();
2331
		$cflink['interface'] = $this->GetInterface();
2332
		$cflink['qlimit'] = trim($this->GetQlimit());
2333
		if (empty($cflink['qlimit']))
2334
			unset($cflink['qlimit']);
2335
		$cflink['priority'] = $this->GetQpriority();
2336
		if (empty($cflink['priority']))
2337
			unset($cflink['priority']);
2338
		$cflink['name'] = $this->GetQname();
2339
		$cflink['description'] = $this->GetDescription();
2340
		if (empty($cflink['description']))
2341
			unset($cflink['description']);
2342
		$cflink['bandwidth'] = $this->GetBandwidth();
2343
		$cflink['bandwidthtype'] = $this->GetBwscale();
2344
		$cflink['enabled'] = trim($this->GetEnabled());
2345
		if (empty($cflink['enabled']))
2346
			unset($cflink['enabled']);
2347
		$cflink['default'] = trim($this->GetDefault());
2348
		if (empty($cflink['default']))
2349
			unset($cflink['default']);
2350
		$cflink['red'] = trim($this->GetRed());
2351
		if (empty($cflink['red']))
2352
			unset($cflink['red']);
2353
		$cflink['rio'] = trim($this->GetRio());
2354
		if (empty($cflink['rio']))
2355
			unset($cflink['rio']);
2356
		$cflink['ecn'] = trim($this->GetEcn());
2357
		if (empty($cflink['ecn']))
2358
			unset($cflink['ecn']);
2359
		$cflink['borrow'] = trim($this->GetBorrow());
2360
		if (empty($cflink['borrow']))
2361
			unset($cflink['borrow']);
2362
	}
2363
}
2364

    
2365
class fairq_queue extends priq_queue {
2366
	var $hogs;
2367
	var $buckets;
2368

    
2369
	function GetBuckets() {
2370
		return $this->buckets;
2371
	}
2372
	function SetBuckets($buckets) {
2373
		$this->buckets = $buckets;
2374
	}
2375
	function GetHogs() {
2376
		return $this->hogs;
2377
	}
2378
	function SetHogs($hogs) {
2379
		$this->hogs = $hogs;
2380
	}
2381
	function CanHaveChildren() {
2382
		return false;
2383
	}
2384

    
2385

    
2386
	function copy_queue($interface, &$cflink) {
2387
                $cflink['interface'] = $interface;
2388
                $cflink['qlimit'] = $this->GetQlimit();
2389
                $cflink['priority'] = $this->GetQpriority();
2390
                $cflink['name'] = $this->GetQname();
2391
                $cflink['description'] = $this->GetDescription();
2392
                $cflink['bandwidth'] = $this->GetBandwidth();
2393
                $cflink['bandwidthtype'] = $this->GetBwscale();
2394
                $cflink['enabled'] = $this->GetEnabled();
2395
                $cflink['default'] = $this->GetDefault();
2396
                $cflink['red'] = $this->GetRed();
2397
                $cflink['rio'] = $this->GetRio();
2398
                $cflink['ecn'] = $this->GetEcn();
2399
                $cflink['buckets'] = $this->GetBuckets();
2400
		$cflink['hogs'] = $this->GetHogs();
2401
	}
2402
	
2403
	/*
2404
	 * Should search even its children
2405
	 */
2406
	function &find_queue($interface, $qname) {
2407
		if ($qname == $this->GetQname())
2408
			return $this;
2409
	}
2410

    
2411
	function find_parentqueue($interface, $qname) { return; }
2412

    
2413
	function delete_queue() {
2414
		unref_on_altq_queue_list($this->GetQname());
2415
		if ($this->GetDefault())
2416
			altq_set_default_queue($this->GetInterface(), "false");
2417
		cleanup_queue_from_rules($this->GetQname());
2418
		unset_object_by_reference($this->GetLink());
2419
	}
2420
	
2421
	function validate_input($data, &$input_errors) {
2422
		parent::validate_input($data, $input_errors);
2423
		
2424
		if ($data['priority'] > 255)
2425
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2426
		$reqdfields[] = "bandwidth";
2427
		$reqdfieldsn[] = "Bandwidth";
2428
		$reqdfields[] = "bandwidthtype";
2429
		$reqdfieldsn[] = "Bandwidthtype";
2430

    
2431
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2432
		
2433
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2434
	                 $input_errors[] = "Bandwidth must be an integer.";
2435

    
2436

    
2437
	        if ($data['bandwidth'] < 0)
2438
                       $input_errors[] = "Bandwidth cannot be negative.";
2439

    
2440

    
2441
        	if ($data['bandwidthtype'] == "%") {
2442
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2443
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2444
           	}
2445

    
2446
/*
2447
           	$parent =& $this->GetParent();
2448
           	switch ($data['bandwidthtype']) {
2449
                       case "%":
2450
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2451
                       default:
2452
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2453
                             break;
2454
           	}
2455
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2456
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2457
*/
2458
	}
2459
	
2460
	function ReadConfig(&$q) {
2461
		parent::ReadConfig($q);
2462
		if (!empty($q['buckets']))
2463
			$this->SetBuckets($q['buckets']);
2464
		else
2465
			$this->SetBuckets("");
2466
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2467
			$this->SetHogs($q['hogs']);
2468
		else
2469
			$this->SetHogs("");
2470
	}
2471
		
2472
	function build_javascript() {
2473
		return parent::build_javascript();
2474
	}
2475

    
2476
	function build_tree() {
2477
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2478
		$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2479
		$tree .= "\" ";
2480
		$tmpvalue = trim($this->GetDefault());
2481
		if (!empty($tmpvalue))
2482
			$tree .= " class=\"navlnk\"";
2483
		$tree .= " >" . $this->GetQname() . "</a>";
2484
		$tree .= "</li>";
2485
		return $tree;
2486
	}
2487
		
2488
	/* Even this should take children into consideration */
2489
	function build_rules() {
2490
		$pfq_rule = "queue ". $this->qname;
2491
		if ($this->GetInterface())
2492
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2493
		if ($this->GetBandwidth() && $this->GetBwscale())
2494
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2495
		$tmpvalue = trim($this->GetQpriority());
2496
		if (!empty($tmpvalue))
2497
			$pfq_rule .= " priority " . $this->GetQpriority();
2498
		$tmpvalue = trim($this->GetQlimit());
2499
		if (!empty($tmpvalue))
2500
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2501
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2502
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2503
			$pfq_rule .= " fairq ( ";
2504
			$tmpvalue = trim($this->GetRed());
2505
			if (!empty($tmpvalue)) {
2506
				$comma = 1;
2507
				$pfq_rule .= " red ";
2508
			}
2509
			$tmpvalue = trim($this->GetRio());
2510
			if (!empty($tmpvalue)) {
2511
				if ($comma) 
2512
					$pfq_rule .= " ,";
2513
				$comma = 1;
2514
				$pfq_rule .= " rio ";
2515
			}
2516
			$tmpvalue = trim($this->GetEcn());
2517
			if (!empty($tmpvalue)) {
2518
				if ($comma) 
2519
					$pfq_rule .= " ,";
2520
				$comma = 1;
2521
				$pfq_rule .= " ecn ";
2522
			}
2523
			$tmpvalue = trim($this->GetDefault());
2524
			if (!empty($tmpvalue)) {
2525
				if ($comma)
2526
					$pfq_rule .= " ,";
2527
				$comma = 1;
2528
				$pfq_rule .= " default ";
2529
			}
2530
			$tmpvalue = trim($this->GetBuckets());
2531
			if (!empty($tmpvalue)) {
2532
				if ($comma)
2533
					$pfq_rule .= ", ";
2534
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2535
			}
2536
			$tmpvalue = trim($this->GetHogs());
2537
			if (!empty($tmpvalue)) {
2538
				if ($comma)
2539
					$pfq_rule .= ", ";
2540
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2541
			}
2542
				$pfq_rule .= " ) ";
2543
		} 
2544

    
2545
		$pfq_rule .= " \n";
2546
		return $pfq_rule;
2547
	}
2548

    
2549
	function build_form() {
2550
		$form = parent::build_form();
2551
		$form .= "<tr>";
2552
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2553
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2554
		if ($this->GetBandwidth() > 0)
2555
			$form .= htmlspecialchars($this->GetBandwidth());
2556
		$form .= "\">";
2557
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2558
		$form .= "<option value=\"Gb\"";
2559
		if ($this->GetBwscale() == "Gb")
2560
			$form .= " selected=\"yes\"";
2561
		$form .= ">Gbit/s</option>";
2562
		$form .= "<option value=\"Mb\"";
2563
		if ($this->GetBwscale() == "Mb")
2564
			$form .= " selected=\"yes\"";
2565
		$form .= ">Mbit/s</option>";
2566
		$form .= "<option value=\"Kb\"";
2567
		if ($this->GetBwscale() == "Kb")
2568
			$form .= " selected=\"yes\"";
2569
		$form .= ">Kbit/s</option>";
2570
		$form .= "<option value=\"\"";
2571
		if ($this->GetBwscale() == "b")
2572
			$form .= " selected=\"yes\"";
2573
		$form .= ">Bit/s</option>";
2574
		$form .= "<option value=\"%\"";
2575
		if ($this->GetBwscale() == "%")
2576
			$form .= " selected=\"yes\"";
2577
		$form .= ">%</option>";
2578
		$form .= "</select> <br>";
2579
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2580
		$form .= "</span></td></tr>";
2581
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2582
		$form .= "<td class=\"vtable\"><table><tr><td>";
2583
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2584
		$tmpvalue = trim($this->GetBuckets());
2585
		if(!empty($tmpvalue)) 
2586
			$form .=  $this->GetBuckets();
2587
		$form .= "\"> Number of buckets available.<br></td></tr>";
2588
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2589
		$tmpvalue = trim($this->GetHogs());
2590
		if(!empty($tmpvalue)) 
2591
			$form .=  $this->GetHogs();
2592
		$form .= "\"> Bandwidth limit for hosts to not saturate link.<br></td></tr>";
2593
		$form .= "</table></td></tr>";
2594
		return $form;
2595
	}
2596

    
2597
	function update_altq_queue_data(&$data) { 
2598
		$this->ReadConfig($data);
2599
	}
2600

    
2601
	function wconfig() {
2602
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2603
		if (!is_array($cflink))
2604
			$cflink = array();
2605
		$cflink['interface'] = $this->GetInterface();
2606
		$cflink['qlimit'] = trim($this->GetQlimit());
2607
		if (empty($cflink['qlimit']))
2608
			unset($cflink['qlimit']);
2609
		$cflink['priority'] = trim($this->GetQpriority());
2610
		if (empty($cflink['priority']))
2611
			unset($cflink['priority']);
2612
		$cflink['name'] = $this->GetQname();
2613
		$cflink['description'] = trim($this->GetDescription());
2614
		if (empty($cflink['description']))
2615
			unset($cflink['description']);
2616
		$cflink['bandwidth'] = $this->GetBandwidth();
2617
		$cflink['bandwidthtype'] = $this->GetBwscale();
2618
		$cflink['enabled'] = $this->GetEnabled();
2619
		if (empty($cflink['enabled']))
2620
			unset($cflink['enabled']);
2621
		$cflink['default'] = trim($this->GetDefault());
2622
		if (empty($cflink['default']))
2623
			unset($cflink['default']);
2624
		$cflink['red'] = trim($this->GetRed());
2625
		if (empty($cflink['red']))
2626
			unset($cflink['red']);
2627
		$cflink['rio'] = trim($this->GetRio());
2628
		if (empty($cflink['rio']))
2629
			unset($cflink['rio']);
2630
		$cflink['ecn'] = trim($this->GetEcn());
2631
		if (empty($cflink['ecn']))
2632
			unset($cflink['ecn']);
2633
		$cflink['buckets'] = trim($this->GetBuckets());
2634
		if (empty($cflink['buckets']))
2635
			unset($cflink['buckets']);
2636
		$cflink['hogs'] = trim($this->GetHogs());
2637
		if (empty($cflink['hogs']))
2638
			unset($cflink['hogs']);
2639
	}
2640
}
2641

    
2642

    
2643
/*
2644
 * dummynet(4) wrappers.
2645
 */
2646

    
2647

    
2648
/*
2649
 * List of respective objects!
2650
 */
2651
$dummynet_pipe_list = array();
2652

    
2653
class dummynet_class {
2654
        var $qname;
2655
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2656
        var $qlimit;
2657
        var $description;
2658
	var $qenabled;
2659
	var $link;
2660
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2661
        var $plr;
2662

    
2663
        var $buckets;
2664
        /* mask parameters */
2665
        var $mask;
2666
        var $noerror;
2667

    
2668
        /* Accessor functions */
2669
        function SetLink($link) {
2670
                $this->link = $link;
2671
        }
2672
        function GetLink() {
2673
                return $this->link;
2674
        }
2675
	function Getmask() {
2676
		return $this->mask;
2677
	}
2678
	function SetMask($mask) {
2679
		$this->mask = $mask;
2680
	}
2681
	function &GetParent() {
2682
		return $this->qparent;
2683
	}
2684
	function SetParent(&$parent) {
2685
		$this->qparent = &$parent;
2686
	}
2687
        function GetEnabled() {
2688
                return $this->qenabled;
2689
        }
2690
        function SetEnabled($value) {
2691
                $this->qenabled = $value;
2692
        }
2693
	function CanHaveChildren() {
2694
		return false;
2695
        }
2696
	function CanBeDeleted() {
2697
                return true;
2698
        }
2699
        function GetQname() {
2700
                return $this->qname;
2701
        }
2702
        function SetQname($name) {
2703
                $this->qname = trim($name);
2704
        }
2705
        function GetQlimit() {
2706
                return $this->qlimit;
2707
        }
2708
        function SetQlimit($limit) {
2709
               	$this->qlimit = $limit;
2710
        }
2711
        function GetDescription() {
2712
                return $this->description;
2713
        }
2714
        function SetDescription($str) {
2715
                $this->description = trim($str);
2716
        }
2717
        function GetFirstime() {
2718
                return $this->firsttime;
2719
        }
2720
        function SetFirsttime($number) {
2721
                $this->firsttime = $number;
2722
        }
2723
        function GetBuckets() {
2724
                return $this->buckets;
2725
        }
2726
        function SetBuckets($buckets) {
2727
                $this->buckets = $buckets;
2728
        }
2729
	function SetNumber($number) {
2730
		$this->qnumber = $number;
2731
	}
2732
	function GetNumber() {
2733
		return $this->qnumber;
2734
	}
2735
        function GetPlr() {
2736
                return $this->plr;
2737
        }
2738
        function SetPlr($plr) {
2739
                $this->plr = $plr;
2740
        }
2741

    
2742
	function build_javascript() { return; } /* Do not remove */
2743

    
2744
	function validate_input($data, &$input_errors) {
2745
		$reqdfields[] = "bandwidth";
2746
		$reqdfieldsn[] = "Bandwidth";
2747
		$reqdfields[] = "bandwidthtype";
2748
		$reqdfieldsn[] = "Bandwidthtype";
2749
		$reqdfields[] = "name";
2750
		$reqdfieldsn[] = "Name";
2751
	
2752
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2753

    
2754
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2755
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2756
            		$input_errors[] = "Plr must be an integer between 1 and 100.";
2757
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2758
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2759
            		$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2760
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2761
            		$input_errors[] = "Queue limit must be an integer";
2762
        	if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2763
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2764
	}
2765
}
2766

    
2767
class dnpipe_class extends dummynet_class {
2768
        var $delay;
2769
	var $qbandwidth;
2770
	var $qbandwidthtype;
2771

    
2772
		/* This is here to help on form building and building rules/lists */
2773
        var $subqueues = array();
2774

    
2775
	function CanHaveChildren() {
2776
	        return true;
2777
        }
2778
	function SetDelay($delay) {
2779
		$this->delay = $delay;
2780
	}
2781
	function GetDelay() {
2782
		return $this->delay;
2783
	}
2784
	function GetBwscale() {
2785
                return $this->qbandwidthtype;
2786
        }
2787
        function SetBwscale($scale) {
2788
               	$this->qbandwidthtype = $scale;
2789
        }		
2790
	function delete_queue() {
2791
		cleanup_dnqueue_from_rules($this->GetQname());
2792
		foreach ($this->subqueues as $q)
2793
			$q->delete_queue();
2794
		unset_dn_object_by_reference($this->GetLink());
2795
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2796
        }
2797
        function GetBandwidth() {
2798
                return $this->qbandwidth;
2799
        }
2800
        function SetBandwidth($bandwidth) {
2801
                $this->qbandwidth = $bandwidth;
2802
        }
2803

    
2804
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2805

    
2806
		if (!is_array($this->subqueues))
2807
			$this->subqueues = array();
2808
			
2809
		$q =& new dnqueue_class();
2810
		$q->SetLink($path);
2811
		$q->SetEnabled("on");
2812
		$q->SetPipe($this->GetQname());
2813
		$q->SetParent(&$this);
2814
		$q->ReadConfig($queue);
2815
		$q->validate_input($queue, $input_errors);
2816
		if (count($input_errors))
2817
			return $q;
2818
		$this->subqueues[$q->GetQname()] = &$q;
2819
            
2820
		return $q;
2821
	}
2822

    
2823
	function &get_queue_list($q = null) {
2824
		$qlist = array();
2825

    
2826
		$qlist[$this->GetQname()] = $this->GetNumber();
2827
		if (is_array($this->subqueues)) {
2828
			foreach ($this->subqueues as $queue)
2829
				$queue->get_queue_list(&$qlist);
2830
		}
2831
		return $qlist;
2832
	}
2833
		
2834
        /*
2835
         * Should search even its children
2836
         */
2837
        function &find_queue($pipe, $qname) {
2838
                if ($qname == $this->GetQname()) 
2839
                        return $this;
2840
               	foreach ($this->subqueues as $q) {
2841
                       	$result =& $q->find_queue("", $qname);
2842
						if ($result)
2843
                       	        return $result;
2844
               	}
2845
        }
2846

    
2847
	function &find_parentqueue($pipe, $qname) {
2848
		return NULL;
2849
       	}
2850

    
2851
	function validate_input($data, &$input_errors) {
2852
		parent::validate_input($data, $input_errors);
2853

    
2854
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2855
       		     	$input_errors[] = "Bandwidth must be an integer.";
2856
		if ($data['delay'] && (!is_numeric($data['delay'])))
2857
            		$input_errors[] = "Delay must be an integer.";
2858
		}
2859

    
2860
	function ReadConfig(&$q) {
2861
           	$this->SetQname($q['name']);
2862
		$this->SetNumber($q['number']);
2863
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2864
			$this->SetBandwidth($q['bandwidth']);
2865
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2866
				$this->SetBwscale($q['bandwidthtype']);
2867
		}
2868
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2869
              		$this->SetQlimit($q['qlimit']);
2870
		if (isset($q['mask']) && $q['mask'] <> "")
2871
              		$this->SetMask($q['mask']);
2872
		if (isset($q['buckets']) && $q['buckets'] <> "")
2873
              		$this->SetBuckets($q['buckets']);
2874
            	if (isset($q['plr']) && $q['plr'] <> "")
2875
            		$this->SetPlr($q['plr']);
2876
		if (isset($q['delay']) && $q['delay'] <> "")
2877
            		$this->SetDelay($q['delay']);
2878
            	if (isset($q['description']) && $q['description'] <> "")
2879
			$this->SetDescription($q['description']);
2880
		$this->SetEnabled($q['enabled']);
2881

    
2882
        }
2883

    
2884
	function build_tree() {
2885
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2886
		$tree .= $this->GetQname() . "</a>";
2887
		if (is_array($this->subqueues)) {
2888
			$tree .= "<ul>";
2889
			foreach ($this->subqueues as $q)  {
2890
				$tree .= $q->build_tree();
2891
			}	
2892
			$tree .= "</ul>";
2893
		}
2894
		$tree .= "</li>";
2895
		
2896
		return $tree;
2897
	}
2898

    
2899
        function build_rules() {
2900
		if ($this->GetEnabled() == "")
2901
			return;
2902

    
2903
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2904
		if ($this->GetBandwidth() && $this->GetBwscale())
2905
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2906
		if ($this->GetQlimit())
2907
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2908
		if ($this->GetPlr())
2909
			$pfq_rule .= " plr " . $this->GetPlr();
2910
		if ($this->GetBuckets())
2911
			$pfq_rule .= " buckets " . $this->GetBuckets();
2912
		if ($this->GetDelay())
2913
			$pfq_rule .= " delay " . $this->GetDelay();
2914

    
2915
		$mask = $this->GetMask();
2916
		if (!empty($mask)) {
2917
			/* XXX TODO extend this to support more complicated masks */
2918
			switch ($mask) {
2919
			case 'srcaddress':
2920
				$pfq_rule .= " mask src-ip 0xffffffff ";
2921
				break;
2922
			case 'dstaddress':
2923
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2924
				break;
2925
			default:
2926
				break;
2927
			}
2928
			$pfq_rule .= "\n";
2929

    
2930
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2931
       			        foreach ($this->subqueues as $q)
2932
				$pfq_rule .= $q->build_rules();
2933
               		}
2934
    		}            
2935
		$pfq_rule .= " \n";
2936

    
2937
		return $pfq_rule;
2938
        }
2939

    
2940
	function update_dn_data(&$data) { 
2941
		$this->ReadConfig($data);
2942
	}
2943

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

    
3021
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3022
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3023
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3024
		$form .= $this->GetDelay() . "\">";
3025
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3026
		$form .= "should specify 0 here (or leave the field empty)</span>";
3027
		$form .= "</td></tr><br/>";
3028
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3029
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3030
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3031
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3032
		$form .= $this->GetPlr() . "\">";
3033
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3034
        	$form .= "should specify 0 here (or leave the field empty).";
3035
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3036
		$form .= "</td></tr>";
3037
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3038
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3039
		$form .= "<td class=\"vncellreq\">";
3040
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3041
		$form .= $this->GetQlimit() . "\">";
3042
		$form .= "&nbsp;slots<br>";
3043
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3044
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
3045
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
3046
		$form .= "are delivered to their destination.</span>";
3047
		$form .= "</td></tr>";
3048
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3049
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3050
                $form .= "<td class=\"vncellreq\">";
3051
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3052
                $form .= $this->GetBuckets() . "\">";
3053
                $form .= "&nbsp;slots<br>";
3054
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3055
                $form .= "should leave the field empty. It increases the hash size set.";
3056
                $form .= "</td></tr>";
3057

    
3058
		return $form;
3059
			
3060
		}
3061

    
3062
	function wconfig() {
3063
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3064
            	if (!is_array($cflink))
3065
            		$cflink = array();
3066
		$cflink['name'] = $this->GetQname();
3067
		$cflink['number'] = $this->GetNumber();
3068
            	$cflink['qlimit'] = $this->GetQlimit();
3069
            	$cflink['plr'] = $this->GetPlr();
3070
            	$cflink['description'] = $this->GetDescription();
3071
		$cflink['bandwidth'] = $this->GetBandwidth();
3072
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3073
		$cflink['enabled'] = $this->GetEnabled();
3074
		$cflink['buckets'] = $this->GetBuckets();
3075
		$cflink['mask'] = $this->GetMask();
3076
		$cflink['delay'] = $this->GetDelay();
3077
	}
3078

    
3079
}
3080

    
3081
class dnqueue_class extends dummynet_class {
3082
        var $pipeparent;
3083
        var $weight;
3084

    
3085
        function GetWeight() {
3086
                return $this->weight;
3087
        }
3088
        function SetWeight($weight) {
3089
                $this->weight = $weight;
3090
        }
3091
	function GetPipe() {
3092
		return $this->pipeparent;
3093
	}
3094
	function SetPipe($pipe) {
3095
		$this->pipeparent = $pipe;
3096
	}
3097

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

    
3101
	function delete_queue() {
3102
		cleanup_dnqueue_from_rules($this->GetQname());
3103
		unset_dn_object_by_reference($this->GetLink());
3104
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3105
        }
3106

    
3107
	function validate_input($data, &$input_errors) {
3108
		parent::validate_input($data, $input_errors);
3109

    
3110
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3111
			($data['weight'] < 1 && $data['weight'] > 100))) 
3112
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3113
	}
3114

    
3115
        /*
3116
         * Should search even its children
3117
         */
3118
        function &find_queue($pipe, $qname) {
3119
                if ($qname == $this->GetQname()) 
3120
                	return $this;
3121
		else
3122
			return NULL;
3123
        }
3124

    
3125
	function &find_parentqueue($pipe, $qname) {
3126
		return $this->qparent;
3127
        }
3128

    
3129
        function &get_queue_list(&$qlist) {
3130
		if ($this->GetEnabled() == "")
3131
			return;
3132
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3133
        }		
3134

    
3135
	function ReadConfig(&$q) {
3136
          	$this->SetQname($q['name']);
3137
		$this->SetNumber($q['number']);
3138
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3139
       		       	$this->SetQlimit($q['qlimit']);
3140
		if (isset($q['mask']) && $q['mask'] <> "")
3141
              		$this->SetMask($q['mask']);
3142
       		if (isset($q['weight']) && $q['weight'] <> "")
3143
            		$this->SetWeight($q['weight']);
3144
            	if (isset($q['description']) && $q['description'] <> "")
3145
			$this->SetDescription($q['description']);
3146
		$this->SetEnabled($q['enabled']);
3147
        }
3148

    
3149
	function build_tree() {
3150
		$parent =& $this->GetParent();
3151
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3152
		$tree .= $this->GetQname() . "</a>";
3153
		$tree .= "</li>";
3154
		
3155
		return $tree;
3156
	}
3157

    
3158
        function build_rules() {
3159
		if ($this->GetEnabled() == "")
3160
			return; 
3161

    
3162
		$parent =& $this->GetParent();
3163
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3164
		if ($this->GetQlimit())
3165
                    	$pfq_rule .= " queue " . $this->GetQimit();
3166
		if ($this->GetWeight())
3167
			$pfq_rule .= " weight " . $this->GetWeight();
3168
		if ($this->GetBuckets())
3169
			$pfq_rule .= " buckets " . $this->GetBuckets();
3170
		$mask = $this->GetMask();
3171
		if (!empty($mask)) {
3172
			/* XXX TODO extend this to support more complicated masks */
3173
			switch ($mask) {
3174
			case 'srcaddress':
3175
				$pfq_rule .= " mask src-ip 0xffffffff ";
3176
				break;
3177
			case 'dstaddress':
3178
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3179
				break;
3180
			default:
3181
				break;
3182
			}
3183
			$pfq_rule .= "\n";
3184
		}
3185

    
3186
		return $pfq_rule;
3187
	}
3188

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

    
3279
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3280
		$form .= " value=\"" . $this->GetPipe() . "\">";
3281

    
3282
		return $form;
3283
			
3284
	}
3285

    
3286
        function update_dn_data(&$data) { 
3287
		$this->ReadConfig($data);
3288
	}
3289

    
3290
	function wconfig() {
3291
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3292
            	if (!is_array($cflink))
3293
            		$cflink = array();
3294
		$cflink['name'] = $this->GetQname();
3295
		$cflink['number'] = $this->GetNumber();
3296
            	$cflink['qlimit'] = $this->GetQlimit();
3297
            	$cflink['description'] = $this->GetDescription();
3298
		$cflink['weight'] = $this->GetWeight();
3299
		$cflink['enabled'] = $this->GetEnabled();
3300
		$cflink['buckets'] = $this->GetBuckets();
3301
		$cflink['mask'] = $this->GetMask();
3302
	}
3303
}
3304

    
3305
// List of layer7 objects
3306
$layer7_rules_list = array();
3307

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

    
3505
class l7rule {
3506
    
3507
    var $rprotocol; //protocol
3508
    var $rstructure; //action, limiter, queue
3509
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3510
    
3511
    //Auxiliary Functions
3512
    
3513
    function GetRProtocol() {
3514
        return $this->rprotocol;
3515
    }
3516
    function SetRProtocol($rprotocol) {
3517
        $this->rprotocol = $rprotocol;
3518
    }
3519
    function GetRStructure() {
3520
        return $this->rstructure;
3521
    }
3522
    function SetRStructure($rstructure) {
3523
        $this->rstructure = $rstructure;
3524
    }
3525
    function GetRBehaviour() {
3526
        return $this->rbehaviour;
3527
    }
3528
    function SetRBehaviour($rbehaviour) {
3529
        $this->rbehaviour = $rbehaviour;
3530
    }
3531
    
3532
    //XXX Do we need to test any particularity for AltQ queues?
3533
    function build_rules() {
3534
	global $dummynet_pipe_list;
3535
	switch ($this->GetRStructure()) {
3536
		case "limiter":
3537
			read_dummynet_config();
3538
			$dn_list =& get_unique_dnqueue_list();
3539
			$found = false;
3540
			if(is_array($dn_list)) {
3541
				foreach($dn_list as $key => $value) {
3542
					if($key == $this->GetRBehaviour()) {
3543
						if($value[0] == "?")
3544
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3545
						else
3546
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3547
						$found = true;
3548
					}
3549
					if($found)
3550
						break;
3551
				}
3552
			}
3553
			break;
3554
		default: //This is for action and for altq
3555
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3556
			break;
3557
	}
3558
        return $l7rule;
3559
    }
3560
}
3561

    
3562
/*
3563
 * This function allows to return an array with all the used divert socket ports
3564
 */
3565
function get_divert_ports() {
3566
    global $layer7_rules_list;
3567
    $dports = array();
3568
    
3569
    foreach($layer7_rules_list as $l7r)
3570
        $dports[] = $l7r->GetRPort();
3571
    
3572
    return $dports;
3573
}
3574

    
3575
function &get_l7c_reference_to_me_in_config(&$name) {
3576
	global $config;
3577
	
3578
	$ptr = NULL;
3579
	
3580
	if(is_array($config['l7shaper']['container'])) {
3581
		foreach($config['l7shaper']['container'] as $key => $value) {
3582
			if($value['name'] == $name)
3583
				$ptr =& $config['l7shaper']['container'][$key];
3584
		}
3585
	}	
3586
	return $ptr;
3587
// $ptr can be null. has to be checked later
3588
}
3589

    
3590
function unset_l7_object_by_reference(&$name) {
3591
	global $config;
3592
        
3593
	if(is_array($config['l7shaper']['container'])) {
3594
		foreach($config['l7shaper']['container'] as $key => $value) {
3595
			if($value['name'] == $name) {
3596
				unset($config['l7shaper']['container'][$key]['l7rules']);
3597
				unset($config['l7shaper']['container'][$key]);
3598
				break;
3599
			}
3600
		}
3601
	}
3602
}
3603

    
3604
function read_layer7_config() {
3605
    global $layer7_rules_list, $config;
3606
    
3607
    $l7cs = &$config['l7shaper']['container'];
3608
    
3609
    $layer7_rules_list = array();
3610
    
3611
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3612
	return;
3613
    
3614
    foreach ($l7cs as $conf) {
3615
	if (empty($conf['name']))
3616
		continue; /* XXX: grrrrrr at php */ 
3617
        $root =& new layer7();
3618
        $root->ReadConfig($conf['name'],$conf);
3619
        $layer7_rules_list[$root->GetRName()] = &$root;
3620
    }
3621
}
3622

    
3623
function generate_layer7_files() {
3624
    global $layer7_rules_list, $g;
3625
    
3626
    read_layer7_config();
3627
    
3628
    if (!empty($layer7_rules_list)) {
3629
	if (!is_module_loaded("ipdivert.ko"))
3630
		mwexec("/sbin/kldload ipdivert.ko");
3631

    
3632
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3633
    }
3634
    
3635
    foreach($layer7_rules_list as $l7rules) {
3636
        if($l7rules->GetREnabled()) {
3637
            $filename = $l7rules->GetRName() . ".l7";
3638
            $path = "{$g['tmp_path']}/" . $filename;
3639
        
3640
            $rules = $l7rules->build_l7_rules();
3641
        
3642
            $fp = fopen($path,'w');
3643
            fwrite($fp,$rules);
3644
            fclose($fp);
3645
        }
3646
    }
3647
}
3648

    
3649
function layer7_start_l7daemon() {
3650
    global $layer7_rules_list, $g;
3651

    
3652
    /*
3653
     * XXX: ermal - Needed ?!
3654
     * read_layer7_config();
3655
     */
3656

    
3657
    foreach($layer7_rules_list as $l7rules) {
3658
        if($l7rules->GetREnabled()) {
3659
            $filename = $l7rules->GetRName() . ".l7";
3660
            $path = "{$g['tmp_path']}/" . $filename;
3661

    
3662
	    unset($l7pid);
3663
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3664
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3665
	    if (count($l7pid) > 0) {
3666
		log_error("Sending HUP signal to {$l7pid[0]}");
3667
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3668
	    } else {
3669
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3670
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3671
		mwexec_bg($ipfw_classifyd_init);
3672
	    }
3673
        }
3674
    }
3675
}
3676

    
3677
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3678
function generate_protocols_array() {
3679
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3680
	$protocols_new = array();
3681
	if(is_array($protocols)) {
3682
		foreach($protocols as $key => $proto) {
3683
			if (strstr($proto, ".pat"))
3684
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3685
		}
3686
		sort($protocols_new);
3687
	}		
3688
	return $protocols_new;
3689
}
3690

    
3691
function get_l7_unique_list() {
3692
	global $layer7_rules_list;
3693
	
3694
	$l7list = array();
3695
	if(is_array($layer7_rules_list)) 
3696
		foreach($layer7_rules_list as $l7c)
3697
			if($l7c->GetREnabled())
3698
				$l7list[] = $l7c->GetRName();
3699
	
3700
	return $l7list;
3701
}
3702

    
3703
// Disable a removed l7 container from the filter
3704
function cleanup_l7_from_rules(&$name) {
3705
	global $config;
3706

    
3707
	if(is_array($config['filter']['rule']))
3708
		foreach ($config['filter']['rule'] as $key => $rule) {
3709
			if ($rule['l7container'] == $name)
3710
				unset($config['filter']['rule'][$key]['l7container']);
3711
		}
3712
}
3713

    
3714
function get_dummynet_name_list() {
3715
	
3716
	$dn_name_list =& get_unique_dnqueue_list();
3717
	$dn_name = array();
3718
	if(is_array($dn_name_list))
3719
		foreach($dn_name_list as $key => $value)
3720
			$dn_name[] = $key;
3721
	
3722
	return $dn_name;
3723
	
3724
}
3725

    
3726
function get_altq_name_list() {
3727
	$altq_name_list =& get_unique_queue_list();
3728
	$altq_name = array();
3729
	if(is_array($altq_name_list))
3730
		foreach($altq_name_list as $key => $aqobj)
3731
			$altq_name[] = $key;
3732
		
3733
	return $altq_name;
3734
}
3735

    
3736
/*
3737
 * XXX: TODO Make a class shaper to hide all these function
3738
 * from the global namespace.
3739
 */
3740

    
3741
/* 
3742
 * This is a layer violation but for now there is no way 
3743
 * i can find to properly do this with PHP.
3744
 */
3745
function altq_set_default_queue($interface, $value) {
3746
	global $altq_list_queues;
3747
		
3748
	$altq_tmp =& $altq_list_queues[$interface];
3749
	if ($altq_tmp) {
3750
		if ($value) {
3751
			$altq_tmp->SetDefaultQueuePresent("true");
3752
		}
3753
		else {
3754
			$altq_tmp->SetDefaultQueuePresent("false");
3755
		}
3756
	}
3757
}
3758

    
3759
function altq_get_default_queue($interface) {
3760
	global $altq_list_queues;
3761

    
3762
	$altq_tmp = $altq_list_queues[$interface];
3763
	if ($altq_tmp)  
3764
		return $altq_tmp->GetDefaultQueuePresent(); 
3765
}
3766

    
3767
function altq_check_default_queues() {
3768
	global $altq_list_queues;
3769

    
3770
	$count = 0;
3771
	if (is_array($altq_list_queues)) {
3772
		foreach($altq_list_queues as $altq) {
3773
			if ($altq->GetDefaultQueuePresent())
3774
				$count++;
3775
		}
3776
	}
3777
	else  $count++;;
3778
	
3779
	return 0;
3780
}
3781

    
3782
function &get_unique_queue_list() {
3783
	global $altq_list_queues;
3784
	
3785
	$qlist = array();
3786
	if (is_array($altq_list_queues)) {
3787
		foreach ($altq_list_queues as $altq) {
3788
			if ($altq->GetEnabled() == "")
3789
				continue;
3790
			$tmplist =& $altq->get_queue_list();
3791
			foreach ($tmplist as $qname => $link) {
3792
				if ($link->GetEnabled() <> "")
3793
					$qlist[$qname] = $link;	
3794
			}
3795
		}
3796
	}
3797
	return $qlist;
3798
}
3799

    
3800
function &get_unique_dnqueue_list() {
3801
	global $dummynet_pipe_list;
3802
	
3803
	$qlist = array();
3804
	if (is_array($dummynet_pipe_list)) {
3805
		foreach ($dummynet_pipe_list as $dn) {
3806
			if ($dn->GetEnabled() == "")
3807
				continue;
3808
			$tmplist =& $dn->get_queue_list();
3809
			foreach ($tmplist as $qname => $link) {
3810
				$qlist[$qname] = $link;	
3811
			}
3812
		}
3813
	}
3814
	return $qlist;
3815
}
3816

    
3817
function ref_on_altq_queue_list($parent, $qname) {
3818
	if (isset($GLOBALS['queue_list'][$qname]))
3819
		$GLOBALS['queue_list'][$qname]++;
3820
	else
3821
		$GLOBALS['queue_list'][$qname] = 1;
3822

    
3823
	unref_on_altq_queue_list($parent);
3824
}
3825

    
3826
function unref_on_altq_queue_list($qname) {
3827
	$GLOBALS['queue_list'][$qname]--;
3828
	if ($GLOBALS['queue_list'][$qname] <= 1)
3829
		unset($GLOBALS['queue_list'][$qname]);	
3830
}
3831

    
3832
function read_altq_config() {
3833
	global $altq_list_queues, $config;
3834
	$path = array();
3835
	
3836
	if (!is_array($config['shaper']))
3837
		$config['shaper'] = array();
3838
	if (!is_array($config['shaper']['queue']))
3839
		$config['shaper']['queue'] = array();
3840
	$a_int = &$config['shaper']['queue'];
3841

    
3842
	$altq_list_queues = array();
3843
	
3844
	if (!is_array($config['shaper']['queue']))
3845
		return;
3846

    
3847
	foreach ($a_int as $key => $conf) {
3848
		$int = $conf['interface'];
3849
		$root =& new altq_root_queue();
3850
		$root->SetInterface($int);
3851
		$altq_list_queues[$root->GetInterface()] = &$root;
3852
		$root->ReadConfig($conf);
3853
		array_push($path, $key);
3854
		$root->SetLink($path);
3855
		if (is_array($conf['queue'])) {
3856
			foreach ($conf['queue'] as $key1 => $q) {
3857
				array_push($path, $key1);
3858
				/* 
3859
				 * XXX: we compeletely ignore errors here but anyway we must have 
3860
				 *	checked them before so no harm should be come from this.
3861
				 */
3862
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3863
				array_pop($path);
3864
			} 	
3865
		}
3866
		array_pop($path);
3867
	}
3868
}
3869

    
3870
function read_dummynet_config() {
3871
	global $dummynet_pipe_list, $config;
3872
	$path = array();
3873
	$dnqueuenumber = 1;
3874
	$dnpipenumber = 1;
3875

    
3876
	if (!is_array($config['dnshaper']))
3877
		$config['dnshaper'] = array();
3878
	if (!is_array($config['dnshaper']['queue']))
3879
		$config['dnshaper']['queue'] = array();
3880
	$a_int = &$config['dnshaper']['queue'];
3881

    
3882
	$dummynet_pipe_list = array();
3883
	
3884
	if (!is_array($config['dnshaper']['queue'])
3885
		|| !count($config['dnshaper']['queue']))
3886
		return;
3887

    
3888
	foreach ($a_int as $key => $conf) {
3889
		if (empty($conf['name']))
3890
			continue; /* XXX: grrrrrr at php */ 
3891
		$root =& new dnpipe_class();
3892
		$root->ReadConfig($conf);
3893
		$root->SetNumber($dnpipenumber);	
3894
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3895
		array_push($path, $key);
3896
		$root->SetLink($path);
3897
		if (is_array($conf['queue'])) {
3898
			foreach ($conf['queue'] as $key1 => $q) {
3899
				array_push($path, $key1);
3900
				/* XXX: We cheat a little here till a better way is found. */
3901
				$q['number'] = $dnqueuenumber;
3902
				/* 
3903
				 * XXX: we compeletely ignore errors here but anyway we must have 
3904
				 *	checked them before so no harm should be come from this.
3905
				 */	
3906
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3907
				array_pop($path);
3908

    
3909
				$dnqueuenumber++;
3910
			} 	
3911
		}
3912
		array_pop($path);
3913
			
3914
		$dnpipenumber++;
3915
	}
3916
}
3917

    
3918
function get_interface_list_to_show() {
3919
	global $altq_list_queues, $config;
3920
	global $shaperIFlist;
3921

    
3922
	$tree = "";
3923
	foreach ($shaperIFlist as $shif => $shDescr) {
3924
		if ($altq_list_queues[$shif]) {
3925
			continue;
3926
		} else  {
3927
			if (!is_altq_capable(get_real_interface($shif)))
3928
				continue;
3929
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3930
		}
3931
	}
3932
	
3933
	return $tree;
3934
}
3935

    
3936
function filter_generate_altq_queues() {
3937
	global $altq_list_queues;
3938
	
3939
	read_altq_config();
3940

    
3941
	$altq_rules = "";
3942
	foreach ($altq_list_queues as $altq) 
3943
		$altq_rules .= $altq->build_rules();
3944

    
3945
	return $altq_rules;
3946
}
3947

    
3948
function filter_generate_dummynet_rules() {
3949
	global $g, $dummynet_pipe_list;
3950
	
3951
	read_dummynet_config();
3952
	
3953
	if (!empty($dummynet_pipe_list)) {
3954
		if (!is_module_loaded("dummynet.ko"))
3955
			mwexec("/sbin/kldload dummynet");
3956
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
3957
		//mwexec("pfctl -F dummynet");
3958
	}
3959

    
3960
	$dn_rules = "";
3961
	foreach ($dummynet_pipe_list as $dn) 
3962
		$dn_rules .= $dn->build_rules();
3963

    
3964
	if (!empty($dn_rules)) {
3965
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
3966
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
3967
	}
3968
	//return $dn_rules;
3969
}
3970

    
3971
function build_iface_without_this_queue($iface, $qname) {
3972
	global $g, $altq_list_queues;
3973

    
3974
	$altq =& $altq_list_queues[$iface];
3975
				if ($altq)
3976
						$scheduler = ": " . $altq->GetScheduler();
3977
	$form = "<tr><td width=\"20%\" >";
3978
	$form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
3979
		$form .= "</td></tr>";
3980
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
3981
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
3982
		$form .= $iface . "&queue=". $qname . "&action=add\">";
3983
		$form .= "<img src=\"";
3984
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
3985
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
3986
		$form .= " Clone shaper/queue on this interface</a></td></tr>";
3987

    
3988
		return $form;
3989

    
3990
}
3991

    
3992

    
3993
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3994
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
3995
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3996
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3997
$default_shaper_msg .= " </p></strong></span>";
3998
$default_shaper_msg .= "</td></tr>";
3999

    
4000
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
4001
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
4002
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
4003
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
4004
$dn_default_shaper_msg .= " </p></strong></span>";
4005
$dn_default_shaper_msg .= "</td></tr>";
4006

    
4007

    
4008

    
4009
?>
(38-38/54)