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 $available_bw; /* in b/s */
235

    
236
	/* Accesor functions */
237
	function GetAvailableBandwidth() {
238
		return $this->available_bw;
239
	}
240
	function SetAvailableBandwidth($bw) {
241
		$this->available_bw = $bw;
242
	}
243
	function GetDefaultQueuePresent() {
244
		if (!empty($this->queues)) {
245
			foreach ($this->queues as $q) {
246
				if ($q->GetDefault())
247
					return true;
248
			}
249
		}
250

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

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

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

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

    
385
	function &get_queue_list($q = null) {
386
		$qlist = array();
387

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

    
396
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
397

    
398
		if (!is_array($this->queues))
399
			$this->queues = array();
400

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

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

    
452
		return $q;
453
	}
454

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

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

    
481
	function build_tree() {
482
		global $shaperIFlist;
483

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

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

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

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

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

    
580
		return $javascript;
581
	}
582
	
583
	function build_shortform() {
584
		global $g;
585

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

    
605
		return $form;
606

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

    
694

    
695
		return $form;
696
	}
697

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

    
726
}
727

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

    
747
	/* This is here to help with form building and building rules/lists */
748
	var $subqueues = array();
749

    
750
	/* Accesor functions */
751
	function GetAvailableBandwidth() {
752
		return $this->available_bw;
753
	}
754
	function SetAvailableBandwidth($bw) {
755
		$this->available_bw = $bw;
756
	}
757
	function SetLink($link) {
758
		$this->link = $link;
759
	}
760
	function GetLink() {
761
		return $this->link;
762
	}
763
	function &GetParent() {
764
		return $this->qparent;
765
	}
766
	function SetParent(&$parent) {
767
		$this->qparent = &$parent;
768
	}
769
	function GetEnabled() {
770
		return $this->qenabled;
771
	}
772
	function SetEnabled($value) {
773
		$this->qenabled = $value;
774
	}
775
	function CanHaveChildren() {
776
		return false;
777
	}
778
	function CanBeDeleted() {
779
		return true;
780
	}
781
	function GetQname() {
782
		return $this->qname;
783
	}
784
	function SetQname($name) {
785
		$this->qname = trim($name);
786
	}
787
	function GetBandwidth() {
788
		return $this->qbandwidth;
789
	}
790
	function SetBandwidth($bandwidth) {
791
		$this->qbandwidth = $bandwidth;
792
	}
793
	function GetInterface() {
794
		return $this->qinterface;
795
	}
796
	function SetInterface($name) {
797
		$this->qinterface = trim($name);
798
	}
799
	function GetQlimit() {
800
		return $this->qlimit;
801
	}
802
	function SetQlimit($limit) {
803
		$this->qlimit = $limit;
804
	}
805
	function GetQpriority() {
806
		return $this->qpriority;
807
	}
808
	function SetQpriority($priority) {
809
		$this->qpriority = $priority;
810
	}
811
	function GetDescription() {
812
		return $this->description;
813
	}
814
	function SetDescription($str) {
815
		$this->description = trim($str);
816
	}
817
	function GetFirstime() {
818
		return $this->firsttime;
819
	}
820
	function SetFirsttime($number) {
821
		$this->firsttime = $number;
822
	}
823
	function GetBwscale() {
824
		return $this->qbandwidthtype;
825
	}
826
	function SetBwscale($scale) {
827
		$this->qbandwidthtype = $scale;
828
	}
829
	function GetDefaultQueuePresent() {
830
		if ($this->GetDefault())
831
			return true;
832
		if (!empty($this->subqueues)) {
833
			foreach ($this->subqueues as $q) {
834
				if ($q->GetDefault())
835
					return true;
836
			}
837
		}
838

    
839
		return false;
840
	}
841
	function GetDefault() {
842
		return $this->qdefault;
843
	}
844
	function SetDefault($value = false) {
845
		$this->qdefault = $value;
846
	}
847
	function GetRed() {
848
		return $this->qred;
849
	}
850
	function SetRed($red = false) {
851
		$this->qred = $red;
852
	}
853
	function GetRio() {
854
		return $this->qrio;
855
	}
856
	function SetRio($rio = false) {
857
		$this->qrio = $rio;
858
	}
859
	function GetEcn() {
860
		return $this->qecn;
861
	}
862
	function SetEcn($ecn = false) {
863
		$this->qecn = $ecn;
864
	}
865
	function GetAck() {
866
		return $this->qack;
867
	}
868
	function SetAck($ack = false) {
869
		$this->qack = $ack;
870
	}
871

    
872
	function build_javascript() {
873
		$javascript = "<script type=\"text/javascript\">";
874
		$javascript .= "function mySuspend() { \n";
875
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
876
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
877
		$javascript .= "else if (document.all)\n";
878
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
879
		$javascript .= "}\n";
880

    
881
		$javascript .= "function myResume() {\n";
882
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
883
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
884
		$javascript .= "else if (document.all)\n";
885
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
886
		$javascript .= "}\n";
887
		$javascript .= "</script>";
888
		
889
		return $javascript;
890
	}
891
	
892
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
893

    
894
	/* 
895
	 * Currently this will not be called unless we decide to clone a whole 
896
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
897
	 */
898
	 function copy_queue($interface, &$cflink) {
899

    
900
 		$cflink['name'] = $this->GetQname();
901
                $cflink['interface'] = $interface;
902
                $cflink['qlimit'] = $this->GetQlimit();
903
                $cflink['priority'] = $this->GetQpriority();
904
                $cflink['description'] = $this->GetDescription();
905
                $cflink['enabled'] = $this->GetEnabled();
906
                $cflink['default'] = $this->GetDefault();
907
                $cflink['red'] = $this->GetRed();
908
                $cflink['rio'] = $this->GetRio();
909
                $cflink['ecn'] = $this->GetEcn();
910

    
911
                if (is_array($this->subqueues)) {
912
                        $cflinkp['queue'] = array();
913
                        foreach ($this->subqueues as $q) {
914
				 $cflink['queue'][$q->GetQname()] = array();
915
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
916
			}
917
                }
918

    
919
	 }
920

    
921
	function clean_queue($sched) {
922
		clean_child_queues($sched, $this->GetLink());
923
		if (is_array($this->subqueues)) {
924
			foreach ($this->subqueues as $q)
925
				$q->clean_queue($sched);
926
		}
927
	}
928

    
929
        function &get_queue_list(&$qlist) {
930
		
931
		$qlist[$this->GetQname()] = & $this;
932
		if (is_array($this->subqueues)) {
933
			foreach ($this->subqueues as $queue)
934
				$queue->get_queue_list($qlist);
935
		}
936
	}
937

    
938
	function delete_queue() {
939
		unref_on_altq_queue_list($this->GetQname());
940
		cleanup_queue_from_rules($this->GetQname());
941
		unset_object_by_reference($this->GetLink());
942
	}
943
	
944
	function delete_all() {
945
                if (count($this->subqueues)) {
946
                        foreach ($this->subqueues as $q) {
947
                                $q->delete_all();
948
                                unset_object_by_reference($q->GetLink());
949
                                unset($q);
950
                        }
951
                        unset($this->subqueues);
952
                }
953
        }
954

    
955
	 function &find_queue($interface, $qname) { 
956
		if ($qname == $this->GetQname())
957
			return $this; 
958
	}
959
	
960
	function find_parentqueue($interface, $qname) { return; }
961
		
962
	function validate_input($data, &$input_errors) {
963
	
964
		$reqdfields[] = "name";
965
		$reqdfieldsn[] = "Name";
966
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
967

    
968
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
969
			$input_errors[] = "Bandwidth must be an integer.";
970
                if ($data['bandwidth'] < 0)
971
			$input_errors[] = "Bandwidth cannot be negative.";
972
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
973
			$input_errors[] = "Qlimit must be an integer.";
974
	 	if ($data['qlimit'] < 0)
975
			$input_errors[] = "Qlimit must be an positive.";
976
		if ($data['priority'] && (!is_numeric($data['priority'])
977
		    || ($data['priority'] < 1) || ($data['priority'] > 15))) {
978
			$input_errors[] = "The priority must be an integer between 1 and 15.";
979
		}
980
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
981
				$input_errors[] = "Queue limit must be an integer";
982
		if ($data['qlimit'] < 0)
983
				$input_errors[] = "Queue limit must be positive";
984
		if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['newname']))
985
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
986
		if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
987
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
988
		if (!empty($data['default']) && altq_get_default_queue($data['interface']))
989
			$input_errors[] = "Only one default queue per interface is allowed.";
990
	}
991

    
992
	function ReadConfig(&$q) {
993
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
994
			$this->SetQname($q['newname']);
995
		} else if (!empty($q['newname'])) {
996
			$this->SetQname($q['newname']);
997
		} else if (isset($q['name']))
998
			$this->SetQname($q['name']);
999
		if (isset($q['interface']))
1000
			$this->SetInterface($q['interface']);
1001
		$this->SetBandwidth($q['bandwidth']);
1002
		if ($q['bandwidthtype'] <> "")
1003
			$this->SetBwscale($q['bandwidthtype']);
1004
		if (!empty($q['qlimit']))
1005
			$this->SetQlimit($q['qlimit']);
1006
		else
1007
			$this->SetQlimit(""); // Default
1008
		if (!empty($q['priority']))
1009
			$this->SetQPriority($q['priority']);
1010
		else
1011
			$this->SetQpriority("");
1012
		if (!empty($q['description']))
1013
			$this->SetDescription($q['description']);
1014
		else
1015
			$this->SetDescription("");
1016
		if (!empty($q['red']))
1017
			$this->SetRed($q['red']);
1018
		else
1019
			$this->SetRed();
1020
		if (!empty($q['rio']))
1021
			$this->SetRio($q['rio']);
1022
		else
1023
			$this->SetRio();
1024
		if (!empty($q['ecn']))
1025
			$this->SetEcn($q['ecn']);
1026
		else
1027
			$this->SetEcn();
1028
		if (!empty($q['default']))
1029
			$this->SetDefault($q['default']);
1030
		else
