Project

General

Profile

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

    
28
/* include all configuration functions */
29
require_once("functions.inc");
30
require_once("pkg-utils.inc");
31
require_once("notices.inc");
32
//require_once("guiconfig.inc");
33

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

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

    
45
	return $ptr;
46
}
47
function unset_object_by_reference(&$mypath) {
48
	global $config;
49

    
50
		$ptr =& $config['shaper'];
51
		for ($i = 0; $i < count($mypath) - 1; $i++) {
52
				$ptr =& $ptr['queue'][$mypath[$i]];
53
		}
54
	unset($ptr['queue'][$mypath[$i]]);
55
}
56

    
57
function clean_child_queues($type, $mypath) {
58
	$ref = &get_reference_to_me_in_config($mypath);
59

    
60
	switch ($type) {
61
	case 'HFSC':
62
		/* Nothing to do */
63
		break;
64
	case 'PRIQ':
65
		if (isset($ref['borrow'])) unset($ref['borrow']);		
66
		if (isset($ref['bandwidth'])) unset($ref['bandwidth']);
67
		if (isset($ref['bandwidthtype'])) unset($ref['bandwidthtype']);
68
		/* fall through */
69
	case 'CBQ':
70
		if (isset($ref['realtime'])) unset($ref['realtime']);	
71
		if (isset($ref['realtime1'])) unset($ref['realtime1']);
72
		if (isset($ref['realtime2'])) unset($ref['realtime2']);
73
		if (isset($ref['realtime3'])) unset($ref['realtime3']);
74
		if (isset($ref['upperlimit'])) unset($ref['upperlimit']);
75
				if (isset($ref['upperlimit1'])) unset($ref['upperlimit1']);
76
				if (isset($ref['upperlimit2'])) unset($ref['upperlimit2']);
77
				if (isset($ref['upperlimit3'])) unset($ref['upperlimit3']);
78
		if (isset($ref['linkshare'])) unset($ref['linkshare']);
79
				if (isset($ref['linkshare1'])) unset($ref['linkshare1']);
80
				if (isset($ref['linkshare2'])) unset($ref['linkshare2']);
81
				if (isset($ref['linkshare3'])) unset($ref['linkshare3']);	
82
		break;
83
	}
84
}
85

    
86
function get_bandwidthtype_scale($type) {
87
        switch ($type) {
88
        case "Gb":
89
                $factor = 1000 * 1000 * 1000;
90
        break;
91
        case "Mb":
92
                $factor = 1000 * 1000;
93
        break;
94
        case "Kb":
95
                $factor = 1000;
96
        break;
97
        case "b":
98
        default:
99
                $factor = 1;
100
        break;
101
        }
102
        return intval($factor);
103
}
104

    
105
function get_hfsc_bandwidth($object, $bw) {
106
	$pattern= "/[0-9]+/";
107
        if (preg_match($pattern, $bw, $match))
108
                $bw_1 = $match[0];
109
        else
110
                return 0;
111
        $pattern= "/(b|Kb|Mb|Gb|%)/";
112
        if (preg_match($pattern, $bw, $match)) {
113
                switch ($match[0]) {
114
                case '%':
115
                        $bw_1 = $bw_1 / 100 * get_interface_bandwidth($object);
116
                        break;
117
                default:
118
                        $bw_1 = $bw_1 * get_bandwidthtype_scale($match[0]);
119
                        break;
120
                }
121
		return intval($bw_1);
122
        } else
123
                return 0;
124
}
125

    
126
function get_interface_bandwidth($object) {
127
	global $altq_list_queues;
128

    
129
        $int = $object->GetInterface();
130
        $altq =& $altq_list_queues[$int];
131
        if ($altq) {
132
                $bw_3 = $altq->GetBandwidth();
133
                $bw_3 = $bw_3 *  get_bandwidthtype_scale($altq->GetBwscale());
134
		return intval($bw_3);
135
        } else return 0;
136
}
137

    
138
/*
139
 * This is duplicated here since we cannot include guiconfig.inc.
140
 * Including it makes all stuff break.
141
 */
