Project

General

Profile

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

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

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

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

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

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

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

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

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

    
49
	return $ptr;
50
}
51

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

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

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

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

    
72
	return $ptr;
73
}
74

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
449
		return $q;
450
	}
451

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

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

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

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

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

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

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

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

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

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

    
602
		return $form;
603

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

    
691

    
692
		return $form;
693
	}
694

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

    
723
}
724

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

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

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

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

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

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

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

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

    
905
	 }
906

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

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

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

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

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

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

    
1016
	}
1017

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

    
1036
		$tree .= "</li>"; 
1037

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

    
1085
		$pfq_rule .= " \n";
1086

    
1087
		return $pfq_rule;
1088
	}
1089

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

    
1166
		return $form;
1167
	}
1168

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

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

    
1205
	}
1206

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

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

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

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

    
1349
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1350

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

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

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

    
1389
        function copy_queue($interface, &$cflink) {
1390

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1624
	}
1625

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

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

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

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

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

    
1782
		 $pfq_rule .= " \n";
1783
			
1784
		return $pfq_rule;
1785
	}
1786

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

    
1826
		return $javascript;
1827
	}
1828

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

    
1930
		return $form;
1931
	}
1932

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

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

    
2041
class cbq_queue extends priq_queue {
2042
	var $qborrow = "";
2043

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

    
2054
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2055

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

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

    
2090
		return $q;
2091
	}
2092

    
2093
	function copy_queue($interface, &$cflink) {
2094

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

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

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

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

    
2185

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

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

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

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

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

    
2303
		$pfq_rule .= " \n";
2304
		return $pfq_rule;
2305
	}
2306

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

    
2345
		return $form;
2346
	}
2347

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

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

    
2390
class fairq_queue extends priq_queue {
2391
	var $hogs;
2392
	var $buckets;
2393

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

    
2410

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

    
2436
	function find_parentqueue($interface, $qname) { return; }
2437

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

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

    
2461

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

    
2465

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

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

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

    
2571
		$pfq_rule .= " \n";
2572
		return $pfq_rule;
2573
	}
2574

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

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

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

    
2668

    
2669
/*
2670
 * dummynet(4) wrappers.
2671
 */
2672

    
2673

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

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

    
2689
        var $buckets;
2690
        /* mask parameters */
2691
        var $mask;
2692
        var $noerror;
2693

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

    
2768
	function build_javascript() { return; } /* Do not remove */
2769

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

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

    
2795
class dnpipe_class extends dummynet_class {
2796
        var $delay;
2797
	var $qbandwidth;
2798
	var $qbandwidthtype;
2799

    
2800
		/* This is here to help on form building and building rules/lists */
2801
        var $subqueues = array();
2802

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

    
2832
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2833

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

    
2853
	function &get_queue_list($q = null) {
2854
		$qlist = array();
2855

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

    
2877
	function &find_parentqueue($pipe, $qname) {
2878
		return NULL;
2879
       	}
2880

    
2881
	function validate_input($data, &$input_errors) {
2882
		parent::validate_input($data, $input_errors);
2883

    
2884
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2885
       		     	$input_errors[] = "Bandwidth must be an integer.";
2886
		if ($data['delay'] && (!is_numeric($data['delay'])))
2887
            		$input_errors[] = "Delay must be an integer.";
2888
		}
2889

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

    
2930
        }
2931

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

    
2947
        function build_rules() {
2948
		if ($this->GetEnabled() == "")
2949
			return;
2950

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

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

    
2978
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2979
       			        foreach ($this->subqueues as $q)
2980
				$pfq_rule .= $q->build_rules();
2981
               		}
2982
    		}            
2983
		$pfq_rule .= " \n";
2984

    
2985
		return $pfq_rule;
2986
        }
2987

    
2988
	function update_dn_data(&$data) { 
2989
		$this->ReadConfig($data);
2990
	}
2991

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

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

    
3108
		return $form;
3109
			
3110
		}
3111

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

    
3129
}
3130

    
3131
class dnqueue_class extends dummynet_class {
3132
        var $pipeparent;
3133
        var $weight;
3134

    
3135
        function GetWeight() {
3136
                return $this->weight;
3137
        }
3138
        function SetWeight($weight) {
3139
                $this->weight = $weight;
3140
        }
3141
	function GetPipe() {
3142
		return $this->pipeparent;
3143
	}
3144
	function SetPipe($pipe) {
3145
		$this->pipeparent = $pipe;
3146
	}
3147

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

    
3151
	function delete_queue() {
3152
		cleanup_dnqueue_from_rules($this->GetQname());
3153
		unset_dn_object_by_reference($this->GetLink());
3154
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3155
        }
3156

    
3157
	function validate_input($data, &$input_errors) {
3158
		parent::validate_input($data, $input_errors);
3159

    
3160
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3161
			($data['weight'] < 1 && $data['weight'] > 100))) 
3162
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3163
	}
3164

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

    
3175
	function &find_parentqueue($pipe, $qname) {
3176
		return $this->qparent;
3177
        }
3178

    
3179
        function &get_queue_list(&$qlist) {
3180
		if ($this->GetEnabled() == "")
3181
			return;
3182
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3183
        }		
3184

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

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

    
3222
        function build_rules() {
3223
		if ($this->GetEnabled() == "")
3224
			return; 
3225

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

    
3250
		return $pfq_rule;
3251
	}
3252

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

    
3345
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3346
		$form .= " value=\"" . $this->GetPipe() . "\">";
3347

    
3348
		return $form;
3349
			
3350
	}
3351

    
3352
        function update_dn_data(&$data) { 
3353
		$this->ReadConfig($data);
3354
	}