1031
			$this->SetDefault();
1032
		if (!empty($q['enabled']))
1033
			$this->SetEnabled($q['enabled']);
1034
		else
1035
			$this->SetEnabled("");
1036

    
1037
	}
1038

    
1039
	function build_tree() {
1040
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
1041
		$tree .= "\" ";
1042
		$tmpvalue = $this->GetDefault();
1043
		if (!empty($tmpvalue))
1044
			$tree .= " class=\"navlnk\"";
1045
		$tree .= " >" . $this->GetQname() . "</a>";
1046
		/* 
1047
		 * Not needed here!
1048
		 * if (is_array($queues) {
1049
		 *	  $tree .= "<ul>";
1050
		 *	  foreach ($q as $queues) 
1051
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1052
		 *	  endforeach	
1053
		 *	  $tree .= "</ul>";
1054
		 * }
1055
		 */
1056

    
1057
		$tree .= "</li>"; 
1058

    
1059
		return $tree;
1060
	}
1061
		
1062
	/* Should return something like:
1063
	 * queue $qname on $qinterface bandwidth ....
1064
	 */
1065
	function build_rules(&$default = false) {
1066
		$pfq_rule = " queue ". $this->qname;
1067
		if ($this->GetInterface())
1068
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1069
		$tmpvalue = $this->GetQpriority();
1070
		if (!empty($tmpvalue))
1071
			$pfq_rule .= " priority ".$this->GetQpriority();
1072
		$tmpvalue = $this->GetQlimit();
1073
		if (!empty($tmpvalue))
1074
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1075
		if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
1076
			$pfq_rule .= " priq ( ";
1077
			$tmpvalue = $this->GetRed();
1078
			if (!empty($tmpvalue)) {
1079
				$comma = 1;
1080
				$pfq_rule .= " red ";
1081
			}
1082
			$tmpvalue = $this->GetRio();
1083
			if (!empty($tmpvalue)) {
1084
				if ($comma) 
1085
					$pfq_rule .= " ,";
1086
				$comma = 1;
1087
				$pfq_rule .= " rio ";
1088
			}
1089
			$tmpvalue = $this->GetEcn();
1090
			if (!empty($tmpvalue)) {
1091
				if ($comma) 
1092
					$pfq_rule .= " ,";
1093
				$comma = 1;
1094
				$pfq_rule .= " ecn ";
1095
			}
1096
			$tmpvalue = $this->GetDefault();
1097
			if (!empty($tmpvalue)) {
1098
				if ($comma)
1099
					$pfq_rule .= " ,";
1100
				$pfq_rule .= " default ";
1101
				$default = true;
1102
			}
1103
			$pfq_rule .= " ) ";
1104
		}
1105

    
1106
		$pfq_rule .= " \n";
1107

    
1108
		return $pfq_rule;
1109
	}
1110

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

    
1188
		return $form;
1189
	}
1190

    
1191
	function build_shortform() {
1192
		/* XXX: Hacks in site. Mostly layer violations!  */
1193
		global $g, $altq_list_queues;
1194
		global $shaperIFlist;
1195
		
1196
		$altq =& $altq_list_queues[$this->GetInterface()];
1197
		if ($altq)
1198
			$scheduler = ": " . $altq->GetScheduler();
1199
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
1200
		$form .= "<a href=\"firewall_shaper.php?interface=" . $this->GetInterface() . "&queue=" . $this->GetQname()."&action=show\">". $shaperIFlist[$this->GetInterface()] .$scheduler."</a>";
1201
		$form .= "</td></tr>";
1202
		/* 
1203
		 * XXX: Hack in sight maybe fix with a class that wraps all
1204
		 * of this layer violations
1205
		 */
1206
		$form .= "<tr>";
1207
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1208
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
1209
		$form .= "</td><td width=\"50%\"></td></tr>";
1210
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1211
		$tmpvalue = $this->GetQpriority();
1212
		if (!empty($tmpvalue))
1213
			$form .= "Priority: on </td></tr>";
1214
		$tmpvalue = $this->GetDefault();
1215
		if (!empty($tmpvalue))
1216
			$form .= "<tr><td class=\"vncellreq\">Default: on </td></tr>";
1217
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1218
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1219
		$form .= $this->GetInterface() . "&queue=";
1220
		$form .= $this->GetQname() . "&action=delete\">";
1221
		$form .= "<img src=\"";
1222
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1223
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Delete queue from interface\">";
1224
		$form .= "<span>Delete queue from interface</span></a></td></tr>";
1225
		
1226
		return $form;
1227

    
1228
	}
1229

    
1230
		function update_altq_queue_data(&$q) { 
1231
		$this->ReadConfig($q);
1232
	}
1233

    
1234
	function wconfig() {
1235
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1236
		if (!is_array($cflink))
1237
			$cflink = array();
1238
		$cflink['name'] = $this->GetQname();
1239
		$cflink['interface'] = $this->GetInterface();
1240
		$cflink['qlimit'] = trim($this->GetQlimit());
1241
		if (empty($cflink['qlimit']))
1242
			unset($cflink['qlimit']);
1243
		$cflink['priority'] = trim($this->GetQpriority());
1244
		if (empty($cflink['priority']))
1245
			unset($cflink['priority']);
1246
		$cflink['description'] = trim($this->GetDescription());
1247
		if (empty($cflink['description']))
1248
			unset($cflink['description']);
1249
		$cflink['enabled'] = trim($this->GetEnabled());
1250
		if (empty($cflink['enabled']))
1251
			unset($cflink['enabled']);
1252
		$cflink['default'] = trim($this->GetDefault());
1253
		if (empty($cflink['default']))
1254
			unset($cflink['default']);
1255
		$cflink['red'] = trim($this->GetRed());
1256
		if (empty($cflink['red']))
1257
			unset($cflink['red']);
1258
		$cflink['rio'] = trim($this->GetRio());
1259
		if (empty($cflink['rio']))
1260
			unset($cflink['rio']);
1261
		$cflink['ecn'] = trim($this->GetEcn());
1262
		if (empty($cflink['ecn']))
1263
			unset($cflink['ecn']);
1264
	}
1265
}
1266

    
1267
class hfsc_queue extends priq_queue {
1268
	/* realtime */
1269
	var $realtime;
1270
	var $r_m1;
1271
	var $r_d;
1272
	var $r_m2;
1273
	/* linkshare */
1274
	var $linkshare;
1275
	var $l_m1;
1276
	var $l_d;
1277
	var $l_m2;
1278
	/* upperlimit */
1279
	var $upperlimit;
1280
	var $u_m1;
1281
	var $u_d;
1282
	var $u_m2;
1283

    
1284
	/*
1285
	 * HFSC can have nested queues.
1286
	 */
1287
	function CanHaveChildren() {
1288
		return true;
1289
	}
1290
	function GetRealtime() {
1291
           return $this->realtime;
1292
	}
1293
	function GetR_m1() {
1294
		return $this->r_m1;
1295
	}
1296
	function GetR_d() {
1297
		return $this->r_d;
1298
	}
1299
	function GetR_m2() {
1300
		return $this->r_m2;
1301
	}
1302
	function SetRealtime() {
1303
		$this->realtime = "on";
1304
	}
1305
	function DisableRealtime() {
1306
		$this->realtime = "";
1307
	}
1308
	function SetR_m1($value) {
1309
		$this->r_m1 = $value;
1310
	}
1311
	function SetR_d($value) {
1312
		$this->r_d = $value;
1313
	}
1314
	function SetR_m2($value) {
1315
		$this->r_m2 = $value;
1316
	}
1317
	function GetLinkshare() {
1318
		return $this->linkshare;
1319
	}
1320
	function DisableLinkshare() {
1321
		$this->linkshare = "";
1322
	}
1323
	function GetL_m1() {
1324
		return $this->l_m1;
1325
	}
1326
	function GetL_d() {
1327
		return $this->l_d;
1328
	}
1329
	function GetL_m2() {
1330
		return $this->l_m2;
1331
	}
1332
	function SetLinkshare() {
1333
		$this->linkshare = "on";
1334
	}
1335
	function SetL_m1($value) {
1336
		$this->l_m1 = $value;
1337
	}
1338
	function SetL_d($value) {
1339
		$this->l_d = $value;
1340
	}
1341
	function SetL_m2($value) {
1342
		$this->l_m2 = $value;
1343
	}
1344
	function GetUpperlimit() {
1345
		return $this->upperlimit;
1346
	}
1347
	function GetU_m1() {
1348
		return $this->u_m1;
1349
	}
1350
	function GetU_d() {
1351
		return $this->u_d;
1352
	}
1353
	function GetU_m2() {
1354
		return $this->u_m2;
1355
	}
1356
	function SetUpperlimit() {
1357
		$this->upperlimit = "on";
1358
	}
1359
	function DisableUpperlimit() {
1360
		$this->upperlimit = "";
1361
	}
1362
	function SetU_m1($value) {
1363
		$this->u_m1 = $value;
1364
	}
1365
	function SetU_d($value) {
1366
		$this->u_d = $value;
1367
	}
1368
	function SetU_m2($value) {
1369
		$this->u_m2 = $value;
1370
	}
1371

    
1372
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1373

    
1374
		if (!is_array($this->subqueues))
1375
			$this->subqueues = array();
1376
		$q =& new hfsc_queue();
1377
		$q->SetInterface($this->GetInterface());
1378
		$q->SetParent(&$this);
1379
		$q->ReadConfig($qname);
1380
		$q->validate_input($qname, $input_errors);
1381
		if (count($input_errors)) {
1382
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
1383
			return $q;
1384
		}
1385

    
1386
		$q->SetEnabled("on");
1387
		$q->SetLink($path);
1388
		switch ($q->GetBwscale()) {
1389
		case "%":
1390
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1391
			break;
1392
		default:
1393
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1394
			break;
1395
		}
1396
		$q->SetAvailableBandwidth($myBw);
1397
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1398

    
1399
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1400
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1401
		if (is_array($qname['queue'])) {
1402
			foreach ($qname['queue'] as $key1 => $que) {
1403
				array_push($path, $key1);
1404
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1405
				array_pop($path);
1406
			}
1407
		}
1408
	
1409
		return $q;
1410
	}