142
function shaper_do_input_validation($postdata, $reqdfields, $reqdfieldsn, $input_errors) {
143

    
144
        /* check for bad control characters */
145
        foreach ($postdata as $pn => $pd) {
146
                if (is_string($pd) && preg_match("/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/", $pd)) {
147
                        $input_errors[] = "The field '" . $pn . "' contains invalid characters.";
148
                }
149
        }
150

    
151
        for ($i = 0; $i < count($reqdfields); $i++) {
152
                if ($postdata[$reqdfields[$i]] == "") {
153
                        $input_errors[] = "The field '" . $reqdfieldsn[$i] . "' is required.";
154
                }
155
        }
156
}
157

    
158
function cleanup_queue_from_rules($queue) {
159
	global $config;
160

    
161
	foreach ($config['filter']['rule'] as $rule) {
162
		if ($rule['defaultqueue'] == $queue)
163
			unset($rule['defaultqueue']);
164
		if ($rule['ackqueue'] == $queue)
165
			unset($rule['ackqueue']);
166
	}
167
	foreach ($config['interfaces'] as $if => $ifdata) {
168
			if ($ifdata['ftpqueue'] == $queue) {
169
				unset($config['interfaces'][$if]['ftpqueue']);
170
				break;
171
			}
172
	}
173
}
174

    
175
class altq_root_queue {
176
		var $interface;
177
		var $tbrconfig ;
178
		var $bandwidth;
179
		var $bandwidthtype; /* b, Kb, Mb */
180
		var $scheduler;
181
		var $qlimit;
182
		var $queues = array();
183
		var $qenabled;
184
		var $link;
185
		var $default_present; /* if we have a default queue set */
186
		var $available_bw; /* in b/s */
187

    
188
		/* Accesor functions */
189
	function GetAvailableBandwidth() {
190
		return $this->available_bw;
191
	}
192
	function SetAvailableBandwidth($bw) {
193
		$this->available_bw = $bw;
194
	}
195
	function SetDefaultQueuePresent($value) {
196
		$this->default_present = $value;
197
	}
198
	function GetDefaultQueuePresent() {
199
		return trim($this->default_present);
200
	}
201
	function SetLink($link) {
202
		$this->link = $link;
203
	}
204
	function GetLink() {
205
		return $this->link;
206
	}	
207
	function GetEnabled() {
208
		return $this->qenabled;
209
	}
210
	function SetEnabled($value) {
211
		$this->qenabled = $value;
212
	}
213
	function CanHaveChilds() {
214
		return true;
215
	}
216
	function CanBeDeleted() {
217
		return false;
218
	}
219
	function GetQname() {
220
		return $this->interface;
221
	}
222
	function SetQname($name) {
223
		$this->interface = trim($name);
224
	}
225
	function GetInterface() {
226
			return $this->interface;
227
	}
228
	function SetInterface($name) {
229
			$this->interface = trim($name);
230
	}
231
	function GetTbrConfig() {
232
			return $this->tbrconfig;
233
	}
234
	function SetTbrConfig($tbrconfig) {
235
			$this->tbrconfig = $tbrconfig;
236
	}
237
	function GetBandwidth() {
238
			return $this->bandwidth;
239
	}
240
	function SetBandwidth($bw) {
241
			$this->bandwidth = trim($bw);
242
	}
243
	function GetBwscale() {
244
			return $this->bandwidthtype;
245
	}
246
	function SetBwscale($bwscale) {
247
			$this->bandwidthtype = $bwscale;
248
	}
249
	function GetScheduler() {
250
			return $this->scheduler;
251
	}
252
	function SetScheduler($scheduler) {
253
			$this->scheduler = trim($scheduler);
254
	}
255
	function GetQlimit() {
256
		return $this->qlimit;
257
	}
258
	function SetQlimit($limit) {
259
		$this->qlimit = $limit;
260
	}
261
	
262
	function validate_input($data, &$input_errors) {
263
		global $config; /* XXX: how to get info about interfaces?! */
264
		
265
		$reqfields[] = "bandwidth";
266
		$reqdfieldsn[] = "Bandwidth";
267
		$reqfields[] = "bandwidthtype";
268
		$reqdfieldsn[] = "Bandwidthtype";
269
		
270
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
271
		
272
		if (isset($config['interface'][$this->GetQname()]['bandwidth'])) {
273
                        switch($data['banwidthtype']) {
274
                                case "%":
275
                                        $myBw = $this->GetAvailableBandwidth() * intval($data['bandwidth']) / 100;
276
                                        break;
277
                                default:
278
                                        $myBw = intval($data['bandwidth']) * get_bandwidthtype_scale($data['banwidthtype'])
279
;
280
                                        break;
281
                        }
282

    
283
                        if ($this->GetAvailableBandwidth() < $myBw)
284
                                        $input_errors[] = "Bandwidth cannot be set higher than that of interface.";
285
                }
286

    
287
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
288
                                                $input_errors[] = "Bandwidth must be an integer.";
289
                if ($data['bandwidth'] < 0)
290
                                                $input_errors[] = "Bandwidth cannot be negative.";
291
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
292
                                                $input_errors[] = "Qlimit must be an integer.";
293
	 	if ($data['qlimit'] < 0)
294
                                                $input_errors[] = "Qlimit must be an positive.";
295
                if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig'])))
296
                                                $input_errors[] = "Tbrsize must be an integer.";
297
                if ($data['tbrconfig'] < 0)
298
                                                $input_errors[] = "Tbrsize must be an positive.";
299
	}
300

    
301

    
302
	/* Implement this to shorten some code on the frontend page */
303
		function ReadConfig(&$conf) {
304
			if (isset($conf['tbrconfig']))
305
				$this->SetTbrConfig($conf['tbrconfig']);
306
			if ($conf['bandwidth'] <> "") {
307
				$this->SetBandwidth($conf['bandwidth']);
308
				if ($conf['bandwidthtype'] <> "")
309
					$this->SetBwscale($conf['bandwidthtype']);
310
			}
311
		if (isset($conf['scheduler'])) {
312
				if ($this->GetScheduler() != $conf['scheduler']) {
313
					foreach ($this->queues as $q) {
314
						clean_child_queues($conf['scheduler'], $this->GetLink());
315
						$q->clean_queue($conf['scheduler']);
316
					}
317
				}
318
				$this->SetScheduler($conf['scheduler']);
319
			}
320
		if (isset($conf['qlimit']) && $conf['qlimit'] <> "")
321
			$this->SetQlimit($conf['qlimit']);
322
		if (isset($conf['name']))
323
			$this->SetQname($conf['name']);		
324
		//if (isset($conf['enabled']) && $conf['enabled'] == "on")
325
			$this->SetEnabled("on");
326

    
327
	}
328
	
329
	function copy_queue($interface, &$queue) {
330
		global $config;
331
		
332
		$mylink = &get_reference_to_me_in_config($this->GetLink());
333
		$link = &get_reference_to_me_in_config($queue->GetLink());
334
	
335
		if ($link && $mylink) {
336
				if (!is_array($mylink['queue'][$queue->GetQname()]))
337
						$mylink['queue'][$queue->GetQname()] = array();
338

    
339
				foreach ($link as $key => $value)
340
						$mylink['queue'][$queue->GetQname()][$key] = $value;
341
		}
342
	}
343

    
344

    
345
		function &add_queue($interface, &$queue, &$path, &$input_errors) {
346

    
347
			if (!is_array($this->queues))
348
				$this->queues = array();
349
				
350
			switch ($this->GetScheduler()) {
351
				case "PRIQ":
352
					$q =& new priq_queue();
353
					break;
354
				case "HFSC":
355
					$q =& new hfsc_queue();
356
					break;
357
				case "CBQ":
358
						$q =& new cbq_queue();
359
					break;
360
				default:
361
					/* XXX: but should not happen anyway */ 
362
					return;
363
					break;
364
			}
365
			$q->SetLink($path);
366
			$q->SetInterface($this->GetInterface());
367
			$q->SetEnabled("on");
368
			$q->SetParent(&$this);
369
			$q->ReadConfig($queue);
370
			$q->validate_input($queue, $input_errors);
371
                 if (count($input_errors)) {
372
                       return $q;
373
                 }
374

    
375
                 if (isset($q['bandwidth'])) {
376
                         switch ($q['bandwidthtype']) {
377
                         case "%":
378
                                $q->SetAvailableBandwidth($this->GetAvailableBandwidth() -
379
                                        ($this->GetAvailableBandwidth() * $q['bandwidth'] / 100));
380
                                break;
381
                        default:
382
                                $q->SetAvailableBandwidth($this->GetAvailableBandwidth() -
383
                                        ($q['bandwidth'] * get_bandwidthtype_scale($q['bandwdithtype'])));
384
                                break;
385
                        }
386
                }
387
			$this->queues[$q->GetQname()] = &$q; 
388
			$GLOBALS['allqueue_list'][] = $q->GetQname();
389
			ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
390
			if (is_array($queue['queue'])) {
391
				foreach ($queue['queue'] as $key1 => $que) {
392
					array_push($path, $key1);
393
								$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
394
					array_pop($path);
395
						}
396
			}
397
	
398
			return $q;
399
		}
400

    
401
		/* interface here might be optional */
402
		function &find_queue($interface, $qname) {
403
			if ($qname == $this->GetQname()) {
404
				return $this;
405
			} 
406
			foreach ($this->queues as $q) {
407
				$result =& $q->find_queue("", $qname);
408
				if ($result)
409
					return $result;
410
			}
411
		}
412

    
413
	function &find_parentqueue($interface, $qname) {
414
		if ($qname == $interface) {
415
			$result =  NULL;
416
		} else if ($this->queues[$qname])	 {
417
			$result = $this;
418
		} else if ($this->GetScheduler() <> "PRIQ") {
419
			foreach ($this->queues as $q) {
420
				$result = $q->find_parentqueue("", $qname);
421
				if ($result)
422
					return $result;
423
			}
424
		}
425
	}
426

    
427
	function build_tree() {
428
		$tree = " <li><a href=\"firewall_shaper.php?interface=".$this->GetInterface()."&queue=". $this->GetInterface()."&action=show"; 
429
		$tree .= "\">" . $this->GetInterface() . "</a>";
430
		if (is_array($this->queues)) {
431
			$tree .= "<ul>";
432
			foreach ($this->queues as $q)  {
433
				$tree .= $q->build_tree();
434
			}
435
		$tree .= "</ul>";
436
		}
437
		$tree .= "</li>";
438
		return $tree;
439
	}
440
	
441
	function delete_queue() { 
442
		foreach ($this->queues as $q)
443
			$q->delete_queue();			
444
		unset_object_by_reference($this->GetLink());
445
	 }
446

    
447
	function delete_all() {
448
                if (count($this->queues)) {
449
                        foreach ($this->queues as $q) {
450
                        	$q->delete_all();
451
                        	unset_object_by_reference($q->GetLink());
452
                                unset($q);
453
               		}
454
        	        unset($this->queues);
455
                }
456
        }
457

    
458
	/*
459
	 * First it spits:
460
	 * altq on $interface ..............
461
	 *      then it goes like
462
	 *      foreach ($queues as $qkey => $queue)
463
	 *              this->queues[$qkey]->build_rule();
464
	 */
465
	function build_rules() {
466
		if (count($this->queues) > 0 && $this->GetEnabled()) {
467
			$rules = " altq on  " . convert_friendly_interface_to_real_interface_name($this->GetInterface());
468
			if ($this->GetScheduler())
469
					$rules .= " ".strtolower($this->GetScheduler());
470
			if ($this->GetBandwidth())
471
					$rules .= " bandwidth ".trim($this->GetBandwidth());
472
			if ($this->GetBwscale())
473
					$rules .= $this->GetBwscale();
474
			if ($this->GetTbrConfig())
475
					$rules .= " tbrsize ".$this->GetTbrConfig();
476
			if (count($this->queues)) {
477
					$i = count($this->queues);
478
					$rules .= " queue { ";
479
					foreach ($this->queues as $qkey => $qnone) {
480
							if ($i > 1) {
481
									$i--;
482
									$rules .= " {$qkey}, ";
483
							} else
484
									$rules .= " {$qkey} ";
485
					}
486
					$rules .= " } \n";
487
					foreach ($this->queues as $q) {
488
							$rules .= $q->build_rules();
489
					}
490
			}
491
		}
492
		$rules .= " \n";
493
		return $rules;
494
	}
495

    
496
	function build_javascript() {
497
			$javascript = "<script type=\"text/javascript\">";
498
			$javascript .= "function mySuspend() {";
499
			$javascript .= "if (document.layers && document.layers['shaperarea'] != null);";
500
			$javascript .= "document.layers['shaperarea'].visibility = 'hidden';";
501
			$javascript .= "else if (document.all)";
502
			$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';";
503
			$javascript .= "}";
504

    
505
			$javascript .= "function myResume() {";
506
			$javascript .= "if (document.layers && document.layers['shaperarea'] != null)";
507
			$javascript .= "document.layers['shaperarea'].visibility = 'visible';";
508
			$javascript .= "else if (document.all)";
509
			$javascript .= "document.all['shaperarea'].style.visibility = 'visible';";
510
			$javascript .= "}";
511
			$javascript .= "</script>";
512

    
513
			return $javascript;
514
	}
515
	
516
	function build_shortform() {
517
			global $g;
518

    
519
			$altq =& $this;
520
			if ($altq)
521
					$scheduler = ": " . $altq->GetScheduler();
522
			$form = "<tr><td width=\"20%\" class=\"vtable\">";
523
			$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=". $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
524
			$form .= "</td></tr>";
525
			$form .= "<tr>";
526
			$form .= "<td width=\"50%\" class=\"vncellreq\">";
527
			$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
528
			$form .= "</td><td width=\"50%\"></td></tr>";
529
			$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
530
			$form .= "<a href=\"firewall_shaper_queues.php?interface=";
531
			$form .= $this->GetInterface() . "&queue=";
532
			$form .= $this->GetQname() . "&action=delete\">";
533
			$form .= "<img src=\"";
534
			$form .= "./themes/".$g['theme']."/images/icons/icon_minus.gif\"";
535
			$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Disable shaper on i
536
nterface\">";
537
			$form .= "<span>Disable shaper from interface</span></a></td></tr>";
538

    
539
			return $form;
540

    
541
	}
542
		/*
543
		 * For requesting the parameters of the root queue
544
		 * to the user like the traffic wizard does.
545
		 */
546
	function build_form() { 
547
		$form = "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
548
		$form .= "<td class=\"vncellreq\">";
549
		$form .= "<strong>".$this->GetQname()."</strong>";
550
		$form .= "</td></tr>";
551
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Scheduler Type ";
552
		$form .= "</td>";
553
		$form .= "<td class=\"vncellreq\">";
554
		$form .= "<select id=\"scheduler\" name=\"scheduler\" class=\"formselect\">";
555
				$form .= "<option value=\"HFSC\"";
556
		if ($this->GetScheduler() == "HFSC")
557
			$form .= " selected=\"yes\"";
558
		$form .= ">HFSC</option>";
559
				$form .= "<option value=\"CBQ\"";
560
		if ($this->GetScheduler() == "CBQ")
561
						$form .= " selected=\"yes\"";
562
		$form .= ">CBQ</option>";
563
				$form .= "<option value=\"PRIQ\"";
564
		if ($this->GetScheduler() == "PRIQ")
565
						$form .= " selected=\"yes\"";
566
		$form .= ">PRIQ</option>";
567
				$form .= "</select>";
568
		$form .= "<br> <span class=\"vexpl\">";
569
		$form .= "NOTE: changing this changes all queues underneath!";
570
		$form .= " Beaware you can loose information.";
571
		$form .= "</span>";
572
		$form .= "</td></tr>";
573
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Bandwidth";
574
		$form .= "</td><td class=\"vncellreq\">";
575
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
576
		$form .= $this->GetBandwidth() . "\">"; 
577
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
578
		$form .= "<option value=\"Kb\"";
579
		if ($this->GetBwscale() == "Kb")
580
			$form .= " selected=\"yes\"";
581
		$form .= ">Kbit/s</option>";
582
		$form .= "<option value=\"Mb\"";
583
		if ($this->GetBwscale() == "Mb")
584
			$form .= " selected=\"yes\"";
585
		$form .= ">Mbit/s</option>";
586
		$form .= "<option value=\"Gb\"";
587
		if ($this->GetBwscale() == "Gb")
588
			$form .= " selected=\"yes\"";
589
		$form .= ">Gbit/s</option>";		
590
		$form .= "<option value=\"\"";
591
		if ($this->GetBwscale() == "b")
592
			$form .= " selected=\"yes\"";
593
		$form .= ">Bit/s</option>";
594
		$form .= "</select>";
595
		$form .= "</td></tr>";
596
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Queue Limit</td>";
597
		$form .= "<td class=\"vncellreq\">";
598
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
599
		$form .= $this->GetQlimit();
600
		$form .= "\">";
601
		$form .= "</td></tr>";
602
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Tbr Size</td>";
603
		$form .= "<td class=\"vncellreq\">";
604
		$form .= "<input type=\"text\" id=\"tbrconfig\" name=\"tbrconfig\" value=\"";
605
		$form .= $this->GetTbrConfig();
606
		$form .= "\">";
607
		$form .= "<br> <span class=\"vexpl\">";
608
		$form .= "Adjusts the size, in bytes, of the token bucket regulator.";
609
		$form .= "If not specified, heuristics based on the interface ";
610
		$form .= "bandwidth are used to determine the size.";
611
				$form .= "</span></td></tr>";
612
		$form .= "<input type=\"hidden\" id=\"interface\" name=\"interface\"";
613
		$form .= " value=\"" . $this->GetInterface() . "\">";
614
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"".$this->GetQname()."\" >";
615

    
616

    
617
		return $form;
618
	}
619

    
620
		function update_altq_queue_data(&$data) { 
621
		$this->ReadConfig($data);
622
	}
623
	
624
	/*
625
	 * Should call on each of it queues and subqueues
626
	 * the same function much like build_rules();
627
	 */
628
	function wconfig() { 
629
		$cflink = &get_reference_to_me_in_config($this->GetLink());
630
		if (!is_array($cflink))
631
			$cflink = array();
632
		$cflink['interface'] = $this->GetInterface();	
633
		$cflink['name'] = $this->GetQname();
634
		$cflink['scheduler'] = $this->GetScheduler();
635
		$cflink['bandwidth'] = $this->GetBandwidth();
636
		$cflink['bandwidthtype'] = $this->GetBwscale();
637
		$cflink['qlimit'] = $this->GetQlimit();
638
		$cflink['tbrconfig'] = $this->GetTbrConfig();
639
		$cflink['enabled'] = $this->GetEnabled();
640
	}
641

    
642
}
643

    
644
class priq_queue {
645
	var $qname;
646
	var $qinterface; 
647
	var $qlimit;
648
	var $qpriority;
649
	var $description;
650
	var $isparent;
651
	var $qbandwidth;
652
	var $qbandwidthtype;
653
	var $qdefault;
654
	var $qrio;
655
	var $qred;
656
	var $qecn;
657
	var $qack;
658
	var $qenabled;
659
	var $qparent;
660
	var $link;
661
	var $available_bw; /* in b/s */
662

    
663
	/* This is here to help on form building and building rules/lists */
664
		var $subqueues = array();
665

    
666
	/* Accesor functions */
667
	function GetAvailableBandwidth() {
668
		return $this->available_bw;
669
	}
670
	function SetAvailableBandwidth($bw) {
671
		$this->available_bw = $bw;
672
	}
673
	function SetLink($link) {
674
			$this->link = $link;
675
	}
676
	function GetLink() {
677
			return $this->link;
678
	}
679
	function &GetParent() {
680
		return $this->qparent;
681
	}
682
	function SetParent(&$parent) {
683
		$this->qparent = &$parent;
684
	}
685
	function GetEnabled() {
686
			return $this->qenabled;
687
	}
688
	function SetEnabled($value) {
689
			$this->qenabled = $value;
690
	}
691
	function CanHaveChilds() {
692
			return false;
693
	}
694
	function CanBeDeleted() {
695
			return true;
696
	}
697
	function GetQname() {
698
			return $this->qname;
699
	}
700
	function SetQname($name) {
701
			$this->qname = trim($name);
702
	}
703
	function GetBandwidth() {
704
			return $this->qbandwidth;
705
	}
706
	function SetBandwidth($bandwidth) {
707
			$this->qbandwidth = $bandwidth;
708
	}
709
	function GetInterface() {
710
			return $this->qinterface;
711
	}
712
	function SetInterface($name) {
713
			$this->qinterface = trim($name);
714
	}
715
	function GetQlimit() {
716
			return $this->qlimit;
717
	}
718
	function SetQlimit($limit) {
719
			$this->qlimit = $limit;
720
	}
721
	function GetQpriority() {
722
			return $this->qpriority;
723
	}
724
	function SetQpriority($priority) {
725
			$this->qpriority = $priority;
726
	}
727
	function GetDescription() {
728
			return $this->description;
729
	}
730
	function SetDescription($str) {
731
			$this->description = trim($str);
732
	}
733
	function GetFirstime() {
734
			return $this->firsttime;
735
	}
736
	function SetFirsttime($number) {
737
			$this->firsttime = $number;
738
	}
739
	function GetBwscale() {
740
			return $this->qbandwidthtype;
741
	}
742
	function SetBwscale($scale) {
743
			$this->qbandwidthtype = $scale;
744
	}
745
	function GetDefault() {
746
			return $this->qdefault;
747
	}
748
	function SetDefault($value = false) {
749
			$this->qdefault = $value;
750
	altq_set_default_queue($this->GetInterface(), "true");
751
	}
752
	function GetRed() {
753
			return $this->qred;
754
	}
755
	function SetRed($red = false) {
756
			$this->qred = $red;
757
	}
758
	function GetRio() {
759
			return $this->qrio;
760
	}
761
	function SetRio($rio = false) {
762
			$this->qrio = $rio;
763
	}
764
function GetEcn() {
765
			return $this->qecn;
766
	}
767
	function SetEcn($ecn = false) {
768
			$this->qecn = $ecn;
769
	}
770
	function GetAck() {
771
			return $this->qack;
772
	}
773
	function SetAck($ack = false) {
774
			$this->qack = $ack;
775
	}
776

    
777
	function build_javascript() {
778
		$javascript = "<script type=\"text/javascript\">";
779
		$javascript .= "function mySuspend() { \n";
780
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);\n";
781
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
782
		$javascript .= "else if (document.all)\n";
783
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
784
		$javascript .= "}\n";
785

    
786
		$javascript .= "function myResume() {\n";
787
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
788
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
789
		$javascript .= "else if (document.all)\n";
790
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
791
		$javascript .= "}\n";
792
		$javascript .= "</script>";
793
		
794
		return $javascript;
795
	}