3355

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

    
3371
// List of layer7 objects
3372
$layer7_rules_list = array();
3373

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

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

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

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

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

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

    
3689
function generate_layer7_files() {
3690
    global $layer7_rules_list, $g;
3691
    
3692
    read_layer7_config();
3693
    
3694
    if (!empty($layer7_rules_list)) {
3695
	if (!is_module_loaded("ipdivert.ko"))
3696
		mwexec("/sbin/kldload ipdivert.ko");
3697

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

    
3715
function layer7_start_l7daemon() {
3716
    global $layer7_rules_list, $g;
3717

    
3718
    /*
3719
     * XXX: ermal - Needed ?!
3720
     * read_layer7_config();
3721
     */
3722

    
3723
    foreach($layer7_rules_list as $l7rules) {
3724
        if($l7rules->GetREnabled()) {
3725
            $filename = $l7rules->GetRName() . ".l7";
3726
            $path = "{$g['tmp_path']}/" . $filename;
3727

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

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

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

    
3769
// Disable a removed l7 container from the filter
3770
function cleanup_l7_from_rules(&$name) {
3771
	global $config;
3772

    
3773
	if(is_array($config['filter']['rule']))
3774
		foreach ($config['filter']['rule'] as $key => $rule) {
3775
			if ($rule['l7container'] == $name)
3776
				unset($config['filter']['rule'][$key]['l7container']);
3777
		}
3778
}
3779

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

    
3792
function get_altq_name_list() {
3793
	$altq_name_list =& get_unique_queue_list();
3794
	$altq_name = array();
3795
	if(is_array($altq_name_list))
3796
		foreach($altq_name_list as $key => $aqobj)
3797
			$altq_name[] = $key;
3798
		
3799
	return $altq_name;
3800
}
3801

    
3802
/*
3803
 * XXX: TODO Make a class shaper to hide all these function
3804
 * from the global namespace.
3805
 */
3806

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

    
3825
function altq_get_default_queue($interface) {
3826
	global $altq_list_queues;
3827

    
3828
	$altq_tmp = $altq_list_queues[$interface];
3829
	if ($altq_tmp)  
3830
		return $altq_tmp->GetDefaultQueuePresent(); 
3831
}
3832

    
3833
function altq_check_default_queues() {
3834
	global $altq_list_queues;
3835

    
3836
	$count = 0;
3837
	if (is_array($altq_list_queues)) {
3838
		foreach($altq_list_queues as $altq) {
3839
			if ($altq->GetDefaultQueuePresent())
3840
				$count++;
3841
		}
3842
	}
3843
	else  $count++;;
3844
	
3845
	return 0;
3846
}
3847

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

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

    
3883
function ref_on_altq_queue_list($parent, $qname) {
3884
	if (isset($GLOBALS['queue_list'][$qname]))
3885
		$GLOBALS['queue_list'][$qname]++;
3886
	else
3887
		$GLOBALS['queue_list'][$qname] = 1;
3888

    
3889
	unref_on_altq_queue_list($parent);
3890
}
3891

    
3892
function unref_on_altq_queue_list($qname) {
3893
	$GLOBALS['queue_list'][$qname]--;
3894
	if ($GLOBALS['queue_list'][$qname] <= 1)
3895
		unset($GLOBALS['queue_list'][$qname]);	
3896
}
3897

    
3898
function read_altq_config() {
3899
	global $altq_list_queues, $config;
3900
	$path = array();
3901
	
3902
	if (!is_array($config['shaper']))
3903
		$config['shaper'] = array();
3904
	if (!is_array($config['shaper']['queue']))
3905
		$config['shaper']['queue'] = array();
3906
	$a_int = &$config['shaper']['queue'];
3907

    
3908
	$altq_list_queues = array();
3909
	
3910
	if (!is_array($config['shaper']['queue']))
3911
		return;
3912

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

    
3936
function read_dummynet_config() {
3937
	global $dummynet_pipe_list, $config;
3938
	$path = array();
3939
	$dnqueuenumber = 1;
3940
	$dnpipenumber = 1;
3941

    
3942
	if (!is_array($config['dnshaper']))
3943
		$config['dnshaper'] = array();
3944
	if (!is_array($config['dnshaper']['queue']))
3945
		$config['dnshaper']['queue'] = array();
3946
	$a_int = &$config['dnshaper']['queue'];
3947

    
3948
	$dummynet_pipe_list = array();
3949
	
3950
	if (!is_array($config['dnshaper']['queue'])
3951
		|| !count($config['dnshaper']['queue']))
3952
		return;
3953

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

    
3975
				$dnqueuenumber++;
3976
			} 	
3977
		}
3978
		array_pop($path);
3979
			
3980
		$dnpipenumber++;
3981
	}
3982
}
3983

    
3984
function get_interface_list_to_show() {
3985
	global $altq_list_queues, $config;
3986
	global $shaperIFlist;
3987

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

    
4002
function filter_generate_altq_queues() {
4003
	global $altq_list_queues;
4004
	
4005
	read_altq_config();
4006

    
4007
	$altq_rules = "";
4008
	foreach ($altq_list_queues as $altq) 
4009
		$altq_rules .= $altq->build_rules();
4010

    
4011
	return $altq_rules;
4012
}
4013

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

    
4026
	$dn_rules = "";
4027
	foreach ($dummynet_pipe_list as $dn) 
4028
		$dn_rules .= $dn->build_rules();
4029

    
4030
	if (!empty($dn_rules)) {
4031
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
4032
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
4033
	}
4034
	//return $dn_rules;
4035
}
4036

    
4037
function build_iface_without_this_queue($iface, $qname) {
4038
	global $g, $altq_list_queues;
4039

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

    
4054
		return $form;
4055

    
4056
}
4057

    
4058

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

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

    
4073
?>
(45-45/61)