1411

    
1412
        function copy_queue($interface, &$cflink) {
1413

    
1414
		$cflink['name'] = $this->GetQname();
1415
		$cflink['interface'] = $interface;
1416
		$cflink['qlimit'] = trim($this->GetQlimit());
1417
		if (empty($cflink['qlimit']))
1418
			unset($cflink['qlimit']);
1419
		$cflink['priority'] = trim($this->GetQpriority());
1420
		if (empty($cflink['priority']))
1421
			unset($cflink['priority']);
1422
		$cflink['description'] = trim($this->GetDescription());
1423
		if (empty($cflink['description']))
1424
			unset($cflink['description']);
1425
		$cflink['bandwidth'] = $this->GetBandwidth();
1426
		$cflink['bandwidthtype'] = $this->GetBwscale();
1427
		$cflink['enabled'] = trim($this->GetEnabled());
1428
		if (empty($cflink['enabled']))
1429
			unset($cflink['enabled']);
1430
		$cflink['default'] = trim($this->GetDefault());
1431
		if (empty($cflink['default']))
1432
			unset($cflink['default']);
1433
		$cflink['red'] = trim($this->GetRed());
1434
		if (empty($cflink['red']))
1435
			unset($cflink['red']);
1436
		$cflink['rio'] = trim($this->GetRio());
1437
		if (empty($cflink['rio']))
1438
			unset($cflink['rio']);
1439
		$cflink['ecn'] = trim($this->GetEcn());
1440
		if (empty($cflink['ecn']))
1441
			unset($cflink['ecn']);
1442
		if ($this->GetLinkshare() <> "") {
1443
			if ($this->GetL_m1() <> "") {
1444
				$cflink['linkshare1'] = $this->GetL_m1();
1445
				$cflink['linkshare2'] = $this->GetL_d();
1446
				$cflink['linkshare'] = "on";
1447
			} else {
1448
				unset($cflink['linkshare1']);
1449
				unset($cflink['linkshare2']);
1450
				unset($cflink['linkshare']);
1451
			}
1452
			if ($this->GetL_m2() <> "") {
1453
				$cflink['linkshare3'] = $this->GetL_m2();
1454
				$cflink['linkshare'] = "on";
1455
			} else {
1456
				unset($cflink['linkshare3']);
1457
				unset($cflink['linkshare']);
1458
			}
1459
		}
1460
		if ($this->GetRealtime() <> "") {
1461
			if ($this->GetR_m1() <> "") {
1462
				$cflink['realtime1'] = $this->GetR_m1();
1463
				$cflink['realtime2'] = $this->GetR_d();
1464
				$cflink['realtime'] = "on";
1465
			} else {
1466
				unset($cflink['realtime1']);
1467
                                unset($cflink['realtime2']);
1468
                                unset($cflink['realtime']);
1469
			}
1470
			if ($this->GetR_m2() <> "") {
1471
				$cflink['realtime3'] = $this->GetR_m2();
1472
				$cflink['realtime'] = "on";
1473
			} else {
1474
				unset($cflink['realtime3']);
1475
				unset($cflink['realtime']);
1476
			}
1477
		}
1478
		if ($this->GetUpperlimit() <> "") {
1479
			if ($this->GetU_m1() <> "") {
1480
				$cflink['upperlimit1'] = $this->GetU_m1();
1481
				$cflink['upperlimit2'] = $this->GetU_d();
1482
				$cflink['upperlimit'] = "on";
1483
			} else {
1484
				unset($cflink['upperlimit']);
1485
				unset($cflink['upperlimit1']);
1486
				unset($cflink['upperlimit2']);
1487
			}
1488
			if ($this->GetU_m2() <> "") {
1489
				$cflink['upperlimit3'] = $this->GetU_m2();
1490
				$cflink['upperlimit'] = "on";
1491
			} else {
1492
				unset($cflink['upperlimit3']);
1493
				unset($cflink['upperlimit']);
1494
			}
1495
		}
1496

    
1497
		if (is_array($this->subqueues)) {
1498
			$cflinkp['queue'] = array();
1499
			foreach ($this->subqueues as $q) {
1500
				$cflink['queue'][$q->GetQname()] = array();
1501
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1502
			}
1503
		}
1504
	}
1505

    
1506
	function delete_queue() { 
1507
		unref_on_altq_queue_list($this->GetQname());
1508
		cleanup_queue_from_rules($this->GetQname());
1509
		$parent =& $this->GetParent();
1510
		foreach ($this->subqueues as $q)  {
1511
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1512
			$q->delete_queue();
1513
		}
1514
		unset_object_by_reference($this->GetLink());
1515
	}
1516

    
1517
	/*
1518
	 * Should search even its children
1519
	 */
1520
	function &find_queue($interface, $qname) {
1521
		if ($qname == $this->GetQname()) 
1522
			return $this;
1523

    
1524
		foreach ($this->subqueues as $q) {
1525
			$result =& $q->find_queue("", $qname);
1526
			if ($result)
1527
				return $result;
1528
		}
1529
	}
1530

    
1531
	function &find_parentqueue($interface, $qname) {
1532
		if ($this->subqueues[$qname]) 
1533
			return $this;
1534
		foreach ($this->subqueues as $q) {
1535
			$result = $q->find_parentqueue("", $qname);
1536
			if ($result)
1537
				return $result;
1538
		}
1539
	}
1540
	
1541
	function validate_input($data, &$input_errors) {
1542
		parent::validate_input($data, $input_errors);
1543
		
1544
		$reqdfields[] = "bandwidth";
1545
		$reqdfieldsn[] = "Bandwidth";
1546
		$reqdfields[] = "bandwidthtype";
1547
		$reqdfieldsn[] = "Bandwidthtype";
1548

    
1549
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1550
		
1551
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1552
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1553
                        	$input_errors[] = "Bandwidth must be an integer.";
1554

    
1555
                	if ($data['bandwidth'] < 0)
1556
                        	$input_errors[] = "Bandwidth cannot be negative.";
1557

    
1558
			if ($data['bandwidthtype'] == "%") {
1559
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1560
					$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1561
			}
1562
		/*
1563
			$parent =& $this->GetParent();
1564
			switch ($data['bandwidthtype']) {
1565
			case "%":
1566
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1567
			default:
1568
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1569
				break;
1570
			}
1571
			if ($parent->GetAvailableBandwidth() < $myBw)
1572
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1573
		*/
1574
		}
1575

    
1576
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1577
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1578
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1579
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1580
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1581
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1582
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1583
			$input_errors[] = ("upperlimit d value needs to be numeric");
1584
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1585
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1586

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

    
1594
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1595
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1596
		}
1597
		*/
1598
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1599
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1600
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1601
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1602
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1603
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1604
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1605
			$input_errors[] = ("linkshare d value needs to be numeric");
1606
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1607
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1608
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1609
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1610
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1611
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1612

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

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

    
1625
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1626
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1627
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1628
			$input_errors[] = ("realtime d value needs to be numeric");
1629
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1630
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1631

    
1632
		/*
1633
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1634
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1635
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1636
                	if (floatval($bw_1) < floatval($bw_2))
1637
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1638

    
1639
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1640
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1641
		}
1642
		*/
1643
	}
1644

    
1645
	function ReadConfig(&$cflink) {
1646
		if (!empty($cflink['linkshare'])) {
1647
			if (!empty($cflink['linkshare1'])) {
1648
				$this->SetL_m1($cflink['linkshare1']);
1649
                                $this->SetL_d($cflink['linkshare2']);
1650
				$this->SetLinkshare();
1651
			} else {
1652
				$this->SetL_m1("");
1653
                                $this->SetL_d("");
1654
				$this->DisableLinkshare();
1655
			}
1656
			if (!empty($cflink['linkshare3'])) {
1657
                                $this->SetL_m2($cflink['linkshare3']);
1658
				$this->SetLinkshare();
1659
			}
1660
		} else
1661
			$this->DisableLinkshare();
1662
		if (!empty($cflink['realtime'])) {
1663
                        if (!empty($cflink['realtime1'])) {
1664
                                $this->SetR_m1($cflink['realtime1']);
1665
                                $this->SetR_d($cflink['realtime2']);
1666
				$this->SetRealtime();
1667
			} else {
1668
                                $this->SetR_m1("");
1669
                                $this->SetR_d("");
1670
				$this->DisableRealtime();
1671
			}
1672
                        if (!empty($cflink['realtime3'])) {
1673
                                $this->SetR_m2($cflink['realtime3']);
1674
				$this->SetRealtime();
1675
			}
1676
		} else
1677
			$this->DisableRealtime(); 
1678
		if (!empty($cflink['upperlimit'])) {
1679
                        if (!empty($cflink['upperlimit1'])) {
1680
                                $this->SetU_m1($cflink['upperlimit1']);
1681
                                $this->SetU_d($cflink['upperlimit2']);
1682
				$this->SetUpperlimit();
1683
			} else {
1684
                                $this->SetU_m1("");
1685
                                $this->SetU_d("");
1686
				$this->DisableUpperlimit();
1687
			}
1688
                        if (!empty($cflink['upperlimit3'])) {
1689
                                $this->SetU_m2($cflink['upperlimit3']);
1690
				$this->SetUpperlimit();
1691
			}
1692
		} else
1693
			$this->DisableUpperlimit();
1694
		parent::ReadConfig($cflink);
1695
	}
1696

    
1697
	function build_tree() {
1698
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1699
		$tree .= "\" ";
1700
		$tmpvalue = $this->GetDefault();
1701
		if (!empty($tmpvalue))
1702
			$tree .= " class=\"navlnk\"";
1703
		$tree .= " >" . $this->GetQname() . "</a>";
1704
		if (is_array($this->subqueues)) {
1705
			$tree .= "<ul>";
1706
			foreach ($this->subqueues as $q)  {
1707
				$tree .= $q->build_tree();
1708
			}	
1709
			$tree .= "</ul>";
1710
		}
1711
		$tree .= "</li>";
1712
		return $tree;
1713
	}