796
	
797
	/* 
798
	 * Currently this will not be called unless we decide to clonce whole 
799
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
800
	 */
801
	 function copy_queue($interface, &$queue) {
802
		global $config;
803

    
804
		$mylink = &get_reference_to_me_in_config($this->GetLink());
805
		$copylink = &get_reference_to_me_in_config($queue->GetLink());
806

    
807
		if ($link && $mylink) {
808
				if (!is_array($mylink['queue'][$queue->GetQname()]))
809
						$mylink['queue'][$queue->GetQname()] = array();
810

    
811
				foreach ($link as $key => $value)
812
						$mylink['queue'][$queue->GetQname()][$key] = $value;
813
		}
814
	 }
815

    
816
	function clean_queue($sched) {
817
		clean_child_queues($sched, $this->GetLink());
818
		if (is_array($this->subqueues)) {
819
				foreach ($this->subqueues as $q)
820
						$q->clean_queue($sched);
821
				}
822
		}
823

    
824

    
825
		
826
	function delete_queue() {
827
		unref_on_altq_queue_list($this->GetQname());
828
		if ($this->GetDefault())
829
				altq_set_default_queue($this->GetInterface(), "false");
830
		cleanup_queue_from_rules($this->GetQname());
831
		unset_object_by_reference($this->GetLink());
832
	}
833
	
834
	function delete_all() {
835
                if (count($this->subqueues)) {
836
                        foreach ($this->subqueues as $q) {
837
                                $q->delete_all();
838
                                unset_object_by_reference($q->GetLink());
839
                                unset($q);
840
                        }
841
                        unset($this->subqueues);
842
                }
843
        }
844

    
845
	 function &find_queue($interface, $qname) { 
846
		if ($qname == $this->GetQname())
847
			return $this; 
848
	}
849
	
850
	function find_parentqueue($interface, $qname) { return; }
851
		
