Project

General

Profile

Download (131 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[] = sprintf(gettext("The field '%s' contains invalid characters."), $pn);
190
                }
191
        }
192

    
193
        for ($i = 0; $i < count($reqdfields); $i++) {
194
                if ($postdata[$reqdfields[$i]] == "") {
195
                        $input_errors[] = sprintf(gettext("The field '%s' is required."), $reqdfieldsn[$i]);
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[] = gettext("Bandwidth");
318
		$reqdfields[] = "bandwidthtype";
319
		$reqdfieldsn[] = gettext("Bandwidthtype");
320
		
321
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
322
		
323
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
324
			$input_errors[] = gettext("Bandwidth must be an integer.");
325
                if ($data['bandwidth'] < 0)
326
			$input_errors[] = gettext("Bandwidth cannot be negative.");
327
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
328
			$input_errors[] = gettext("Qlimit must be an integer.");
329
	 	if ($data['qlimit'] < 0)
330
			$input_errors[] = gettext("Qlimit must be an positive.");
331
                if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig'])))
332
			$input_errors[] = gettext("Tbrsize must be an integer.");
333
                if ($data['tbrconfig'] < 0)
334
			$input_errors[] = gettext("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 .= gettext("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\"> " . gettext("Enable/disable discipline and its children") . "</span>";
620
		$form .= "</td></tr>";
621
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">" . gettext("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\">" . gettext("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 .= gettext("NOTE: Changing this changes all child queues!");
648
		$form .= gettext(" Beware you can lose information.");
649
		$form .= "</span>";
650
		$form .= "</td></tr>";
651
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("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 .= gettext("Adjusts the size, in bytes, of the token bucket regulator. "
687
		      .  "If not specified, heuristics based on the interface "
688
		      .  "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[] = gettext("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[] = gettext("The priority must be an integer between 1 and 15.");
979
		}
980
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
981
				$input_errors[] = gettext("Queue limit must be an integer");
982
		if ($data['qlimit'] < 0)
983
				$input_errors[] = gettext("Queue limit must be positive");
984
		if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['newname']))
985
			 $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
986
		if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
987
			 $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
988
		if (!empty($data['default']) && altq_get_default_queue($data['interface']))
989
			$input_errors[] = gettext("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 .= gettext("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\"> " . gettext("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 .= gettext("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\">" . gettext("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\">" . gettext("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\">" . gettext("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\">" . gettext("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\">" . gettext("Queue limit in packets per second."); 
1151
		$form .= "</span></td>";
1152
		$form .= "<tr>";
1153
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncell\">" . gettext("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\">" . gettext("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\">" . gettext("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\">" . gettext("Explicit Congestion Notification") . "</a><br>";
1179
		$form .= "<span class=\"vexpl\"><br>" . gettext("Select options for this queue");
1180
		$form .= "</tr><tr>";
1181
		$form .= "<td width=\"22%\" class=\"vncellreq\">" . gettext("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

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

    
1227
	}
1228

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1844
		return $javascript;
1845
	}
1846

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

    
1948
		return $form;
1949
	}
1950

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

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

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

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

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

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

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

    
2108
		return $q;
2109
	}
2110

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

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

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

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

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

    
2201

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

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

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

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

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

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

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

    
2362
		return $form;
2363
	}
2364

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

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

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

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

    
2427

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

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

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

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

    
2476

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

    
2480

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

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

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

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

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

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

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

    
2683

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

    
2688

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2945
        }
2946

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

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

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

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

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

    
3000
		return $pfq_rule;
3001
        }
3002

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

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

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

    
3122
		return $form;
3123
			
3124
		}
3125

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

    
3143
}
3144

    
3145
class dnqueue_class extends dummynet_class {
3146
        var $pipeparent;
3147
        var $weight;
3148

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

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

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

    
3171
	function validate_input($data, &$input_errors) {
3172
		parent::validate_input($data, $input_errors);
3173

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

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

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

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

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

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

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

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

    
3264
		return $pfq_rule;
3265
	}
3266

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

    
3358
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3359
		$form .= " value=\"" . $this->GetPipe() . "\">";
3360

    
3361
		return $form;
3362
			
3363
	}
3364

    
3365
        function update_dn_data(&$data) { 
3366
		$this->ReadConfig($data);
3367
	}
3368

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

    
3384
// List of layer7 objects
3385
$layer7_rules_list = array();
3386

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

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

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

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

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

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

    
3701
function generate_layer7_files() {
3702
    global $layer7_rules_list, $g;
3703
    
3704
    read_layer7_config();
3705
    
3706
    if (!empty($layer7_rules_list)) {
3707
	if (!is_module_loaded("ipdivert.ko"))
3708
		mwexec("/sbin/kldload ipdivert.ko");
3709

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

    
3727
function layer7_start_l7daemon() {
3728
    global $layer7_rules_list, $g;
3729

    
3730
    /*
3731
     * XXX: ermal - Needed ?!
3732
     * read_layer7_config();
3733
     */
3734

    
3735
    foreach($layer7_rules_list as $l7rules) {
3736
        if($l7rules->GetREnabled()) {
3737
            $filename = $l7rules->GetRName() . ".l7";
3738
            $path = "{$g['tmp_path']}/" . $filename;
3739

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

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

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

    
3781
// Disable a removed l7 container from the filter
3782
function cleanup_l7_from_rules(&$name) {
3783
	global $config;
3784

    
3785
	if(is_array($config['filter']['rule']))
3786
		foreach ($config['filter']['rule'] as $key => $rule) {
3787
			if ($rule['l7container'] == $name)
3788
				unset($config['filter']['rule'][$key]['l7container']);
3789
		}
3790
}
3791

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

    
3804
function get_altq_name_list() {
3805
	$altq_name_list =& get_unique_queue_list();
3806
	$altq_name = array();
3807
	if(is_array($altq_name_list))
3808
		foreach($altq_name_list as $key => $aqobj)
3809
			$altq_name[] = $key;
3810
		
3811
	return $altq_name;
3812
}
3813

    
3814
/*
3815
 * XXX: TODO Make a class shaper to hide all these function
3816
 * from the global namespace.
3817
 */
3818

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

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

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

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

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

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

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

    
3889
	unref_on_altq_queue_list($parent);
3890
}
3891

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

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

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

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

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

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

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

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

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

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

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

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

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

    
4011
	return $altq_rules;
4012
}
4013

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

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

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

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

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

    
4054
	return $form;
4055

    
4056
}
4057

    
4058

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

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

    
4073
?>
(45-45/62)