1714

    
1715
	/* Even this should take children into consideration */
1716
	function build_rules(&$default = false) {
1717

    
1718
		$pfq_rule = " queue ". $this->qname;
1719
		if ($this->GetInterface())
1720
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1721
		if ($this->GetBandwidth() && $this->GetBwscale())
1722
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1723
				
1724
		$tmpvalue = $this->GetQlimit();
1725
		if (!empty($tmpvalue))
1726
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1727
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1728
			$pfq_rule .= " hfsc ( ";
1729
			$tmpvalue = $this->GetRed();
1730
			if (!empty($tmpvalue)) {
1731
				$comma = 1;
1732
				$pfq_rule .= " red ";
1733
			}
1734
			
1735
			$tmpvalue = $this->GetRio();
1736
			if (!empty($tmpvalue)) {
1737
				if ($comma) 
1738
					$pfq_rule .= " ,";
1739
				$comma = 1;
1740
				$pfq_rule .= " rio ";
1741
			}
1742
			$tmpvalue = $this->GetEcn();
1743
			if (!empty($tmpvalue)) {
1744
				if ($comma) 
1745
					$pfq_rule .= " ,";
1746
				$comma = 1;
1747
				$pfq_rule .= " ecn ";
1748
			}
1749
			$tmpvalue = $this->GetDefault();
1750
			if (!empty($tmpvalue)) {
1751
				if ($comma)
1752
					$pfq_rule .= " ,";
1753
				$comma = 1;
1754
				$pfq_rule .= " default ";
1755
				$default = true;
1756
			}
1757

    
1758
			if ($this->GetRealtime() <> "")  {
1759
				if ($comma) 
1760
					$pfq_rule .= " , ";
1761
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1762
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1763
				else  if ($this->GetR_m2() <> "")
1764
					$pfq_rule .= " realtime " . $this->GetR_m2();
1765
				$comma = 1;
1766
			}
1767
			if ($this->GetLinkshare() <> "") {
1768
				if ($comma)
1769
					$pfq_rule .= " ,";
1770
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1771
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1772
				else if ($this->GetL_m2() <> "")
1773
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1774
				$comma = 1;
1775
			}
1776
			if ($this->GetUpperlimit() <> "") {
1777
				if ($comma)
1778
					$pfq_rule .= " ,";
1779
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1780
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1781
				else if ($this->GetU_m2() <> "")
1782
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1783
			}
1784
			$pfq_rule .= " ) ";
1785
		}
1786
		if (count($this->subqueues)) {
1787
			$i = count($this->subqueues);
1788
			$pfq_rule .= " { ";
1789
			foreach ($this->subqueues as $qkey => $qnone) {
1790
				if ($i > 1) {
1791
					$i--;
1792
					$pfq_rule .= " {$qkey}, ";
1793
				} else
1794
					$pfq_rule .= " {$qkey} ";
1795
			}
1796
			$pfq_rule .= " } \n";
1797
			foreach ($this->subqueues as $q)
1798
				$pfq_rule .= $q->build_rules(&$default);
1799
		}
1800

    
1801
		 $pfq_rule .= " \n";
1802
			
1803
		return $pfq_rule;
1804
	}
1805

    
1806
	function build_javascript() {
1807
		$javascript = parent::build_javascript();
1808
		$javascript .= "<script type=\"text/javascript\">";
1809
		$javascript .= "function enable_realtime(enable_over) { \n";
1810
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1811
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1812
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1813
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1814
		$javascript .= " } else { \n";
1815
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1816
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1817
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1818
		$javascript .= " } \n";
1819
		$javascript .= " } \n";
1820
		$javascript .= "function enable_linkshare(enable_over) { \n";
1821
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1822
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1823
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1824
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1825
		$javascript .= " } else { \n";
1826
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1827
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1828
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1829
		$javascript .= " } \n";
1830
		$javascript .= " } \n";
1831
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1832
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1833
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1834
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1835
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1836
		$javascript .= " } else { \n";
1837
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1838
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1839
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1840
		$javascript .= " } \n";
1841
			
1842
		$javascript .= "} \n";
1843
		$javascript .= "</script>";
1844

    
1845
		return $javascript;
1846
	}
1847

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

    
1949
		return $form;
1950
	}
1951

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

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

    
2060
class cbq_queue extends priq_queue {
2061
	var $qborrow = "";
2062

    
2063
	function GetBorrow() {
2064
		return $this->qborrow;
2065
	}
2066
	function SetBorrow($borrow) {
2067
		$this->qborrow = $borrow;
2068
	}
2069
	function CanHaveChildren() {
2070
		return true;
2071
	}
2072

    
2073
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2074

    
2075
		if (!is_array($this->subqueues))
2076
			$this->subqueues = array();
2077
		$q =& new cbq_queue();
2078
		$q->SetInterface($this->GetInterface());
2079
		$q->SetParent(&$this);
2080
		$q->ReadConfig($qname);
2081
                $q->validate_input($qname, $input_errors);
2082
                if (count($input_errors)) {
2083
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2084
                        return $q;
2085
                }
2086
                switch ($q->GetBwscale()) {
2087
                case "%":
2088
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2089
                        break;
2090
                default:
2091
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2092
                        break;
2093
                }
2094
                $q->SetAvailableBandwidth($myBw);
2095
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2096

    
2097
		$q->SetEnabled("on");
2098
		$q->SetLink($path);
2099
		$this->subqueues[$q->GetQName()] = &$q;
2100
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2101
		if (is_array($qname['queue'])) {
2102
			foreach ($qname['queue'] as $key1 => $que) {
2103
				array_push($path, $key1);
2104
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2105
				array_pop($path);
2106
			}
2107
		}
2108

    
2109
		return $q;
2110
	}
2111

    
2112
	function copy_queue($interface, &$cflink) {
2113

    
2114
		$cflink['interface'] = $interface;
2115
		$cflink['qlimit'] = trim($this->GetQlimit());
2116
		if (empty($clink['qlimit']))
2117
			unset($cflink['qlimit']);
2118
		$cflink['priority'] = trim($this->GetQpriority());
2119
		if (empty($cflink['priority']))
2120
			unset($cflink['priority']);
2121
		$cflink['name'] = $this->GetQname();
2122
		$cflink['description'] = trim($this->GetDescription());
2123
		if (empty($cflink['description']))
2124
			unset($cflink['description']);
2125
		$cflink['bandwidth'] = $this->GetBandwidth();
2126
		$cflink['bandwidthtype'] = $this->GetBwscale();
2127
		$cflink['enabled'] = trim($this->GetEnabled());
2128
		if (empty($cflink['enabled']))
2129
			unset($cflink['enabled']);
2130
		$cflink['default'] = trim($this->GetDefault());
2131
		if (empty($cflink['default']))
2132
			unset($cflink['default']);
2133
		$cflink['red'] = trim($this->GetRed());
2134
		if (empty($cflink['red']))
2135
			unset($cflink['red']);
2136
		$cflink['rio'] = trim($this->GetRio());
2137
		if (empty($cflink['rio']))
2138
			unset($cflink['rio']);
2139
		$cflink['ecn'] = trim($this->GetEcn());
2140
		if (empty($cflink['ecn']))
2141
			unset($cflink['ecn']);
2142
		$cflink['borrow'] = trim($this->GetBorrow());
2143
		if (empty($cflink['borrow']))
2144
			unset($cflink['borrow']);
2145
		if (is_array($this->queues)) {
2146
			$cflinkp['queue'] = array();
2147
			foreach ($this->subqueues as $q) {
2148
				$cflink['queue'][$q->GetQname()] = array();
2149
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
2150
			}
2151
		}
2152
	}
2153
	
2154
	/*
2155
	 * Should search even its children
2156
	 */
2157
	function &find_queue($interface, $qname) {
2158
		if ($qname == $this->GetQname())
2159
			return $this;
2160
		foreach ($this->subqueues as $q) {
2161
			$result =& $q->find_queue("", $qname);
2162
			if ($result)
2163
				return $result;
2164
		}
2165
	}
2166

    
2167
	function &find_parentqueue($interface, $qname) {
2168
		if ($this->subqueues[$qname])
2169
			return $this;
2170
		foreach ($this->subqueues as $q) {
2171
			$result = $q->find_parentqueue("", $qname);
2172
			if ($result)
2173
				return $result;
2174
		}
2175
	}
2176

    
2177
	function delete_queue() {
2178
		unref_on_altq_queue_list($this->GetQname());
2179
		cleanup_queue_from_rules($this->GetQname());
2180
		foreach ($this->subqueues as $q) {
2181
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2182
			$q->delete_queue();
2183
		}
2184
		unset_object_by_reference($this->GetLink());
2185
	}
2186
	
2187
	function validate_input($data, &$input_errors) {
2188
		parent::validate_input($data, $input_errors);
2189
		
2190
		if ($data['priority'] > 7)
2191
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2192
		$reqdfields[] = "bandwidth";
2193
		$reqdfieldsn[] = "Bandwidth";
2194
		$reqdfields[] = "bandwidthtype";
2195
		$reqdfieldsn[] = "Bandwidthtype";
2196

    
2197
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2198
		
2199
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2200
			$input_errors[] = "Bandwidth must be an integer.";
2201

    
2202

    
2203
		if ($data['bandwidth'] < 0)
2204
                       $input_errors[] = "Bandwidth cannot be negative.";
2205

    
2206
		if ($data['bandwidthtype'] == "%") {
2207
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2208
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2209
		}
2210

    
2211
/*
2212
		$parent =& $this->GetParent();
2213
		switch ($data['bandwidthtype']) {
2214
		case "%":
2215
			$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2216
			break;
2217
		default:
2218
			$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2219
			break;
2220
		}
2221
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2222
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2223
*/
2224
	}
2225

    
2226
	function ReadConfig(&$q) {
2227
		parent::ReadConfig($q);
2228
		if (!empty($q['borrow']))
2229
			$this->SetBorrow("on");
2230
		else
2231
			$this->SetBorrow("");
2232
	}