852
	function validate_input($data, &$input_errors) {
853
	
854
		$reqfields[] = "name";
855
		$erqfieldsn[] = "Name";
856
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
857

    
858
		if ($data['priority'] && (!is_numeric($data['priority'])
859
						|| ($data['priority'] < 1) || ($data['priority'] > 15))) {
860
					$input_errors[] = "The priority must be an integer between 1 and 15.";
861
		}
862
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
863
				$input_errors[] = "Queue limit must be an integer";
864
		if ($data['qlimit'] < 0)
865
				$input_errors[] = "Queue limit must be positive";
866
		if (!preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
867
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
868
		
869
	}
870

    
871
	function ReadConfig(&$q) {
872
		if (isset($q['name']))
873
				$this->SetQname($q['name']);
874
		if (isset($q['interface']))
875
				$this->SetInterface($q['interface']);
876
		if ($q['bandwidth'] <> "") {
877
			$this->SetBandwidth($q['bandwidth']);
878
			if ($q['bandwidthtype'] <> "")
879
				$this->SetBwscale($q['bandwidthtype']);
880
		}
881
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
882
					$this->SetQlimit($q['qlimit']);
883
				if (isset($q['priority']))
884
						$this->SetQPriority($q['priority']);
885
				if (isset($q['description']) && $q['description'] != "")
886
						$this->SetDescription($q['description']);
887
		if (isset($q['ftpqueue']) && $q['ftpqueue'] <> "") 
888
			set_is_ftp_queue($this->GetInterface(), $this->GetQname());
889
		$this->SetRed($q['red']);
890
		$this->SetRio($q['rio']);
891
		$this->SetEcn($q['ecn']);
892
		$this->SetDefault($q['default']);
893
		$this->SetEnabled($q['enabled']);
894

    
895
		}
896

    
897
	function build_tree() {
898
			$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
899
			$tree .= "\" ";
900
			if ($this->GetDefault())
901
				$tree .= " class=\"navlnk\"";
902
			$tree .= " >" . $this->GetQname() . "</a>";
903
			/* 
904
			 * Not needed here!
905
			 * if (is_array($queues) {
906
			 *	  $tree .= "<ul>";
907
			 *	  foreach ($q as $queues) 
908
			 *		  $tree .= $queues['$q->GetName()']->build_tree();
909
			 *	  endforeach	
910
			 *	  $tree .= "</ul>";
911
			 * }
912
			 */
913

    
914
			$tree .= "</li>"; 
915

    
916
			return $tree;
917
		}
918
		
919
		/* Should return something like:
920
		 * queue $qname on $qinterface bandwidth ....
921
		 */
922
		function build_rules() {
923
				$pfq_rule = " queue ". $this->qname;
924
				if ($this->GetInterface())
925
						$pfq_rule .= " on ".convert_friendly_interface_to_real_interface_name($this->GetInterface());
926
				if ($this->GetQpriority())
927
						$pfq_rule .= " priority ".$this->GetQpriority();
928
				if ($this->GetQlimit())
929
						$pfq_rule .= " qlimit " . $this->GetQlimit();
930
				if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
931
						$pfq_rule .= " priq ( ";
932
					if ($this->GetRed()) {
933
						$comma = 1;
934
						$pfq_rule .= " red ";
935
					}
936
					if ($this->GetRio()) {
937
						if ($comma) 
938
								$pfq_rule .= " ,";
939
						$comma = 1;
940
						$pfq_rule .= " rio ";
941
					}
942
					if ($this->GetEcn()) {
943
						if ($comma) 
944
								$pfq_rule .= " ,";
945
						$comma = 1;
946
						$pfq_rule .= " ecn ";
947
					}	
948
					if ($this->GetDefault()) {
949
						if ($comma)
950
							$pfq_rule .= " ,";
951
						$pfq_rule .= " default ";
952
					}
953
					$pfq_rule .= " ) ";
954
				}
955
	
956
				$pfq_rule .= " \n";
957
		
958
				return $pfq_rule;
959
		}
960

    
961
		/*
962
		 * To return the html form to show to user
963
		 * for getting the parameters.
964
		 * Should do even for first time when the
965
		 * object is created and later when we may
966
		 * need to update it.
967
		 */
968
		function build_form() {
969
				$form .= "<tr>";
970
		$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">";
971
		$form .= "Queue Name</td><td width=\"78%\" class=\"vtable\">";
972
		$form .= "<input name=\"name\" type=\"text\" id=\"name\" class=\"formfld unknown\" size=\"15\" value=\"";
973
		$form .= htmlspecialchars($this->GetQname());
974
		$form .= "\">";
975
				$form .= "<br> <span class=\"vexpl\">Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.";
976
				$form .= "</span></td>";
977
		$form .= "</tr><tr>";
978
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Priority</td>";
979
				$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
980
				$form .= htmlspecialchars($this->GetQpriority());
981
				$form .= "\">";
982
				$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>";
983
				$form .= "</tr>";
984
				$form .= "</tr>";
985
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Queue limit</td>";
986
				$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"5\" value=\"";
987
				$form .= htmlspecialchars($this->GetQlimit());
988
				$form .= "\">";
989
		$form .= "<br> <span class=\"vexpl\">Queue limit in packet per second."; 
990
				$form .= "</span></td>";
991
				$form .= "<tr>";
992
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncell\">Scheduler options</td>";
993
				$form .= "<td width=\"78%\" class=\"vtable\">";
994
		if ($this->GetDefault()) { 
995
				$form .= "<input type=\"checkbox\" id=\"default\" CHECKED name=\"default\"";
996
		$form .= "> Default queue<br>";
997
		} else if (count($this->subqueues) < 1) {
998
			$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\"";
999
					$form .= "> Default queue<br>";
1000
		}
1001
		/* XXX: TODO Add check to disable this if it has been set on another queue on this interface. */
1002
		$form .= "<input type=\"checkbox\" id=\"ftpqueue\" name=\"ftpqueue\" ";
1003
		if (get_is_ftp_queue($this->GetInterface(), $this->GetQname()))  
1004
			$form .= " CHECKED";
1005
		$form .= ">Use this queue for the ftp proxy<br>";
1006
		/* XXX: TODO */
1007
				$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\"";
1008
				if($this->GetRed()) 
1009
			$form .=  " CHECKED";
1010
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">Random Early Detection</a><br>";
1011
				$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\"";
1012
				if($this->GetRio()) 
1013
			$form .=  " CHECKED";
1014
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">Random Early Detection In and Out</a><br>";
1015
				$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\"";
1016
				if($this->GetEcn()) 
1017
			$form .=  " CHECKED";
1018
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">Explicit Congestion Notification</a><br>";
1019
				$form .= "<span class=\"vexpl\"><br>Select options for this queue";
1020
				$form .= "</tr><tr>";
1021
		$form .= "<td width=\"22%\" class=\"vncellreq\">Description</td>";
1022
		$form .= "<td width=\"78%\" class=\"vtable\">";
1023
		$form .= "<input type=\"text\" name=\"description\" size=\"50%\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\"  >";
1024
		$form .= "</td></tr>";
1025
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1026
				$form .= " value=\"".$this->GetInterface()."\">";
1027

    
1028
		return $form;
1029
		}
1030

    
1031
	function build_shortform() {
1032
		/* XXX: Hacks in site. Mostly layer violations!  */
1033
		global $g, $altq_list_queues;
1034

    
1035
		$altq =& $altq_list_queues[$this->GetInterface()];
1036
		if ($altq)
1037
			$scheduler = ": " . $altq->GetScheduler();
1038
		 $form = "<tr><td width=\"20%\" class=\"vtable\">";
1039
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=" . $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
1040
		$form .= "</td></tr>";
1041
		/* 
1042
		 * XXX: Hack in sight maybe fix with a class that wraps all
1043
		 * of this layer violations
1044
		 */
1045
		$form .= "<tr>";
1046
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1047
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
1048
		$form .= "</td><td width=\"50%\"></td></tr>";
1049
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1050
		if ($this->GetQpriority())
1051
			$form .= "Priority: on </td></tr>";
1052
		if ($this->GetDefault())
1053
			$form .= "<tr><td class=\"vncellreq\">Default: on </td></tr>";
1054
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1055
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1056
			$form .= $this->GetInterface() . "&queue=";
1057
			$form .= $this->GetQname() . "&action=delete\">";
1058
			$form .= "<img src=\"";
1059
			$form .= "./themes/".$g['theme']."/images/icons/icon_minus.gif\"";
1060
			$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Delete queue from interface\">";
1061
			$form .= "<span>Delete queue from interface</span></a></td></tr>";
1062
		
1063
		return $form;
1064

    
1065
	}
1066

    
1067
		function update_altq_queue_data(&$q) { 
1068
		$this->ReadConfig($q);
1069
	}
1070

    
1071
		function wconfig() {
1072
				$cflink =& get_reference_to_me_in_config($this->GetLink());
1073
		if (!is_array($cflink))
1074
			$cflink = array();
1075
		$cflink['name'] = $this->GetQname();
1076
				$cflink['interface'] = $this->GetInterface();
1077
				$cflink['qlimit'] = $this->GetQlimit();
1078
				$cflink['priority'] = $this->GetQpriority();
1079
		$cflink['description'] = $this->GetDescription();
1080
		$cflink['enabled'] = $this->GetEnabled();
1081
		$cflink['default'] = $this->GetDefault();
1082
		$cflink['red'] = $this->GetRed();
1083
		$cflink['rio'] = $this->GetRio();
1084
		$cflink['ecn'] = $this->GetEcn();
1085
	}