2233
		
2234
	function build_javascript() {
2235
		return parent::build_javascript();
2236
	}
2237

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

    
2321
		$pfq_rule .= " \n";
2322
		return $pfq_rule;
2323
	}
2324

    
2325
	function build_form() {
2326
		$form = parent::build_form();
2327
		$form .= "<tr>";
2328
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2329
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2330
		if ($this->GetBandwidth() > 0)
2331
			$form .= htmlspecialchars($this->GetBandwidth());
2332
		$form .= "\">";
2333
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2334
		$form .= "<option value=\"Gb\"";
2335
		if ($this->GetBwscale() == "Gb")
2336
			$form .= " selected=\"yes\"";
2337
		$form .= ">Gbit/s</option>";
2338
		$form .= "<option value=\"Mb\"";
2339
		if ($this->GetBwscale() == "Mb")
2340
			$form .= " selected=\"yes\"";
2341
		$form .= ">Mbit/s</option>";
2342
		$form .= "<option value=\"Kb\"";
2343
		if ($this->GetBwscale() == "Kb")
2344
			$form .= " selected=\"yes\"";
2345
		$form .= ">Kbit/s</option>";
2346
		$form .= "<option value=\"\"";
2347
		if ($this->GetBwscale() == "b")
2348
			$form .= " selected=\"yes\"";
2349
		$form .= ">Bit/s</option>";
2350
		$form .= "<option value=\"%\"";
2351
		if ($this->GetBwscale() == "%")
2352
			$form .= " selected=\"yes\"";
2353
		$form .= ">%</option>";
2354
		$form .= "</select> <br>";
2355
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2356
		$form .= "</span></td></tr>";
2357
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2358
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2359
		if($this->GetBorrow() == "on") 
2360
			$form .=  " CHECKED ";
2361
		$form .= "> Borrow from other queues when available<br></td></tr>";
2362

    
2363
		return $form;
2364
	}
2365

    
2366
	function update_altq_queue_data(&$data) { 
2367
		$this->ReadConfig($data);
2368
	}
2369

    
2370
	function wconfig() {
2371
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2372
		if (!is_array($cflink))
2373
			$cflink = array();
2374
		$cflink['interface'] = $this->GetInterface();
2375
		$cflink['qlimit'] = trim($this->GetQlimit());
2376
		if (empty($cflink['qlimit']))
2377
			unset($cflink['qlimit']);
2378
		$cflink['priority'] = $this->GetQpriority();
2379
		if (empty($cflink['priority']))
2380
			unset($cflink['priority']);
2381
		$cflink['name'] = $this->GetQname();
2382
		$cflink['description'] = $this->GetDescription();
2383
		if (empty($cflink['description']))
2384
			unset($cflink['description']);
2385
		$cflink['bandwidth'] = $this->GetBandwidth();
2386
		$cflink['bandwidthtype'] = $this->GetBwscale();
2387
		$cflink['enabled'] = trim($this->GetEnabled());
2388
		if (empty($cflink['enabled']))
2389
			unset($cflink['enabled']);
2390
		$cflink['default'] = trim($this->GetDefault());
2391
		if (empty($cflink['default']))
2392
			unset($cflink['default']);
2393
		$cflink['red'] = trim($this->GetRed());
2394
		if (empty($cflink['red']))
2395
			unset($cflink['red']);
2396
		$cflink['rio'] = trim($this->GetRio());
2397
		if (empty($cflink['rio']))
2398
			unset($cflink['rio']);
2399
		$cflink['ecn'] = trim($this->GetEcn());
2400
		if (empty($cflink['ecn']))
2401
			unset($cflink['ecn']);
2402
		$cflink['borrow'] = trim($this->GetBorrow());
2403
		if (empty($cflink['borrow']))
2404
			unset($cflink['borrow']);
2405
	}
2406
}
2407

    
2408
class fairq_queue extends priq_queue {
2409
	var $hogs;
2410
	var $buckets;
2411

    
2412
	function GetBuckets() {
2413
		return $this->buckets;
2414
	}
2415
	function SetBuckets($buckets) {
2416
		$this->buckets = $buckets;
2417
	}
2418
	function GetHogs() {
2419
		return $this->hogs;
2420
	}
2421
	function SetHogs($hogs) {
2422
		$this->hogs = $hogs;
2423
	}
2424
	function CanHaveChildren() {
2425
		return false;
2426
	}
2427

    
2428

    
2429
	function copy_queue($interface, &$cflink) {
2430
                $cflink['interface'] = $interface;
2431
                $cflink['qlimit'] = $this->GetQlimit();
2432
                $cflink['priority'] = $this->GetQpriority();
2433
                $cflink['name'] = $this->GetQname();
2434
                $cflink['description'] = $this->GetDescription();
2435
                $cflink['bandwidth'] = $this->GetBandwidth();
2436
                $cflink['bandwidthtype'] = $this->GetBwscale();
2437
                $cflink['enabled'] = $this->GetEnabled();
2438
                $cflink['default'] = $this->GetDefault();
2439
                $cflink['red'] = $this->GetRed();
2440
                $cflink['rio'] = $this->GetRio();
2441
                $cflink['ecn'] = $this->GetEcn();
2442
                $cflink['buckets'] = $this->GetBuckets();
2443
		$cflink['hogs'] = $this->GetHogs();
2444
	}
2445
	
2446
	/*
2447
	 * Should search even its children
2448
	 */
2449
	function &find_queue($interface, $qname) {
2450
		if ($qname == $this->GetQname())
2451
			return $this;
2452
	}
2453

    
2454
	function find_parentqueue($interface, $qname) { return; }
2455

    
2456
	function delete_queue() {
2457
		unref_on_altq_queue_list($this->GetQname());
2458
		cleanup_queue_from_rules($this->GetQname());
2459
		unset_object_by_reference($this->GetLink());
2460
	}
2461
	
2462
	function validate_input($data, &$input_errors) {
2463
		parent::validate_input($data, $input_errors);
2464
		
2465
		if ($data['priority'] > 255)
2466
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2467
		$reqdfields[] = "bandwidth";
2468
		$reqdfieldsn[] = "Bandwidth";
2469
		$reqdfields[] = "bandwidthtype";
2470
		$reqdfieldsn[] = "Bandwidthtype";
2471

    
2472
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2473
		
2474
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2475
	                 $input_errors[] = "Bandwidth must be an integer.";
2476

    
2477

    
2478
	        if ($data['bandwidth'] < 0)
2479
                       $input_errors[] = "Bandwidth cannot be negative.";
2480

    
2481

    
2482
        	if ($data['bandwidthtype'] == "%") {
2483
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2484
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2485
           	}
2486

    
2487
/*
2488
           	$parent =& $this->GetParent();
2489
           	switch ($data['bandwidthtype']) {
2490
                       case "%":
2491
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2492
                       default:
2493
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2494
                             break;
2495
           	}
2496
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2497
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2498
*/
2499
	}
2500
	
2501
	function ReadConfig(&$q) {
2502
		parent::ReadConfig($q);
2503
		if (!empty($q['buckets']))
2504
			$this->SetBuckets($q['buckets']);
2505
		else
2506
			$this->SetBuckets("");
2507
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2508
			$this->SetHogs($q['hogs']);
2509
		else
2510
			$this->SetHogs("");
2511
	}
2512
		
2513
	function build_javascript() {
2514
		return parent::build_javascript();
2515
	}
2516

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

    
2587
		$pfq_rule .= " \n";
2588
		return $pfq_rule;
2589
	}
2590

    
2591
	function build_form() {
2592
		$form = parent::build_form();
2593
		$form .= "<tr>";
2594
		$form .= "<td valign=\"center\" class=\"vncellreq\">Bandwidth</td>";
2595
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2596
		if ($this->GetBandwidth() > 0)
2597
			$form .= htmlspecialchars($this->GetBandwidth());
2598
		$form .= "\">";
2599
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2600
		$form .= "<option value=\"Gb\"";
2601
		if ($this->GetBwscale() == "Gb")
2602
			$form .= " selected=\"yes\"";
2603
		$form .= ">Gbit/s</option>";
2604
		$form .= "<option value=\"Mb\"";
2605
		if ($this->GetBwscale() == "Mb")
2606
			$form .= " selected=\"yes\"";
2607
		$form .= ">Mbit/s</option>";
2608
		$form .= "<option value=\"Kb\"";
2609
		if ($this->GetBwscale() == "Kb")
2610
			$form .= " selected=\"yes\"";
2611
		$form .= ">Kbit/s</option>";
2612
		$form .= "<option value=\"\"";
2613
		if ($this->GetBwscale() == "b")
2614
			$form .= " selected=\"yes\"";
2615
		$form .= ">Bit/s</option>";
2616
		$form .= "<option value=\"%\"";
2617
		if ($this->GetBwscale() == "%")
2618
			$form .= " selected=\"yes\"";
2619
		$form .= ">%</option>";
2620
		$form .= "</select> <br>";
2621
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2622
		$form .= "</span></td></tr>";
2623
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2624
		$form .= "<td class=\"vtable\"><table><tr><td>";
2625
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2626
		$tmpvalue = trim($this->GetBuckets());
2627
		if(!empty($tmpvalue)) 
2628
			$form .=  $this->GetBuckets();
2629
		$form .= "\"> Number of buckets available.<br></td></tr>";
2630
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2631
		$tmpvalue = trim($this->GetHogs());
2632
		if(!empty($tmpvalue)) 
2633
			$form .=  $this->GetHogs();
2634
		$form .= "\"> Bandwidth limit for hosts to not saturate link.<br></td></tr>";
2635
		$form .= "</table></td></tr>";
2636
		return $form;
2637
	}
2638

    
2639
	function update_altq_queue_data(&$data) { 
2640
		$this->ReadConfig($data);
2641
	}