1086
}
1087

    
1088
class hfsc_queue extends priq_queue {
1089
		/* realtime */
1090
	var $realtime;
1091
		var $r_m1;
1092
		var $r_d;
1093
		var $r_m2;
1094
		/* linkshare */
1095
	var $linkshare;
1096
		var $l_m1;
1097
		var $l_d;
1098
		var $l_m2;
1099
		/* upperlimit */
1100
	var $upperlimit;
1101
		var $u_m1;
1102
		var $u_d;
1103
		var $u_m2;
1104

    
1105
		/*
1106
		 * HFSC can have nested queues.
1107
		 */
1108

    
1109
	function CanHaveChilds() {
1110
				return true;
1111
		}
1112
	function GetRealtime() {
1113
           return $this->realtime;
1114
     }
1115
     function GetR_m1() {
1116
           return $this->r_m1;
1117
     }
1118
     function GetR_d() {
1119
           return $this->r_d;
1120
     }
1121
     function GetR_m2() {
1122
           return $this->r_m2;
1123
     }
1124
     function SetRealtime() {
1125
           $this->realtime = "on";
1126
     }
1127
     function SetR_m1($value) {
1128
           $this->r_m1 = $value;
1129
     }
1130
     function SetR_d($value) {
1131
           $this->r_d = $value;
1132
     }
1133
     function SetR_m2($value) {
1134
           $this->r_m2 = $value;
1135
     }
1136
     function GetLinkshare() {
1137
           return $this->linkshare;
1138
     }
1139
     function GetL_m1() {
1140
           return $this->l_m1;
1141
     }
1142
     function GetL_d() {
1143
           return $this->l_d;
1144
     }
1145
     function GetL_m2() {
1146
           return $this->l_m2;
1147
     }
1148
     function SetLinkshare() {
1149
           $this->linkshare = "on";
1150
     }
1151
     function SetL_m1($value) {
1152
           $this->l_m1 = $value;
1153
     }
1154
     function SetL_d($value) {
1155
           $this->l_d = $value;
1156
     }
1157
     function SetL_m2($value) {
1158
           $this->l_m2 = $value;
1159
     }
1160
     function GetUpperlimit() {
1161
           return $this->upperlimit;
1162
     }
1163
     function GetU_m1() {
1164
           return $this->u_m1;
1165
     }
1166
     function GetU_d() {
1167
           return $this->u_d;
1168
     }
1169
     function GetU_m2() {
1170
           return $this->u_m2;
1171
     }
1172
     function SetUpperlimit() {
1173
           $this->upperlimit = "on";
1174
     }
1175
     function SetU_m1($value) {
1176
           $this->u_m1 = $value;
1177
     }
1178
     function SetU_d($value) {
1179
           $this->u_d = $value;
1180
     }
1181
     function SetU_m2($value) {
1182
           $this->u_m2 = $value;
1183
     }
1184

    
1185

    
1186

    
1187
		function &add_queue($interface, &$qname, &$path, &$input_errors) {
1188

    
1189
			if (!is_array($this->subqueues))
1190
							$this->subqueues = array();
1191
			$q =& new hfsc_queue();
1192
			$q->SetInterface($this->GetInterface());
1193
			$q->SetParent(&$this);
1194
			$this->CalculateRemainingBandwidth($qname['bandwidth'], $qname['bandwidthtype']);
1195
			$q->ReadConfig($qname);
1196
			$q->validate_input($qname, $input_errors);
1197
			if (count($input_errors)) {
1198
				return $q;
1199
			}
1200
			$q->SetEnabled("on");
1201
			$q->SetLink($path);
1202
			switch($q->GetBwscale()) {
1203
                                case "%":
1204
                                        $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1205
                                        break;
1206
                                default:
1207
                                        $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1208
                                        break;
1209
                        }
1210
                        $q->SetAvailableBandwidth($myBw);
1211
                        $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1212

    
1213
			$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1214
			$GLOBALS['allqueue_list'][] = $q->GetQname();
1215
			ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1216
			if (is_array($qname['queue'])) {
1217
				foreach ($qname['queue'] as $key1 => $que) {
1218
					array_push($path, $key1);
1219
								$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1220
					array_pop($path);
1221
				}
1222
					}
1223
	
1224
			return $q;
1225
		}
1226

    
1227
		function delete_queue() { 
1228
			unref_on_altq_queue_list($this->GetQname());
1229
			if ($this->GetDefault()) 
1230
				altq_set_default_queue($this->GetInterface(), "false");
1231
			cleanup_queue_from_rules($this->GetQname());
1232
			$parent =& $this->GetParent();
1233
			$parent->CalculateRemainingBandwidth($this->GetBandwidth(), $this->GetBwscale(), "delete"); 			
1234
			foreach ($this->subqueues as $q)
1235
				$q->delete_queue();
1236
			unset_object_by_reference($this->GetLink());
1237
			}
1238
	
1239
			/*
1240
			 * Should search even its childs
1241
			 */
1242
			function &find_queue($interface, $qname) {
1243
					if ($qname == $this->GetQname()) 
1244
							return $this;
1245
		
1246
					foreach ($this->subqueues as $q) {
1247
							$result =& $q->find_queue("", $qname);
1248
				if ($result)
1249
									return $result;
1250
					}
1251
			}
1252

    
1253
	function &find_parentqueue($interface, $qname) {
1254
		if ($this->subqueues[$qname]) 
1255
			return $this;
1256
				foreach ($this->subqueues as $q) {
1257
					$result = $q->find_parentqueue("", $qname);
1258
			if ($result)
1259
				return $result;
1260
		}
1261
		}
1262
	
1263
	function validate_input($data, &$input_errors) {
1264
		parent::validate_input($data, $input_errors);
1265
		
1266
		$reqfields[] = "bandwidth";
1267
		$reqdfieldsn[] = "Bandwidth";
1268
		$reqfields[] = "bandwidthtype";
1269
		$reqdfieldsn[] = "Bandwidthtype";
1270

    
1271
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1272
		
1273
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1274
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1275
                        $input_errors[] = "Bandwidth must be an integer.";
1276

    
1277
                if ($data['bandwidth'] < 0)
1278
                        $input_errors[] = "Bandwidth cannot be negative.";
1279

    
1280
                if ($data['bandwidthtype'] == "%") {
1281
                 if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1282
                       $input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1283
                 }
1284

    
1285
                $parent =& $this->GetParent();
1286
                switch ($data['bandwidthtype']) {
1287
                       case "%":
1288
                             $myBw = $parent->GetAvailableBandwidth() * intval($data['bandwidth']) / 100;
1289
                       default:
1290
                             $mybw = intval($data['bandwiddth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1291
                             break;
1292
                }
1293
                if ($parent->GetAvailableBandwidth() < $myBw)
1294
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
1295
                if ($data['priority'] > 7)
1296
                        $input_errors[] = "Priority must be an integer between 1 and 7.";
1297
		}
1298

    
1299
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1300
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1301
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1302
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1303
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1304
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1305
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1306
			$input_errors[] = ("upperlimit d value needs to be numeric");
1307
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1308
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1309

    
1310
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1311
		$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1312
		$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1313
		if (intval($bw_1) < intval($bw_2)) 
1314
			$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1315

    
1316
		
1317
		if (get_interface_bandwidth($this) < (0.8 * (intval($bw_1) + intval($bw_2))))
1318
			$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1319
		}
1320
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1321
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1322
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1323
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1324
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1325
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1326
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1327
			$input_errors[] = ("linkshare d value needs to be numeric");
1328
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1329
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1330
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1331
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1332
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1333
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1334

    
1335
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "") {
1336
		$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1337
                $bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1338
                if (intval($bw_1) < intval($bw_2))
1339
                        $input_errors[] = ("linkshare m1 cannot be smaller than m2");
1340

    
1341

    
1342
                if (get_interface_bandwidth($this) < (0.8 * (intval($bw_1) + intval($bw_2))))
1343
                        $input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1344
		}
1345
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1346
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1347
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1348
			$input_errors[] = ("realtime d value needs to be numeric");
1349
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1350
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1351

    
1352
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "") {
1353
		$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1354
                $bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1355
                if (intval($bw_1) < intval($bw_2))
1356
                        $input_errors[] = ("realtime m1 cannot be smaller than m2");
1357

    
1358

    
1359
                if (get_interface_bandwidth($this) < (0.8 * (intval($bw_1) + intval($bw_2))))
1360
                        $input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1361
		}
1362

    
1363
	}
1364

    
1365
		function ReadConfig(&$cflink) {
1366
		if (isset($cflink['linkshare']) && $cflink['linkshare'] <> "") {
1367
			if (isset($cflink['linkshare1']) && $cflink['linkshare1'] <> "") {
1368
				$this->SetL_m1($cflink['linkshare1']);
1369
                                $this->SetL_d($cflink['linkshare2']);
1370
				$this->SetLinkshare();
1371
			}
1372
			if (isset($cflink['linkshare3']) && $cflink['linkshare3'] <> "") {
1373
                                $this->SetL_m2($cflink['linkshare3']);
1374
				$this->SetLinkshare();
1375
			}
1376
		}
1377
		if (isset($cflink['realtime']) && $cflink['realtime'] <> "") {
1378
                        if (isset($cflink['realtime1']) && $cflink['realtime1'] <> "") {
1379
                                $this->SetR_m1($cflink['realtime1']);
1380
                                $this->SetR_d($cflink['realtime2']);
1381
				$this->SetRealtime();
1382
			}
1383
                        if (isset($cflink['realtime3']) && $cflink['realtime3'] <> "") {
1384
                                $this->SetR_m2($cflink['realtime3']);
1385
				$this->SetRealtime();
1386
			}
1387
		}
1388
		if (isset($cflink['upperlimit']) && $cflink['upperlimit'] <> "") {
1389
                        if (isset($cflink['upperlimit1']) && $cflink['upperlimit1'] <> "") {
1390
                                $this->SetU_m1($cflink['upperlimit1']);
1391
                                $this->SetU_d($cflink['upperlimit2']);
1392
				$this->SetUpperlimit();
1393
			}
1394
                        if (isset($cflink['upperlimit3']) && $cflink['upperlimit3'] <> "") {
1395
                                $this->SetU_m2($cflink['upperlimit3']);
1396
				$this->SetUpperlimit();
1397
			}
1398
		}
1399
		parent::ReadConfig($cflink);
1400

    
1401
		}