2642

    
2643
	function wconfig() {
2644
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2645
		if (!is_array($cflink))
2646
			$cflink = array();
2647
		$cflink['interface'] = $this->GetInterface();
2648
		$cflink['qlimit'] = trim($this->GetQlimit());
2649
		if (empty($cflink['qlimit']))
2650
			unset($cflink['qlimit']);
2651
		$cflink['priority'] = trim($this->GetQpriority());
2652
		if (empty($cflink['priority']))
2653
			unset($cflink['priority']);
2654
		$cflink['name'] = $this->GetQname();
2655
		$cflink['description'] = trim($this->GetDescription());
2656
		if (empty($cflink['description']))
2657
			unset($cflink['description']);
2658
		$cflink['bandwidth'] = $this->GetBandwidth();
2659
		$cflink['bandwidthtype'] = $this->GetBwscale();
2660
		$cflink['enabled'] = $this->GetEnabled();
2661
		if (empty($cflink['enabled']))
2662
			unset($cflink['enabled']);
2663
		$cflink['default'] = trim($this->GetDefault());
2664
		if (empty($cflink['default']))
2665
			unset($cflink['default']);
2666
		$cflink['red'] = trim($this->GetRed());
2667
		if (empty($cflink['red']))
2668
			unset($cflink['red']);
2669
		$cflink['rio'] = trim($this->GetRio());
2670
		if (empty($cflink['rio']))
2671
			unset($cflink['rio']);
2672
		$cflink['ecn'] = trim($this->GetEcn());
2673
		if (empty($cflink['ecn']))
2674
			unset($cflink['ecn']);
2675
		$cflink['buckets'] = trim($this->GetBuckets());
2676
		if (empty($cflink['buckets']))
2677
			unset($cflink['buckets']);
2678
		$cflink['hogs'] = trim($this->GetHogs());
2679
		if (empty($cflink['hogs']))
2680
			unset($cflink['hogs']);
2681
	}
2682
}
2683

    
2684

    
2685
/*
2686
 * dummynet(4) wrappers.
2687
 */
2688

    
2689

    
2690
/*
2691
 * List of respective objects!
2692
 */
2693
$dummynet_pipe_list = array();
2694

    
2695
class dummynet_class {
2696
        var $qname;
2697
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2698
        var $qlimit;
2699
        var $description;
2700
	var $qenabled;
2701
	var $link;
2702
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2703
        var $plr;
2704

    
2705
        var $buckets;
2706
        /* mask parameters */
2707
        var $mask;
2708
        var $noerror;
2709

    
2710
        /* Accessor functions */
2711
        function SetLink($link) {
2712
                $this->link = $link;
2713
        }
2714
        function GetLink() {
2715
                return $this->link;
2716
        }
2717
	function Getmask() {
2718
		return $this->mask;
2719
	}
2720
	function SetMask($mask) {
2721
		$this->mask = $mask;
2722
	}
2723
	function &GetParent() {
2724
		return $this->qparent;
2725
	}
2726
	function SetParent(&$parent) {
2727
		$this->qparent = &$parent;
2728
	}
2729
        function GetEnabled() {
2730
                return $this->qenabled;
2731
        }
2732
        function SetEnabled($value) {
2733
                $this->qenabled = $value;
2734
        }
2735
	function CanHaveChildren() {
2736
		return false;
2737
        }
2738
	function CanBeDeleted() {
2739
                return true;
2740
        }
2741
        function GetQname() {
2742
                return $this->qname;
2743
        }
2744
        function SetQname($name) {
2745
                $this->qname = trim($name);
2746
        }
2747
        function GetQlimit() {
2748
                return $this->qlimit;
2749
        }
2750
        function SetQlimit($limit) {
2751
               	$this->qlimit = $limit;
2752
        }
2753
        function GetDescription() {
2754
                return $this->description;
2755
        }
2756
        function SetDescription($str) {
2757
                $this->description = trim($str);
2758
        }
2759
        function GetFirstime() {
2760
                return $this->firsttime;
2761
        }
2762
        function SetFirsttime($number) {
2763
                $this->firsttime = $number;
2764
        }
2765
        function GetBuckets() {
2766
                return $this->buckets;
2767
        }
2768
        function SetBuckets($buckets) {
2769
                $this->buckets = $buckets;
2770
        }
2771
	function SetNumber($number) {
2772
		$this->qnumber = $number;
2773
	}
2774
	function GetNumber() {
2775
		return $this->qnumber;
2776
	}
2777
        function GetPlr() {
2778
                return $this->plr;
2779
        }
2780
        function SetPlr($plr) {
2781
                $this->plr = $plr;
2782
        }
2783

    
2784
	function build_javascript() { return; } /* Do not remove */
2785

    
2786
	function validate_input($data, &$input_errors) {
2787
		$reqdfields[] = "bandwidth";
2788
		$reqdfieldsn[] = "Bandwidth";
2789
		$reqdfields[] = "bandwidthtype";
2790
		$reqdfieldsn[] = "Bandwidthtype";
2791
		$reqdfields[] = "newname";
2792
		$reqdfieldsn[] = "Name";
2793
	
2794
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2795

    
2796
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2797
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2798
            		$input_errors[] = "Plr must be an integer between 1 and 100.";
2799
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2800
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2801
            		$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2802
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2803
            		$input_errors[] = "Queue limit must be an integer";
2804
        	if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]+$/", $data['newname']))
2805
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2806
        	if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2807
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2808
	}
2809
}
2810

    
2811
class dnpipe_class extends dummynet_class {
2812
        var $delay;
2813
	var $qbandwidth;
2814
	var $qbandwidthtype;
2815

    
2816
		/* This is here to help on form building and building rules/lists */
2817
        var $subqueues = array();
2818

    
2819
	function CanHaveChildren() {
2820
	        return true;
2821
        }
2822
	function SetDelay($delay) {
2823
		$this->delay = $delay;
2824
	}
2825
	function GetDelay() {
2826
		return $this->delay;
2827
	}
2828
	function GetBwscale() {
2829
                return $this->qbandwidthtype;
2830
        }
2831
        function SetBwscale($scale) {
2832
               	$this->qbandwidthtype = $scale;
2833
        }		
2834
	function delete_queue() {
2835
		cleanup_dnqueue_from_rules($this->GetQname());
2836
		foreach ($this->subqueues as $q)
2837
			$q->delete_queue();
2838
		unset_dn_object_by_reference($this->GetLink());
2839
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2840
        }
2841
        function GetBandwidth() {
2842
                return $this->qbandwidth;
2843
        }
2844
        function SetBandwidth($bandwidth) {
2845
                $this->qbandwidth = $bandwidth;
2846
        }
2847

    
2848
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2849

    
2850
		if (!is_array($this->subqueues))
2851
			$this->subqueues = array();
2852
			
2853
		$q =& new dnqueue_class();
2854
		$q->SetLink($path);
2855
		$q->SetEnabled("on");
2856
		$q->SetPipe($this->GetQname());
2857
		$q->SetParent(&$this);
2858
		$q->ReadConfig($queue);
2859
		$q->validate_input($queue, $input_errors);
2860
		if (count($input_errors)) {
2861
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2862
			return $q;
2863
		}
2864
		$this->subqueues[$q->GetQname()] = &$q;
2865
            
2866
		return $q;
2867
	}
2868

    
2869
	function &get_queue_list($q = null) {
2870
		$qlist = array();
2871

    
2872
		$qlist[$this->GetQname()] = $this->GetNumber();
2873
		if (is_array($this->subqueues)) {
2874
			foreach ($this->subqueues as $queue)
2875
				$queue->get_queue_list(&$qlist);
2876
		}
2877
		return $qlist;
2878
	}
2879
		
2880
        /*
2881
         * Should search even its children
2882
         */
2883
        function &find_queue($pipe, $qname) {
2884
                if ($qname == $this->GetQname()) 
2885
                        return $this;
2886
               	foreach ($this->subqueues as $q) {
2887
                       	$result =& $q->find_queue("", $qname);
2888
						if ($result)
2889
                       	        return $result;
2890
               	}
2891
        }
2892

    
2893
	function &find_parentqueue($pipe, $qname) {
2894
		return NULL;
2895
       	}
2896

    
2897
	function validate_input($data, &$input_errors) {
2898
		parent::validate_input($data, $input_errors);
2899

    
2900
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2901
       		     	$input_errors[] = "Bandwidth must be an integer.";
2902
		if ($data['delay'] && (!is_numeric($data['delay'])))
2903
            		$input_errors[] = "Delay must be an integer.";
2904
		}
2905

    
2906
	function ReadConfig(&$q) {
2907
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
2908
			$this->SetQname($q['newname']);
2909
		} else if (!empty($q['newname'])) {
2910
			$this->SetQname($q['newname']);
2911
		} else {
2912
			$this->SetQname($q['name']);
2913
		}
2914
		$this->SetNumber($q['number']);
2915
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2916
			$this->SetBandwidth($q['bandwidth']);
2917
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2918
				$this->SetBwscale($q['bandwidthtype']);
2919
		}
2920
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2921
              		$this->SetQlimit($q['qlimit']);
2922
		else
2923
              		$this->SetQlimit("");
2924
		if (isset($q['mask']) && $q['mask'] <> "")
2925
              		$this->SetMask($q['mask']);
2926
		else
2927
              		$this->SetMask("");
2928
		if (isset($q['buckets']) && $q['buckets'] <> "")
2929
              		$this->SetBuckets($q['buckets']);
2930
		else
2931
              		$this->SetBuckets("");
2932
            	if (isset($q['plr']) && $q['plr'] <> "")
2933
            		$this->SetPlr($q['plr']);
2934
		else
2935
            		$this->SetPlr("");
2936
		if (isset($q['delay']) && $q['delay'] <> "")
2937
            		$this->SetDelay($q['delay']);
2938
		else
2939
			$this->SetDelay(0);
2940
            	if (isset($q['description']) && $q['description'] <> "")
2941
			$this->SetDescription($q['description']);
2942
		else
2943
			$this->SetDescription("");
2944
		$this->SetEnabled($q['enabled']);
2945

    
2946
        }
2947

    
2948
	function build_tree() {
2949
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2950
		$tree .= $this->GetQname() . "</a>";
2951
		if (is_array($this->subqueues)) {
2952
			$tree .= "<ul>";
2953
			foreach ($this->subqueues as $q)  {
2954
				$tree .= $q->build_tree();
2955
			}	
2956
			$tree .= "</ul>";
2957
		}
2958
		$tree .= "</li>";
2959
		
2960
		return $tree;
2961
	}
2962

    
2963
        function build_rules() {
2964
		if ($this->GetEnabled() == "")
2965
			return;
2966

    
2967
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2968
		if ($this->GetBandwidth() && $this->GetBwscale())
2969
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2970
		if ($this->GetQlimit())
2971
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2972
		if ($this->GetPlr())
2973
			$pfq_rule .= " plr " . $this->GetPlr();
2974
		if ($this->GetBuckets())
2975
			$pfq_rule .= " buckets " . $this->GetBuckets();
2976
		if ($this->GetDelay())
2977
			$pfq_rule .= " delay " . $this->GetDelay();
2978

    
2979
		$mask = $this->GetMask();
2980
		if (!empty($mask)) {
2981
			/* XXX TODO extend this to support more complicated masks */
2982
			switch ($mask) {
2983
			case 'srcaddress':
2984
				$pfq_rule .= " mask src-ip 0xffffffff ";
2985
				break;
2986
			case 'dstaddress':
2987
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2988
				break;
2989
			default:
2990
				break;
2991
			}
2992
			$pfq_rule .= "\n";
2993

    
2994
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2995
       			        foreach ($this->subqueues as $q)
2996
				$pfq_rule .= $q->build_rules();
2997
               		}
2998
    		}            
2999
		$pfq_rule .= " \n";
3000

    
3001
		return $pfq_rule;
3002
        }
3003

    
3004
	function update_dn_data(&$data) { 
3005
		$this->ReadConfig($data);
3006
	}
3007

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

    
3087
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3088
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3089
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3090
		$form .= $this->GetDelay() . "\">";
3091
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3092
		$form .= "should specify 0 here (or leave the field empty)</span>";
3093
		$form .= "</td></tr><br/>";
3094
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3095
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3096
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3097
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3098
		$form .= $this->GetPlr() . "\">";
3099
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3100
        	$form .= "should specify 0 here (or leave the field empty).";
3101
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3102
		$form .= "</td></tr>";
3103
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3104
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3105
		$form .= "<td class=\"vncellreq\">";
3106
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3107
		$form .= $this->GetQlimit() . "\">";
3108
		$form .= "&nbsp;slots<br>";
3109
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3110
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
3111
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
3112
		$form .= "are delivered to their destination.</span>";
3113
		$form .= "</td></tr>";
3114
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3115
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3116
                $form .= "<td class=\"vncellreq\">";
3117
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3118
                $form .= $this->GetBuckets() . "\">";
3119
                $form .= "&nbsp;slots<br>";
3120
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3121
                $form .= "should leave the field empty. It increases the hash size set.";
3122
                $form .= "</td></tr>";
3123

    
3124
		return $form;
3125
			
3126
		}
3127

    
3128
	function wconfig() {
3129
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3130
            	if (!is_array($cflink))
3131
            		$cflink = array();
3132
		$cflink['name'] = $this->GetQname();
3133
		$cflink['number'] = $this->GetNumber();
3134
            	$cflink['qlimit'] = $this->GetQlimit();
3135
            	$cflink['plr'] = $this->GetPlr();
3136
            	$cflink['description'] = $this->GetDescription();
3137
		$cflink['bandwidth'] = $this->GetBandwidth();
3138
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3139
		$cflink['enabled'] = $this->GetEnabled();
3140
		$cflink['buckets'] = $this->GetBuckets();
3141
		$cflink['mask'] = $this->GetMask();
3142
		$cflink['delay'] = $this->GetDelay();
3143
	}
3144

    
3145
}
3146

    
3147
class dnqueue_class extends dummynet_class {
3148
        var $pipeparent;
3149
        var $weight;
3150

    
3151
        function GetWeight() {
3152
                return $this->weight;
3153
        }
3154
        function SetWeight($weight) {
3155
                $this->weight = $weight;
3156
        }
3157
	function GetPipe() {
3158
		return $this->pipeparent;
3159
	}
3160
	function SetPipe($pipe) {
3161
		$this->pipeparent = $pipe;
3162
	}
3163

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

    
3167
	function delete_queue() {
3168
		cleanup_dnqueue_from_rules($this->GetQname());
3169
		unset_dn_object_by_reference($this->GetLink());
3170
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3171
        }
3172

    
3173
	function validate_input($data, &$input_errors) {
3174
		parent::validate_input($data, $input_errors);
3175

    
3176
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3177
			($data['weight'] < 1 && $data['weight'] > 100))) 
3178
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3179
	}
3180

    
3181
        /*
3182
         * Should search even its children
3183
         */
3184
        function &find_queue($pipe, $qname) {
3185
                if ($qname == $this->GetQname()) 
3186
                	return $this;
3187
		else
3188
			return NULL;
3189
        }
3190

    
3191
	function &find_parentqueue($pipe, $qname) {
3192
		return $this->qparent;
3193
        }
3194

    
3195
        function &get_queue_list(&$qlist) {
3196
		if ($this->GetEnabled() == "")
3197
			return;
3198
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3199
        }		
3200

    
3201
	function ReadConfig(&$q) {
3202
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
3203
			$this->SetQname($q['newname']);
3204
		} else if (!empty($q['newname'])) {
3205
			$this->SetQname($q['newname']);
3206
		} else {
3207
			$this->SetQname($q['name']);
3208
		}
3209
		$this->SetNumber($q['number']);
3210
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3211
       		       	$this->SetQlimit($q['qlimit']);
3212
		else
3213
       		       	$this->SetQlimit("");
3214
		if (isset($q['mask']) && $q['mask'] <> "")
3215
              		$this->SetMask($q['mask']);
3216
		else
3217
              		$this->SetMask("");
3218
       		if (isset($q['weight']) && $q['weight'] <> "")
3219
            		$this->SetWeight($q['weight']);
3220
		else
3221
            		$this->SetWeight("");
3222
            	if (isset($q['description']) && $q['description'] <> "")
3223
			$this->SetDescription($q['description']);
3224
		else
3225
			$this->SetDescription("");
3226
		$this->SetEnabled($q['enabled']);
3227
        }
3228

    
3229
	function build_tree() {
3230
		$parent =& $this->GetParent();
3231
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3232
		$tree .= $this->GetQname() . "</a>";
3233
		$tree .= "</li>";
3234
		
3235
		return $tree;
3236
	}
3237

    
3238
        function build_rules() {
3239
		if ($this->GetEnabled() == "")
3240
			return; 
3241

    
3242
		$parent =& $this->GetParent();
3243
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3244
		if ($this->GetQlimit())
3245
                    	$pfq_rule .= " queue " . $this->GetQimit();
3246
		if ($this->GetWeight())
3247
			$pfq_rule .= " weight " . $this->GetWeight();
3248
		if ($this->GetBuckets())
3249
			$pfq_rule .= " buckets " . $this->GetBuckets();
3250
		$mask = $this->GetMask();
3251
		if (!empty($mask)) {
3252
			/* XXX TODO extend this to support more complicated masks */
3253
			switch ($mask) {
3254
			case 'srcaddress':
3255
				$pfq_rule .= " mask src-ip 0xffffffff ";
3256
				break;
3257
			case 'dstaddress':
3258
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3259
				break;
3260
			default:
3261
				break;
3262
			}
3263
			$pfq_rule .= "\n";
3264
		}
3265

    
3266
		return $pfq_rule;
3267
	}
3268

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

    
3361
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3362
		$form .= " value=\"" . $this->GetPipe() . "\">";
3363

    
3364
		return $form;
3365
			
3366
	}
3367

    
3368
        function update_dn_data(&$data) { 
3369
		$this->ReadConfig($data);
3370
	}
3371

    
3372
	function wconfig() {
3373
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3374
            	if (!is_array($cflink))
3375
            		$cflink = array();
3376
		$cflink['name'] = $this->GetQname();
3377
		$cflink['number'] = $this->GetNumber();
3378
            	$cflink['qlimit'] = $this->GetQlimit();
3379
            	$cflink['description'] = $this->GetDescription();
3380
		$cflink['weight'] = $this->GetWeight();
3381
		$cflink['enabled'] = $this->GetEnabled();
3382
		$cflink['buckets'] = $this->GetBuckets();
3383
		$cflink['mask'] = $this->GetMask();
3384
	}
3385
}
3386

    
3387
// List of layer7 objects
3388
$layer7_rules_list = array();
3389

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

    
3587
class l7rule {
3588
    
3589
    var $rprotocol; //protocol
3590
    var $rstructure; //action, limiter, queue
3591
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3592
    
3593
    //Auxiliary Functions
3594
    
3595
    function GetRProtocol() {
3596
        return $this->rprotocol;
3597
    }
3598
    function SetRProtocol($rprotocol) {
3599
        $this->rprotocol = $rprotocol;
3600
    }
3601
    function GetRStructure() {
3602
        return $this->rstructure;
3603
    }
3604
    function SetRStructure($rstructure) {
3605
        $this->rstructure = $rstructure;
3606
    }
3607
    function GetRBehaviour() {
3608
        return $this->rbehaviour;
3609
    }
3610
    function SetRBehaviour($rbehaviour) {
3611
        $this->rbehaviour = $rbehaviour;
3612
    }
3613
    
3614
    //XXX Do we need to test any particularity for AltQ queues?
3615
    function build_rules() {
3616
	global $dummynet_pipe_list;
3617
	switch ($this->GetRStructure()) {
3618
		case "limiter":
3619
			read_dummynet_config();
3620
			$dn_list =& get_unique_dnqueue_list();
3621
			$found = false;
3622
			if(is_array($dn_list)) {
3623
				foreach($dn_list as $key => $value) {
3624
					if($key == $this->GetRBehaviour()) {
3625
						if($value[0] == "?")
3626
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3627
						else
3628
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3629
						$found = true;
3630
					}
3631
					if($found)
3632
						break;
3633
				}
3634
			}
3635
			break;
3636
		default: //This is for action and for altq
3637
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3638
			break;
3639
	}
3640
        return $l7rule;
3641
    }
3642
}
3643

    
3644
/*
3645
 * This function allows to return an array with all the used divert socket ports
3646
 */