1402

    
1403
	function build_tree() {
1404
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1405
		$tree .= "\" ";
1406
		if ($this->GetDefault())
1407
								$tree .= " class=\"navlnk\"";
1408
		$tree .= " >" . $this->GetQname() . "</a>";
1409
		if (is_array($this->subqueues)) {
1410
			$tree .= "<ul>";
1411
			foreach ($this->subqueues as $q)  {
1412
				$tree .= $q->build_tree();
1413
			}	
1414
			$tree .= "</ul>";
1415
		}
1416
		$tree .= "</li>";
1417
		return $tree;
1418
	}
1419

    
1420
		/* Even this should take childs in consideration */
1421
		function build_rules() {
1422

    
1423
				$pfq_rule = " queue ". $this->qname;
1424
				if ($this->GetInterface())
1425
						$pfq_rule .= " on ".convert_friendly_interface_to_real_interface_name($this->GetInterface());
1426
		if ($this->GetBandwidth() && $this->GetBwscale())
1427
						$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1428
					
1429
				if ($this->GetQpriority())
1430
						$pfq_rule .= " priority " . $this->GetQpriority();
1431
				if ($this->GetQlimit())
1432
						$pfq_rule .= " qlimit " . $this->GetQlimit();
1433
		  if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() || $this->GetLinkshare() || $this->GetUpperlimit()) {
1434
						$pfq_rule .= " hfsc ( ";
1435
						if ($this->GetRed()) {
1436
								$comma = 1;
1437
								$pfq_rule .= " red ";
1438
						}
1439
						if ($this->GetRio()) {
1440
								if ($comma) 
1441
										$pfq_rule .= " ,";
1442
								$comma = 1;
1443
								$pfq_rule .= " rio ";
1444
						}
1445
						if ($this->GetEcn()) {
1446
								if ($comma) 
1447
										$pfq_rule .= " ,";
1448
								$comma = 1;
1449
								$pfq_rule .= " ecn ";
1450
						}
1451
						if ($this->GetDefault()) {
1452
								if ($comma)
1453
										$pfq_rule .= " ,";
1454
								$comma = 1;
1455
								$pfq_rule .= " default ";
1456
						}
1457

    
1458
						if ($this->GetRealtime() <> "")  {
1459
				if ($comma) 
1460
									$pfq_rule .= " , ";
1461
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1462
			$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1463
				else  if ($this->GetR_m2() <> "")
1464
					$pfq_rule .= " realtime " . $this->GetR_m2();
1465
				$comma = 1;
1466
			}
1467
						if ($this->GetLinkshare() <> "") {
1468
								if ($comma)
1469
					$pfq_rule .= " ,";
1470
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1471
			$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1472
				else if ($this->GetL_m2() <> "")
1473
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1474
				$comma = 1;
1475
			}
1476
						if ($this->GetUpperlimit() <> "") {
1477
				if ($comma)
1478
					$pfq_rule .= " ,";
1479
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1480
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1481
				else if ($this->GetU_m2() <> "")
1482
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1483
			}
1484
						$pfq_rule .= " )\n ";
1485
					}
1486
					if (count($this->subqueues)) {
1487
						$i = count($this->subqueues);
1488
						$pfq_rule .= " { ";
1489
						foreach ($this->subqueues as $qkey => $qnone) {
1490
								if ($i > 1) {
1491
										$i--;
1492
										$pfq_rule .= " {$qkey}, ";
1493
								} else
1494
										$pfq_rule .= " {$qkey} ";
1495
								$pfq_rule .= " } \n";
1496
								foreach ($this->subqueues as $q)
1497
									$pfq_rule .= $q->build_rules();
1498
						}
1499
					}
1500

    
1501
				 $pfq_rule .= " \n";
1502
			
1503
				return $pfq_rule;
1504
		}
1505

    
1506
	function build_javascript() {
1507
		$javascript = parent::build_javascript();
1508
		$javascript .= "<script type=\"text/javascript\">";
1509
		$javascript .= "function enable_realtime(enable_over) { \n";
1510
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1511
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1512
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1513
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1514
		$javascript .= " } else { \n";
1515
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1516
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1517
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1518
		$javascript .= " } \n";
1519
		$javascript .= " } \n";
1520
		$javascript .= "function enable_linkshare(enable_over) { \n";
1521
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1522
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1523
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1524
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1525
		$javascript .= " } else { \n";
1526
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1527
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1528
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1529
		$javascript .= " } \n";
1530
		$javascript .= " } \n";
1531
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1532
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1533
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1534
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1535
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1536
		$javascript .= " } else { \n";
1537
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1538
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1539
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1540
		$javascript .= " } \n";
1541
			
1542
		$javascript .= "} \n";
1543
		$javascript .= "</script>";
1544

    
1545
		return $javascript;
1546
	}
1547

    
1548
		function build_form() {
1549
				$form = "<tr>";
1550
				$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
1551
				$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1552
				$form .= htmlspecialchars($this->GetBandwidth());
1553
				$form .= "\">";
1554
				$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1555
				$form .= "<option value=\"Gb\"";
1556
				if ($this->GetBwscale() == "Gb")
1557
						$form .= " selected=\"yes\"";
1558
				$form .= ">Gbit/s</option>";
1559
				$form .= "<option value=\"Mb\"";
1560
				if ($this->GetBwscale() == "Mb")
1561
						$form .= " selected=\"yes\"";
1562
				$form .= ">Mbit/s</option>";
1563
				$form .= "<option value=\"Kb\"";
1564
				if ($this->GetBwscale() == "Kb")
1565
						$form .= " selected=\"yes\"";
1566
				$form .= ">Kbit/s</option>";
1567
				$form .= "<option value=\"\"";
1568
				if ($this->GetBwscale() == "b")
1569
						$form .= " selected=\"yes\"";
1570
				$form .= ">Bit/s</option>";
1571
				$form .= "<option value=\"%\"";
1572
				if ($this->GetBwscale() == "%")
1573
						$form .= " selected=\"yes\"";
1574
				$form .= ">%</option>";
1575
				$form .= "</select> <br>";
1576
				$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
1577
				$form .= "</span></td>";
1578
				$form .= parent::build_form();
1579
				$form .= "<tr>";
1580
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Service Curve (sc)</td>";
1581
				$form .= "<td width=\"78%\" class=\"vtable\">";
1582
				$form .= "<table>";
1583
				$form .= "<tr><td>&nbsp;</td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>";
1584
				$form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\"";
1585
				if($this->GetUpperlimit() <> "") 
1586
					$form .=  " CHECKED ";
1587
				$form .= "onChange=\"enable_upperlimit()\"> Upperlimit:</td><td><input size=\"6\" value=\"";
1588
				$form .= htmlspecialchars($this->GetU_m1());
1589
				$form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" ";
1590
				if (!$this->GetUpperlimit()) $form .= " disabled";
1591
				$form .= "></td><td><input size=\"6\" value=\"";
1592
				$form .= htmlspecialchars($this->GetU_d());
1593
				$form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" ";
1594
		if (!$this->GetUpperlimit()) $form .= " disabled";
1595
		$form .= "></td><td><input size=\"6\" value=\"";
1596
				$form .= htmlspecialchars($this->GetU_m2());
1597
				$form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" ";
1598
		if (!$this->GetUpperlimit()) $form .= " disabled";
1599
		$form .= "></td><td>The maximum allowed bandwidth for the queue.</td></tr>";
1600
				$form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\"";
1601
				if($this->GetRealtime() <> "") 
1602
			$form .=  " CHECKED ";
1603
				$form .= "onChange=\"enable_realtime()\"> Real time:</td><td><input size=\"6\" value=\"";
1604
				$form .= htmlspecialchars($this->GetR_m1());
1605
				$form .= "\" id=\"realtime1\" name=\"realtime1\" ";
1606
		if (!$this->GetRealtime()) $form .= " disabled";
1607
		$form .= "></td><td><input size=\"6\" value=\"";
1608
				$form .= htmlspecialchars($this->GetR_d());
1609
				$form .= "\" id=\"realtime2\" name=\"realtime2\" ";
1610
		if (!$this->GetRealtime()) $form .= " disabled";
1611
		$form .= "></td><td><input size=\"6\" value=\"";
1612
				$form .= htmlspecialchars($this->GetR_m2());
1613
				$form .= "\" id=\"realtime3\" name=\"realtime3\" ";
1614
		if (!$this->GetRealtime()) $form .= " disabled";
1615
		$form .= "></td><td>The minimum required bandwidth for the queue.</td></tr>";
1616
				$form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" id=\"linkshare\" name=\"linkshare\"";
1617
				if($this->GetLinkshare() <> "") 
1618
			$form .=  " CHECKED ";
1619
				$form .= "onChange=\"enable_linkshare()\"> Link share:</td><td><input size=\"6\" value=\"";
1620
				$form .= htmlspecialchars($this->GetL_m1());
1621
				$form .= "\" id=\"linkshare1\" name=\"linkshare1\" ";
1622
		if (!$this->GetLinkshare()) $form .= " disabled";
1623
		$form .= "></td><td><input size=\"6\" value=\"";
1624
				$form .= htmlspecialchars($this->GetL_d());
1625
				$form .= "\" id=\"linkshare2\" name=\"linkshare2\" ";
1626
		if (!$this->GetLinkshare()) $form .= " disabled";
1627
		$form .= "></td><td><input size=\"6\" value=\"";
1628
				$form .= htmlspecialchars($this->GetL_m2());
1629
				$form .= "\" id=\"linkshare3\" name=\"linkshare3\" ";
1630
		if (!$this->GetLinkshare()) $form .= " disabled";
1631
		$form .= "></td><td>The bandwidth share of a backlogged queue - this overrides priority.</td></tr>";
1632
				$form .= "</table><br>";
1633
				$form .= "The format for service curve specifications is (m1, d, m2).  m2 controls";
1634
				$form .= "the bandwidth assigned to the queue.  m1 and d are optional and can be";
1635
				$form .= "used to control the initial bandwidth assignment.  For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value";
1636
				$form .= "given in m2.";
1637
				$form .= "</span></td>";
1638
				$form .= "</tr>";
1639

    
1640
				return $form;
1641
		}