3647
function get_divert_ports() {
3648
    global $layer7_rules_list;
3649
    $dports = array();
3650
    
3651
    foreach($layer7_rules_list as $l7r)
3652
        $dports[] = $l7r->GetRPort();
3653
    
3654
    return $dports;
3655
}
3656

    
3657
function &get_l7c_reference_to_me_in_config(&$name) {
3658
	global $config;
3659
	
3660
	$ptr = NULL;
3661
	
3662
	if(is_array($config['l7shaper']['container'])) {
3663
		foreach($config['l7shaper']['container'] as $key => $value) {
3664
			if($value['name'] == $name)
3665
				$ptr =& $config['l7shaper']['container'][$key];
3666
		}
3667
	}	
3668
	return $ptr;
3669
// $ptr can be null. has to be checked later
3670
}
3671

    
3672
function unset_l7_object_by_reference(&$name) {
3673
	global $config;
3674
        
3675
	if(is_array($config['l7shaper']['container'])) {
3676
		foreach($config['l7shaper']['container'] as $key => $value) {
3677
			if($value['name'] == $name) {
3678
				unset($config['l7shaper']['container'][$key]['l7rules']);
3679
				unset($config['l7shaper']['container'][$key]);
3680
				break;
3681
			}
3682
		}
3683
	}
3684
}
3685

    
3686
function read_layer7_config() {
3687
    global $layer7_rules_list, $config;
3688
    
3689
    $l7cs = &$config['l7shaper']['container'];
3690
    
3691
    $layer7_rules_list = array();
3692
    
3693
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3694
	return;
3695
    
3696
    foreach ($l7cs as $conf) {
3697
	if (empty($conf['name']))
3698
		continue; /* XXX: grrrrrr at php */ 
3699
        $root =& new layer7();
3700
        $root->ReadConfig($conf['name'],$conf);
3701
        $layer7_rules_list[$root->GetRName()] = &$root;
3702
    }
3703
}
3704

    
3705
function generate_layer7_files() {
3706
    global $layer7_rules_list, $g;
3707
    
3708
    read_layer7_config();
3709
    
3710
    if (!empty($layer7_rules_list)) {
3711
	if (!is_module_loaded("ipdivert.ko"))
3712
		mwexec("/sbin/kldload ipdivert.ko");
3713

    
3714
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3715
    }
3716
    
3717
    foreach($layer7_rules_list as $l7rules) {
3718
        if($l7rules->GetREnabled()) {
3719
            $filename = $l7rules->GetRName() . ".l7";
3720
            $path = "{$g['tmp_path']}/" . $filename;
3721
        
3722
            $rules = $l7rules->build_l7_rules();
3723
        
3724
            $fp = fopen($path,'w');
3725
            fwrite($fp,$rules);
3726
            fclose($fp);
3727
        }
3728
    }
3729
}
3730

    
3731
function layer7_start_l7daemon() {
3732
    global $layer7_rules_list, $g;
3733

    
3734
    /*
3735
     * XXX: ermal - Needed ?!
3736
     * read_layer7_config();
3737
     */
3738

    
3739
    foreach($layer7_rules_list as $l7rules) {
3740
        if($l7rules->GetREnabled()) {
3741
            $filename = $l7rules->GetRName() . ".l7";
3742
            $path = "{$g['tmp_path']}/" . $filename;
3743

    
3744
	    unset($l7pid);
3745
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3746
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3747
	    if (count($l7pid) > 0) {
3748
		log_error("Sending HUP signal to {$l7pid[0]}");
3749
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3750
	    } else {
3751
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3752
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 8 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3753
		mwexec_bg($ipfw_classifyd_init);
3754
	    }
3755
        }
3756
    }
3757
}
3758

    
3759
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3760
function generate_protocols_array() {
3761
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3762
	$protocols_new = array();
3763
	if(is_array($protocols)) {
3764
		foreach($protocols as $key => $proto) {
3765
			if (strstr($proto, ".pat"))
3766
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3767
		}
3768
		sort($protocols_new);
3769
	}		
3770
	return $protocols_new;
3771
}
3772

    
3773
function get_l7_unique_list() {
3774
	global $layer7_rules_list;
3775
	
3776
	$l7list = array();
3777
	if(is_array($layer7_rules_list)) 
3778
		foreach($layer7_rules_list as $l7c)
3779
			if($l7c->GetREnabled())
3780
				$l7list[] = $l7c->GetRName();
3781
	
3782
	return $l7list;
3783
}
3784

    
3785
// Disable a removed l7 container from the filter
3786
function cleanup_l7_from_rules(&$name) {
3787
	global $config;
3788

    
3789
	if(is_array($config['filter']['rule']))
3790
		foreach ($config['filter']['rule'] as $key => $rule) {
3791
			if ($rule['l7container'] == $name)
3792
				unset($config['filter']['rule'][$key]['l7container']);
3793
		}
3794
}
3795

    
3796
function get_dummynet_name_list() {
3797
	
3798
	$dn_name_list =& get_unique_dnqueue_list();
3799
	$dn_name = array();
3800
	if(is_array($dn_name_list))
3801
		foreach($dn_name_list as $key => $value)
3802
			$dn_name[] = $key;
3803
	
3804
	return $dn_name;
3805
	
3806
}
3807

    
3808
function get_altq_name_list() {
3809
	$altq_name_list =& get_unique_queue_list();
3810
	$altq_name = array();
3811
	if(is_array($altq_name_list))
3812
		foreach($altq_name_list as $key => $aqobj)
3813
			$altq_name[] = $key;
3814
		
3815
	return $altq_name;
3816
}
3817

    
3818
/*
3819
 * XXX: TODO Make a class shaper to hide all these function
3820
 * from the global namespace.
3821
 */
3822

    
3823
/* 
3824
 * This is a layer violation but for now there is no way 
3825
 * i can find to properly do this with PHP.
3826
 */
3827
function altq_get_default_queue($interface) {
3828
	global $altq_list_queues;
3829

    
3830
	$altq_tmp = $altq_list_queues[$interface];
3831
	if ($altq_tmp)
3832
		return $altq_tmp->GetDefaultQueuePresent(); 
3833
	else
3834
		return false;
3835
}
3836

    
3837
function altq_check_default_queues() {
3838
	global $altq_list_queues;
3839

    
3840
	$count = 0;
3841
	if (is_array($altq_list_queues)) {
3842
		foreach($altq_list_queues as $altq) {
3843
			if ($altq->GetDefaultQueuePresent())
3844
				$count++;
3845
		}
3846
	}
3847
	else  $count++;;
3848
	
3849
	return 0;
3850
}
3851

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

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

    
3887
function ref_on_altq_queue_list($parent, $qname) {
3888
	if (isset($GLOBALS['queue_list'][$qname]))
3889
		$GLOBALS['queue_list'][$qname]++;
3890
	else
3891
		$GLOBALS['queue_list'][$qname] = 1;
3892

    
3893
	unref_on_altq_queue_list($parent);
3894
}
3895

    
3896
function unref_on_altq_queue_list($qname) {
3897
	$GLOBALS['queue_list'][$qname]--;
3898
	if ($GLOBALS['queue_list'][$qname] <= 1)
3899
		unset($GLOBALS['queue_list'][$qname]);	
3900
}
3901

    
3902
function read_altq_config() {
3903
	global $altq_list_queues, $config;
3904
	$path = array();
3905
	
3906
	if (!is_array($config['shaper']))
3907
		$config['shaper'] = array();
3908
	if (!is_array($config['shaper']['queue']))
3909
		$config['shaper']['queue'] = array();
3910
	$a_int = &$config['shaper']['queue'];
3911

    
3912
	$altq_list_queues = array();
3913
	
3914
	if (!is_array($config['shaper']['queue']))
3915
		return;
3916

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

    
3940
function read_dummynet_config() {
3941
	global $dummynet_pipe_list, $config;
3942
	$path = array();
3943
	$dnqueuenumber = 1;
3944
	$dnpipenumber = 1;
3945

    
3946
	if (!is_array($config['dnshaper']))
3947
		$config['dnshaper'] = array();
3948
	if (!is_array($config['dnshaper']['queue']))
3949
		$config['dnshaper']['queue'] = array();
3950
	$a_int = &$config['dnshaper']['queue'];
3951

    
3952
	$dummynet_pipe_list = array();
3953
	
3954
	if (!is_array($config['dnshaper']['queue'])
3955
		|| !count($config['dnshaper']['queue']))
3956
		return;
3957

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

    
3979
				$dnqueuenumber++;
3980
			} 	
3981
		}
3982
		array_pop($path);
3983
			
3984
		$dnpipenumber++;
3985
	}
3986
}
3987

    
3988
function get_interface_list_to_show() {
3989
	global $altq_list_queues, $config;
3990
	global $shaperIFlist;
3991

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

    
4006
function filter_generate_altq_queues() {
4007
	global $altq_list_queues;
4008
	
4009
	read_altq_config();
4010

    
4011
	$altq_rules = "";
4012
	foreach ($altq_list_queues as $altq) 
4013
		$altq_rules .= $altq->build_rules();
4014

    
4015
	return $altq_rules;
4016
}
4017

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

    
4030
	$dn_rules = "";
4031
	foreach ($dummynet_pipe_list as $dn) 
4032
		$dn_rules .= $dn->build_rules();
4033

    
4034
	if (!empty($dn_rules)) {
4035
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
4036
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
4037
	}
4038
	//return $dn_rules;
4039
}
4040

    
4041
function build_iface_without_this_queue($iface, $qname) {
4042
	global $g, $altq_list_queues;
4043
	global $shaperIFlist;
4044

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

    
4059
	return $form;
4060

    
4061
}
4062

    
4063

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

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

    
4078
?>
(46-46/62)