1642

    
1643
	function update_altq_queue_data(&$data) { 
1644
		$this->ReadConfig($data);
1645
	}
1646

    
1647
	function wconfig() {
1648
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1649
		if (!is_array($cflink))
1650
			$cflink = array();
1651
			$cflink['name'] = $this->GetQname();
1652
			$cflink['interface'] = $this->GetInterface();
1653
			$cflink['qlimit'] = $this->GetQlimit();
1654
			$cflink['priority'] = $this->GetQpriority();
1655
			$cflink['description'] = $this->GetDescription();
1656
			$cflink['bandwidth'] = $this->GetBandwidth();
1657
			$cflink['bandwidthtype'] = $this->GetBwscale();
1658
			$cflink['enabled'] = $this->GetEnabled();
1659
			$cflink['default'] = $this->GetDefault();
1660
			$cflink['red'] = $this->GetRed();
1661
			$cflink['rio'] = $this->GetRio();
1662
			$cflink['ecn'] = $this->GetEcn();
1663
			if ($this->GetLinkshare() <> "" ) {
1664
				if ($this->GetL_m1() <> "") {
1665
					$cflink['linkshare1'] = $this->GetL_m1();
1666
					$cflink['linkshare2'] = $this->GetL_d();
1667
					$cflink['linkshare'] = "on";
1668
				}
1669
				if ($this->GetL_m2() <> "") {
1670
					$cflink['linkshare3'] = $this->GetL_m2();
1671
					$cflink['linkshare'] = "on";
1672
				}
1673
			}
1674
			if ($this->GetRealtime() <> "" ) {
1675
				if ($this->GetR_m1() <> "") {
1676
					$cflink['realtime1'] = $this->GetR_m1();
1677
					$cflink['realtime2'] = $this->GetR_d();
1678
					$cflink['realtime'] = "on";
1679
				}
1680
				if ($this->GetR_m2()) {
1681
					$cflink['realtime3'] = $this->GetR_m2();
1682
					$cflink['realtime'] = "on";
1683
				}
1684
			}
1685
			if ($this->GetUpperlimit() <> "") {
1686
				if ($this->GetU_m1() <> "") {
1687
					$cflink['upperlimit1'] = $this->GetU_m1();
1688
					$cflink['upperlimit2'] = $this->GetU_d();
1689
					$cflink['upperlimit'] = "on";
1690
				}
1691
				if ($this->GetU_m2()) {
1692
					$cflink['upperlimit3'] = $this->GetU_m2();
1693
					$cflink['upperlimit'] = "on";
1694
				}
1695
			}
1696
		}
1697
	}
1698

    
1699
class cbq_queue extends priq_queue {
1700
		var $qborrow;
1701

    
1702
	function GetBorrow() {
1703
		return $this->qborrow;
1704
	}
1705
	function SetBorrow($borrow) {
1706
		$this->qborrow = $borrow;
1707
	}
1708
	function CanHaveChilds() {
1709
			return true;
1710
	}
1711

    
1712
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1713

    
1714
		if (!is_array($this->subqueues))
1715
						$this->subqueues = array();
1716
		$q =& new cbq_queue();
1717
		$q->SetInterface($this->GetInterface());
1718
		$q->SetParent(&$this);
1719
		$q->ReadConfig($qname);
1720
                $q->validate_input($qname, $input_errors);
1721
                if (count($input_errors)) {
1722
                        return $q;
1723
                }
1724
                switch ($q->GetBwscale()) {
1725
                        case "%":
1726
                                $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1727
                                break;
1728
                        default:
1729
                                $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1730
                                break;
1731
                }
1732
                $q->SetAvailableBandwidth($myBw);
1733
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1734

    
1735
		$q->SetEnabled("on");
1736
		$q->SetLink($path);
1737
		$this->subqueues[$q->GetQName()] = &$q;
1738
		$GLOBALS['allqueue_list'][] = $q->GetQname();
1739
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1740
		if (is_array($qname['queue'])) {
1741
				foreach ($qname['queue'] as $key1 => $que) {
1742
						array_push($path, $key1);
1743
						$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1744
						array_pop($path);
1745
				}
1746
		}
1747

    
1748
		return $q;
1749
		}
1750
	
1751
		/*
1752
		 * Should search even its childs
1753
		 */
1754
		function &find_queue($interface, $qname) {
1755
				if ($qname == $this->GetQname())
1756
						return $this;
1757
				foreach ($this->subqueues as $q) {
1758
						$result =& $q->find_queue("", $qname);
1759
			if ($result)
1760
								return $result;
1761
				}
1762
		}
1763

    
1764
	function &find_parentqueue($interface, $qname) {
1765
				if ($this->subqueues[$qname])
1766
						return $this;
1767
				foreach ($this->subqueues as $q) {
1768
					$result = $q->find_parentqueue("", $qname);
1769
			if ($result)
1770
				return $result;
1771
		}
1772
		}
1773

    
1774
		function delete_queue() {
1775
			unref_on_altq_queue_list($this->GetQname());
1776
			if ($this->GetDefault())
1777
				altq_set_default_queue($this->GetInterface(), "false");
1778
			cleanup_queue_from_rules($this->GetQname());
1779
			foreach ($this->subqueues as $q)
1780
				$q->delete_queue();
1781
			$parent =& $this->GetParent();
1782
			$parent->CalculateRemainingBandwidth($this->GetBandwidth(), $this->GetBwscale(), "delete"); 			
1783
			unset_object_by_reference($this->subqueues[$qname]->GetLink());
1784
		}
1785
	
1786
	function validate_input($data, &$input_errors) {
1787
		parent::validate_input($data, $input_errors);
1788
		
1789
		if ($data['priority'] > 7)
1790
				$input_errors[] = "Priority must be an integer between 1 and 7.";
1791
		$reqfields[] = "bandwidth";
1792
		$reqdfieldsn[] = "Bandwidth";
1793
		$reqfields[] = "bandwidthtype";
1794
		$reqdfieldsn[] = "Bandwidthtype";
1795

    
1796
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1797
		
1798
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
1799
                 $input_errors[] = "Bandwidth must be an integer.";
1800

    
1801

    
1802
           if ($data['bandwidth'] < 0)
1803
                       $input_errors[] = "Bandwidth cannot be negative.";
1804

    
1805

    
1806
           if ($data['bandwidthtype'] == "%") {
1807
                 if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1808
                       $input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1809
           }
1810

    
1811
           $parent =& $this->GetParent();
1812
           switch ($data['bandwidthtype']) {
1813
                       case "%":
1814
                             $myBw = $parent->GetAvailableBandwidth() * intval($data['bandwidth']) / 100;
1815
                       default:
1816
                             $mybw = intval($data['bandwiddth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1817
                             break;
1818
           }
1819
                if ($parent->GetAvailableBandwidth() < intval($myBw))
1820
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
1821
	}
1822
		function ReadConfig(&$q) {
1823
				parent::ReadConfig($q);
1824
		if ($q['borrow'])
1825
			$this->SetBorrow("on");
1826
		}
1827
		
1828
	function build_javascript() {
1829
		return parent::build_javascript();
1830
	}
1831

    
1832
	function build_tree() {
1833
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
1834
			$tree .= "\" ";
1835
			if ($this->GetDefault())
1836
								$tree .= " class=\"navlnk\"";
1837
			$tree .= " >" . $this->GetQname() . "</a>";
1838
			if (is_array($this->subqueues)) {
1839
				$tree .= "<ul>";
1840
				foreach ($this->subqueues as $q)  {
1841
					$tree .= $q->build_tree();
1842
				}	
1843
				$tree .= "</ul>";
1844
			}
1845
			$tree .= "</li>";
1846
			return $tree;
1847
	}
1848
		
1849
	/* Even this should take childs in consideration */
1850
	function build_rules() {
1851
		   $pfq_rule = "queue ". $this->qname;
1852
			if ($this->GetInterface())
1853
					$pfq_rule .= " on ".convert_friendly_interface_to_real_interface_name($this->GetInterface());
1854
			if ($this->GetBandwidth() && $this->GetBwscale())
1855
					$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1856
			if ($this->GetQpriority())
1857
					$pfq_rule .= " priority " . $this->GetQpriority();
1858
			if ($this->GetQlimit())
1859
					$pfq_rule .= " qlimit " . $this->GetQlimit();
1860
			if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow()) {
1861
				$pfq_rule .= " cbq ( ";
1862
				if ($this->GetRed()) {
1863
						$comma = 1;
1864
						$pfq_rule .= " red ";
1865
				}
1866
				if ($this->GetRio()) {
1867
						if ($comma) 
1868
								$pfq_rule .= " ,";
1869
						$comma = 1;
1870
						$pfq_rule .= " rio ";
1871
				}
1872
				if ($this->GetEcn()) {
1873
						if ($comma) 
1874
								$pfq_rule .= " ,";
1875
						$comma = 1;
1876
						$pfq_rule .= " ecn ";
1877
				}
1878
				if ($this->GetDefault()) {
1879
						if ($comma)
1880
								$pfq_rule .= " ,";
1881
						$comma = 1;
1882
						$pfq_rule .= " default ";
1883
				}
1884
				if ($this->GetBorrow()) {
1885
					if ($comma)
1886
						$pfq_rule .= ", ";
1887
					$pfq_rule .= " borrow ";
1888
				}
1889
				$pfq_rule .= " ) ";
1890
			} 
1891
			if (count($this->subqueues)) {
1892
					$i = count($this->subqueues);
1893
					$pfq_rule .= " { ";
1894
					foreach ($this->subqueues as $qkey => $qnone) {
1895
							if ($i > 1) {
1896
									$i--;
1897
									$pfq_rule .= " {$qkey}, ";
1898
							} else
1899
									$pfq_rule .= " {$qkey} ";
1900
					}
1901
					$pfq_rule .= " } \n";
1902
					foreach ($this->subqueues as $q)
1903
							$pfq_rule .= $q->build_rules();
1904
			}
1905

    
1906
			$pfq_rule .= " \n";
1907
			return $pfq_rule;
1908
	}
1909

    
1910
	function build_form() {
1911
		$form = "<tr>";
1912
		$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
1913
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1914
		if ($this->GetBandwidth() > 0)
1915
				$form .= htmlspecialchars($this->GetBandwidth());
1916
		$form .= "\">";
1917
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1918
		$form .= "<option value=\"Gb\"";
1919
		if ($this->GetBwscale() == "Gb")
1920
				$form .= " selected=\"yes\"";
1921
		$form .= ">Gbit/s</option>";
1922
		$form .= "<option value=\"Mb\"";
1923
		if ($this->GetBwscale() == "Mb")
1924
				$form .= " selected=\"yes\"";
1925
		$form .= ">Mbit/s</option>";
1926
		$form .= "<option value=\"Kb\"";
1927
		if ($this->GetBwscale() == "Kb")
1928
				$form .= " selected=\"yes\"";
1929
		$form .= ">Kbit/s</option>";
1930
		$form .= "<option value=\"\"";
1931
		if ($this->GetBwscale() == "b")
1932
				$form .= " selected=\"yes\"";
1933
		$form .= ">Bit/s</option>";
1934
		$form .= "<option value=\"%\"";
1935
		if ($this->GetBwscale() == "%")
1936
				$form .= " selected=\"yes\"";
1937
		$form .= ">%</option>";
1938
		$form .= "</select> <br>";
1939
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
1940
		$form .= "</span></td></tr>";
1941
		$form .= parent::build_form();
1942
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
1943
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
1944
			if($this->GetBorrow() == "on") 
1945
		$form .=  " CHECKED ";
1946
		$form .= "> Borrow from other queues when available<br></td></tr>";
1947

    
1948
		return $form;
1949
	}
1950

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

    
1955
	function wconfig() {
1956
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1957
				if (!is_array($cflink))
1958
						$cflink = array();
1959
				$cflink['interface'] = $this->GetInterface();
1960
				$cflink['qlimit'] = $this->GetQlimit();
1961
				$cflink['priority'] = $this->GetQpriority();
1962
				$cflink['name'] = $this->GetQname();
1963
				$cflink['description'] = $this->GetDescription();
1964
				$cflink['bandwidth'] = $this->GetBandwidth();
1965
				$cflink['bandwidthtype'] = $this->GetBwscale();
1966
				$cflink['enabled'] = $this->GetEnabled();
1967
				$cflink['default'] = $this->GetDefault();
1968
				$cflink['red'] = $this->GetRed();
1969
				$cflink['rio'] = $this->GetRio();
1970
				$cflink['ecn'] = $this->GetEcn();
1971
				$cflink['borrow'] = $this->GetBorrow();
1972
		}
1973
}
1974

    
1975

    
1976

    
1977

    
1978
/*
1979
 * XXX: TODO Make a class shaper to hide all these function
1980
 * from the global namespace.
1981
 */
1982

    
1983
/* 
1984
 * This is a layer violation but for now there is no way 
1985
 * i can find to properly do this with PHP.
1986
 */
1987
function altq_set_default_queue($interface, $value) {
1988
	global $altq_list_queues;
1989
		
1990
	$altq_tmp =& $altq_list_queues[$interface];
1991
	if ($altq_tmp) {
1992
		if ($value) {
1993
			$altq_tmp->SetDefaultQueuePresent("true");
1994
		}
1995
		else {
1996
			$altq_tmp->SetDefaultQueuePresent("false");
1997
		}
1998
	}
1999
}
2000

    
2001
function altq_get_default_queue($interface) {
2002
	global $altq_list_queues;
2003

    
2004
	$altq_tmp = $altq_list_queues[$interface];
2005
	if ($altq_tmp)  
2006
		return $altq_tmp->GetDefaultQueuePresent(); 
2007
}
2008

    
2009
function get_is_ftp_queue($interface, $qname) {
2010
	global $config;
2011

    
2012
	if (isset($config['interfaces'][$interface]['ftpqueue']) &&
2013
		$config['interfaces'][$interface]['ftpqueue'] == $qname)
2014
		return true;
2015
	return false;
2016
}
2017

    
2018
function set_is_ftp_queue($interface, $qname) {
2019
	global $config;
2020

    
2021
	if (!is_array($config['interfaces'][$interface]['ftpqueue']))
2022
		$config['interfaces'][$interface]['ftpqueue'] = array();
2023
	$config['interfaces'][$interface]['ftpqueue'] = $qname;
2024
}
2025

    
2026
function ref_on_altq_queue_list($parent, $qname) {
2027
	if (isset($GLOBALS['queue_list'][$qname]))
2028
		$GLOBALS['queue_list'][$qname]++;
2029
	else
2030
		$GLOBALS['queue_list'][$qname] = 1;
2031

    
2032
	unref_on_altq_queue_list($parent);
2033
}
2034

    
2035
function unref_on_altq_queue_list($qname) {
2036
	$GLOBALS['queue_list'][$qname]--;
2037
	if ($GLOBALS['queue_list'][$qname] <= 1)
2038
		unset($GLOBALS['queue_list'][$qname]);	
2039
}
2040

    
2041
function read_altq_config() {
2042
	global $altq_list_queues, $config;
2043
	$path = array();
2044
	
2045
	$a_int = &$config['shaper']['queue'];
2046

    
2047
	$altq_list_queues = array();
2048
	
2049
	$GLOBALS['allqueue_list'] = array();
2050
	
2051
	if (!is_array($config['shaper']['queue']))
2052
		return;
2053

    
2054
	foreach ($a_int as $key => $conf) {
2055
				$int = $conf['interface'];
2056
				$root =& new altq_root_queue();
2057
				$root->SetInterface($int);
2058
				$altq_list_queues[$root->GetInterface()] = &$root;
2059
				$root->ReadConfig($conf);
2060
		array_push($path, $key);
2061
		$root->SetLink($path);
2062
		$GLOBALS['allqueue_list'][] = $root->GetQname();
2063
		if (is_array($conf['queue'])) {
2064
			foreach ($conf['queue'] as $key1 => $q) {
2065
				array_push($path, $key1);
2066
				/* 
2067
				 * XXX: we compeletely ignore errors here but anyway we must have 
2068
				 *	checked them before so no harm should be come from this.
2069
				 */
2070
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
2071
				array_pop($path);
2072
			} 	
2073
				}
2074
		array_pop($path);
2075
	}
2076
}
2077

    
2078

    
2079

    
2080
function get_interface_list_to_show() {
2081
	global $altq_list_queues, $config;
2082
		
2083
	$tree = "";
2084
	foreach ($config['interfaces'] as $if => $ifdesc) {
2085
		if ($altq_list_queues[$if])
2086
			continue;
2087
		else  {
2088
			if (!is_altq_capable($ifdesc['if'])) 
2089
				continue;
2090
			if (!isset($ifdesc['enable']) && $if != "lan" && $if != "wan")
2091
				continue;
2092
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$if."&action=add\">".$if."</a></li>";
2093
		}
2094
	}
2095
	
2096
	return $tree;
2097
}
2098

    
2099
function filter_generate_altq_queues() {
2100
	global $altq_list_queues;
2101
	
2102
	read_altq_config();
2103

    
2104
	$altq_rules = "";
2105
	foreach ($altq_list_queues as $altq) 
2106
		$altq_rules .= $altq->build_rules();
2107

    
2108
	return $altq_rules;
2109
}
2110

    
2111

    
2112
function build_iface_without_this_queue($iface, $qname) {
2113
	global $g, $altq_list_queues;
2114

    
2115
	$altq =& $altq_list_queues[$iface];
2116
				if ($altq)
2117
						$scheduler = ": " . $altq->GetScheduler();
2118
	$form = "<tr><td width=\"20%\" >";
2119
	$form .= "<a href=\"firewall_shaper.php?interface" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
2120
		$form .= "</td></tr>";
2121
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
2122
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
2123
		$form .= $iface . "&queue=". $qname . "&action=add\">";
2124
		$form .= "<img src=\"";
2125
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
2126
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Activate queue on this interface\">";
2127
		$form .= " Activate queue on this interface</a></td></tr>";
2128

    
2129
		return $form;
2130

    
2131
}
2132

    
2133

    
2134
$default_shaper_msg =	"<tr><td width=\"80%\" >";
2135
$default_shaper_msg .= "<strong>Welcome to the pfSense Traffic Shaper.";
2136
$default_shaper_msg .= "The tree on the left helps you navigate through the";
2137
$default_shaper_msg .= "queues while the buttons at the bottom, which show actions, are activated accordingly";
2138
$default_shaper_ms .= " as allowed</strong>";
2139
$default_shaper_msg .= "</td></tr>";
2140

    
2141
?>
(20-20/29)