Project

General

Profile

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

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

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

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

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

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

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

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

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

    
49
	return $ptr;
50
}
51

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

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

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

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

    
72
	return $ptr;
73
}
74

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
449
		return $q;
450
	}
451

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

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

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

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

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

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

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

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

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

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

    
602
		return $form;
603

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

    
691

    
692
		return $form;
693
	}
694

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

    
723
}
724

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

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

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

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

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

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

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

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

    
905
	 }
906

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

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

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

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

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

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

    
1010
	}
1011

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

    
1030
		$tree .= "</li>"; 
1031

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

    
1079
		$pfq_rule .= " \n";
1080

    
1081
		return $pfq_rule;
1082
	}
1083

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

    
1157
		return $form;
1158
	}
1159

    
1160
	function build_shortform() {
1161
		/* XXX: Hacks in site. Mostly layer violations!  */
1162
		global $g, $altq_list_queues;
1163

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

    
1196
	}
1197

    
1198
		function update_altq_queue_data(&$q) { 
1199
		$this->ReadConfig($q);
1200
	}
1201

    
1202
	function wconfig() {
1203
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1204
		if (!is_array($cflink))
1205
			$cflink = array();
1206
		$cflink['name'] = $this->GetQname();
1207
		$cflink['interface'] = $this->GetInterface();
1208
		$cflink['qlimit'] = trim($this->GetQlimit());
1209
		if (empty($cflink['qlimit']))
1210
			unset($cflink['qlimit']);
1211
		$cflink['priority'] = trim($this->GetQpriority());
1212
		if (empty($cflink['priority']))
1213
			unset($cflink['priority']);
1214
		$cflink['description'] = trim($this->GetDescription());
1215
		if (empty($cflink['description']))
1216
			unset($cflink['description']);
1217
		$cflink['enabled'] = trim($this->GetEnabled());
1218
		if (empty($cflink['enabled']))
1219
			unset($cflink['enabled']);
1220
		$cflink['default'] = trim($this->GetDefault());
1221
		if (empty($cflink['default']))
1222
			unset($cflink['default']);
1223
		$cflink['red'] = trim($this->GetRed());
1224
		if (empty($cflink['red']))
1225
			unset($cflink['red']);
1226
		$cflink['rio'] = trim($this->GetRio());
1227
		if (empty($cflink['rio']))
1228
			unset($cflink['rio']);
1229
		$cflink['ecn'] = trim($this->GetEcn());
1230
		if (empty($cflink['ecn']))
1231
			unset($cflink['ecn']);
1232
	}
1233
}
1234

    
1235
class hfsc_queue extends priq_queue {
1236
	/* realtime */
1237
	var $realtime;
1238
	var $r_m1;
1239
	var $r_d;
1240
	var $r_m2;
1241
	/* linkshare */
1242
	var $linkshare;
1243
	var $l_m1;
1244
	var $l_d;
1245
	var $l_m2;
1246
	/* upperlimit */
1247
	var $upperlimit;
1248
	var $u_m1;
1249
	var $u_d;
1250
	var $u_m2;
1251

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

    
1340
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1341

    
1342
		if (!is_array($this->subqueues))
1343
			$this->subqueues = array();
1344
		$q =& new hfsc_queue();
1345
		$q->SetInterface($this->GetInterface());
1346
		$q->SetParent(&$this);
1347
		$q->ReadConfig($qname);
1348
		$q->validate_input($qname, $input_errors);
1349
		if (count($input_errors)) {
1350
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
1351
			return $q;
1352
		}
1353

    
1354
		$q->SetEnabled("on");
1355
		$q->SetLink($path);
1356
		switch ($q->GetBwscale()) {
1357
		case "%":
1358
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1359
			break;
1360
		default:
1361
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1362
			break;
1363
		}
1364
		$q->SetAvailableBandwidth($myBw);
1365
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1366

    
1367
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1368
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1369
		if (is_array($qname['queue'])) {
1370
			foreach ($qname['queue'] as $key1 => $que) {
1371
				array_push($path, $key1);
1372
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1373
				array_pop($path);
1374
			}
1375
		}
1376
	
1377
		return $q;
1378
	}
1379

    
1380
        function copy_queue($interface, &$cflink) {
1381

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

    
1465
		if (is_array($this->subqueues)) {
1466
			$cflinkp['queue'] = array();
1467
			foreach ($this->subqueues as $q) {
1468
				$cflink['queue'][$q->GetQname()] = array();
1469
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1470
			}
1471
		}
1472
	}
1473

    
1474
	function delete_queue() { 
1475
		unref_on_altq_queue_list($this->GetQname());
1476
		$tmpvalue = $this->GetDefault();
1477
		if (!empty($tmpvalue)) 
1478
			altq_set_default_queue($this->GetInterface(), "false");
1479
		cleanup_queue_from_rules($this->GetQname());
1480
		$parent =& $this->GetParent();
1481
		foreach ($this->subqueues as $q)  {
1482
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1483
			$q->delete_queue();
1484
		}
1485
		unset_object_by_reference($this->GetLink());
1486
	}
1487

    
1488
	/*
1489
	 * Should search even its children
1490
	 */
1491
	function &find_queue($interface, $qname) {
1492
		if ($qname == $this->GetQname()) 
1493
			return $this;
1494

    
1495
		foreach ($this->subqueues as $q) {
1496
			$result =& $q->find_queue("", $qname);
1497
			if ($result)
1498
				return $result;
1499
		}
1500
	}
1501

    
1502
	function &find_parentqueue($interface, $qname) {
1503
		if ($this->subqueues[$qname]) 
1504
			return $this;
1505
		foreach ($this->subqueues as $q) {
1506
			$result = $q->find_parentqueue("", $qname);
1507
			if ($result)
1508
				return $result;
1509
		}
1510
	}
1511
	
1512
	function validate_input($data, &$input_errors) {
1513
		parent::validate_input($data, $input_errors);
1514
		
1515
		$reqdfields[] = "bandwidth";
1516
		$reqdfieldsn[] = "Bandwidth";
1517
		$reqdfields[] = "bandwidthtype";
1518
		$reqdfieldsn[] = "Bandwidthtype";
1519

    
1520
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1521
		
1522
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1523
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1524
                        	$input_errors[] = "Bandwidth must be an integer.";
1525

    
1526
                	if ($data['bandwidth'] < 0)
1527
                        	$input_errors[] = "Bandwidth cannot be negative.";
1528

    
1529
			if ($data['bandwidthtype'] == "%") {
1530
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1531
					$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1532
			}
1533
		/*
1534
			$parent =& $this->GetParent();
1535
			switch ($data['bandwidthtype']) {
1536
			case "%":
1537
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1538
			default:
1539
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1540
				break;
1541
			}
1542
			if ($parent->GetAvailableBandwidth() < $myBw)
1543
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1544
		*/
1545
		}
1546

    
1547
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1548
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1549
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1550
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1551
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1552
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1553
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1554
			$input_errors[] = ("upperlimit d value needs to be numeric");
1555
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1556
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1557

    
1558
		/*
1559
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1560
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1561
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1562
			if (floatval($bw_1) < floatval($bw_2)) 
1563
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1564

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

    
1584
		/*
1585
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1586
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1587
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1588
                	if (floatval($bw_1) < floatval($bw_2))
1589
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1590

    
1591
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1592
                        	$input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1593
		}
1594
		*/
1595

    
1596
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1597
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1598
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1599
			$input_errors[] = ("realtime d value needs to be numeric");
1600
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1601
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1602

    
1603
		/*
1604
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1605
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1606
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1607
                	if (floatval($bw_1) < floatval($bw_2))
1608
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1609

    
1610
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1611
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1612
		}
1613
		*/
1614

    
1615
	}
1616

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

    
1669
	function build_tree() {
1670
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1671
		$tree .= "\" ";
1672
		$tmpvalue = $this->GetDefault();
1673
		if (!empty($tmpvalue))
1674
			$tree .= " class=\"navlnk\"";
1675
		$tree .= " >" . $this->GetQname() . "</a>";
1676
		if (is_array($this->subqueues)) {
1677
			$tree .= "<ul>";
1678
			foreach ($this->subqueues as $q)  {
1679
				$tree .= $q->build_tree();
1680
			}	
1681
			$tree .= "</ul>";
1682
		}
1683
		$tree .= "</li>";
1684
		return $tree;
1685
	}
1686

    
1687
	/* Even this should take children into consideration */
1688
	function build_rules($default = false) {
1689

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

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

    
1773
		 $pfq_rule .= " \n";
1774
			
1775
		return $pfq_rule;
1776
	}
1777

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

    
1817
		return $javascript;
1818
	}
1819

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

    
1921
		return $form;
1922
	}
1923

    
1924
	function update_altq_queue_data(&$data) { 
1925
		$this->ReadConfig($data);
1926
	}
1927

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

    
2032
class cbq_queue extends priq_queue {
2033
	var $qborrow = "";
2034

    
2035
	function GetBorrow() {
2036
		return $this->qborrow;
2037
	}
2038
	function SetBorrow($borrow) {
2039
		$this->qborrow = $borrow;
2040
	}
2041
	function CanHaveChildren() {
2042
		return true;
2043
	}
2044

    
2045
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2046

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

    
2069
		$q->SetEnabled("on");
2070
		$q->SetLink($path);
2071
		$this->subqueues[$q->GetQName()] = &$q;
2072
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2073
		if (is_array($qname['queue'])) {
2074
			foreach ($qname['queue'] as $key1 => $que) {
2075
				array_push($path, $key1);
2076
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2077
				array_pop($path);
2078
			}
2079
		}
2080

    
2081
		return $q;
2082
	}
2083

    
2084
	function copy_queue($interface, &$cflink) {
2085

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

    
2139
	function &find_parentqueue($interface, $qname) {
2140
		if ($this->subqueues[$qname])
2141
			return $this;
2142
		foreach ($this->subqueues as $q) {
2143
			$result = $q->find_parentqueue("", $qname);
2144
			if ($result)
2145
				return $result;
2146
		}
2147
	}
2148

    
2149
	function delete_queue() {
2150
		unref_on_altq_queue_list($this->GetQname());
2151
		if ($this->GetDefault())
2152
			altq_set_default_queue($this->GetInterface(), "false");
2153
		cleanup_queue_from_rules($this->GetQname());
2154
		foreach ($this->subqueues as $q) {
2155
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2156
			$q->delete_queue();
2157
		}
2158
		unset_object_by_reference($this->GetLink());
2159
	}
2160
	
2161
	function validate_input($data, &$input_errors) {
2162
		parent::validate_input($data, $input_errors);
2163
		
2164
		if ($data['priority'] > 7)
2165
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2166
		$reqdfields[] = "bandwidth";
2167
		$reqdfieldsn[] = "Bandwidth";
2168
		$reqdfields[] = "bandwidthtype";
2169
		$reqdfieldsn[] = "Bandwidthtype";
2170

    
2171
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2172
		
2173
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2174
			$input_errors[] = "Bandwidth must be an integer.";
2175

    
2176

    
2177
		if ($data['bandwidth'] < 0)
2178
                       $input_errors[] = "Bandwidth cannot be negative.";
2179

    
2180
		if ($data['bandwidthtype'] == "%") {
2181
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2182
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2183
		}
2184

    
2185
/*
2186
           $parent =& $this->GetParent();
2187
           switch ($data['bandwidthtype']) {
2188
                       case "%":
2189
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2190
                       default:
2191
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2192
                             break;
2193
           }
2194
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2195
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2196
*/
2197
	}
2198

    
2199
	function ReadConfig(&$q) {
2200
		parent::ReadConfig($q);
2201
		if (!empty($q['borrow']))
2202
			$this->SetBorrow("on");
2203
		else
2204
			$this->SetBorrow("");
2205
	}
2206
		
2207
	function build_javascript() {
2208
		return parent::build_javascript();
2209
	}
2210

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

    
2294
		$pfq_rule .= " \n";
2295
		return $pfq_rule;
2296
	}
2297

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

    
2336
		return $form;
2337
	}
2338

    
2339
	function update_altq_queue_data(&$data) { 
2340
		$this->ReadConfig($data);
2341
	}
2342

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

    
2381
class fairq_queue extends priq_queue {
2382
	var $hogs;
2383
	var $buckets;
2384

    
2385
	function GetBuckets() {
2386
		return $this->buckets;
2387
	}
2388
	function SetBuckets($buckets) {
2389
		$this->buckets = $buckets;
2390
	}
2391
	function GetHogs() {
2392
		return $this->hogs;
2393
	}
2394
	function SetHogs($hogs) {
2395
		$this->hogs = $hogs;
2396
	}
2397
	function CanHaveChildren() {
2398
		return false;
2399
	}
2400

    
2401

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

    
2427
	function find_parentqueue($interface, $qname) { return; }
2428

    
2429
	function delete_queue() {
2430
		unref_on_altq_queue_list($this->GetQname());
2431
		if ($this->GetDefault())
2432
			altq_set_default_queue($this->GetInterface(), "false");
2433
		cleanup_queue_from_rules($this->GetQname());
2434
		unset_object_by_reference($this->GetLink());
2435
	}
2436
	
2437
	function validate_input($data, &$input_errors) {
2438
		parent::validate_input($data, $input_errors);
2439
		
2440
		if ($data['priority'] > 255)
2441
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2442
		$reqdfields[] = "bandwidth";
2443
		$reqdfieldsn[] = "Bandwidth";
2444
		$reqdfields[] = "bandwidthtype";
2445
		$reqdfieldsn[] = "Bandwidthtype";
2446

    
2447
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2448
		
2449
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2450
	                 $input_errors[] = "Bandwidth must be an integer.";
2451

    
2452

    
2453
	        if ($data['bandwidth'] < 0)
2454
                       $input_errors[] = "Bandwidth cannot be negative.";
2455

    
2456

    
2457
        	if ($data['bandwidthtype'] == "%") {
2458
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2459
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2460
           	}
2461

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

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

    
2562
		$pfq_rule .= " \n";
2563
		return $pfq_rule;
2564
	}
2565

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

    
2614
	function update_altq_queue_data(&$data) { 
2615
		$this->ReadConfig($data);
2616
	}
2617

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

    
2659

    
2660
/*
2661
 * dummynet(4) wrappers.
2662
 */
2663

    
2664

    
2665
/*
2666
 * List of respective objects!
2667
 */
2668
$dummynet_pipe_list = array();
2669

    
2670
class dummynet_class {
2671
        var $qname;
2672
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2673
        var $qlimit;
2674
        var $description;
2675
	var $qenabled;
2676
	var $link;
2677
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2678
        var $plr;
2679

    
2680
        var $buckets;
2681
        /* mask parameters */
2682
        var $mask;
2683
        var $noerror;
2684

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

    
2759
	function build_javascript() { return; } /* Do not remove */
2760

    
2761
	function validate_input($data, &$input_errors) {
2762
		$reqdfields[] = "bandwidth";
2763
		$reqdfieldsn[] = "Bandwidth";
2764
		$reqdfields[] = "bandwidthtype";
2765
		$reqdfieldsn[] = "Bandwidthtype";
2766
		$reqdfields[] = "name";
2767
		$reqdfieldsn[] = "Name";
2768
	
2769
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2770

    
2771
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2772
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2773
            		$input_errors[] = "Plr must be an integer between 1 and 100.";
2774
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2775
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2776
            		$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2777
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2778
            		$input_errors[] = "Queue limit must be an integer";
2779
        	if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2780
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2781
	}
2782
}
2783

    
2784
class dnpipe_class extends dummynet_class {
2785
        var $delay;
2786
	var $qbandwidth;
2787
	var $qbandwidthtype;
2788

    
2789
		/* This is here to help on form building and building rules/lists */
2790
        var $subqueues = array();
2791

    
2792
	function CanHaveChildren() {
2793
	        return true;
2794
        }
2795
	function SetDelay($delay) {
2796
		$this->delay = $delay;
2797
	}
2798
	function GetDelay() {
2799
		return $this->delay;
2800
	}
2801
	function GetBwscale() {
2802
                return $this->qbandwidthtype;
2803
        }
2804
        function SetBwscale($scale) {
2805
               	$this->qbandwidthtype = $scale;
2806
        }		
2807
	function delete_queue() {
2808
		cleanup_dnqueue_from_rules($this->GetQname());
2809
		foreach ($this->subqueues as $q)
2810
			$q->delete_queue();
2811
		unset_dn_object_by_reference($this->GetLink());
2812
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2813
        }
2814
        function GetBandwidth() {
2815
                return $this->qbandwidth;
2816
        }
2817
        function SetBandwidth($bandwidth) {
2818
                $this->qbandwidth = $bandwidth;
2819
        }
2820

    
2821
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2822

    
2823
		if (!is_array($this->subqueues))
2824
			$this->subqueues = array();
2825
			
2826
		$q =& new dnqueue_class();
2827
		$q->SetLink($path);
2828
		$q->SetEnabled("on");
2829
		$q->SetPipe($this->GetQname());
2830
		$q->SetParent(&$this);
2831
		$q->ReadConfig($queue);
2832
		$q->validate_input($queue, $input_errors);
2833
		if (count($input_errors)) {
2834
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2835
			return $q;
2836
		}
2837
		$this->subqueues[$q->GetQname()] = &$q;
2838
            
2839
		return $q;
2840
	}
2841

    
2842
	function &get_queue_list($q = null) {
2843
		$qlist = array();
2844

    
2845
		$qlist[$this->GetQname()] = $this->GetNumber();
2846
		if (is_array($this->subqueues)) {
2847
			foreach ($this->subqueues as $queue)
2848
				$queue->get_queue_list(&$qlist);
2849
		}
2850
		return $qlist;
2851
	}
2852
		
2853
        /*
2854
         * Should search even its children
2855
         */
2856
        function &find_queue($pipe, $qname) {
2857
                if ($qname == $this->GetQname()) 
2858
                        return $this;
2859
               	foreach ($this->subqueues as $q) {
2860
                       	$result =& $q->find_queue("", $qname);
2861
						if ($result)
2862
                       	        return $result;
2863
               	}
2864
        }
2865

    
2866
	function &find_parentqueue($pipe, $qname) {
2867
		return NULL;
2868
       	}
2869

    
2870
	function validate_input($data, &$input_errors) {
2871
		parent::validate_input($data, $input_errors);
2872

    
2873
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2874
       		     	$input_errors[] = "Bandwidth must be an integer.";
2875
		if ($data['delay'] && (!is_numeric($data['delay'])))
2876
            		$input_errors[] = "Delay must be an integer.";
2877
		}
2878

    
2879
	function ReadConfig(&$q) {
2880
           	$this->SetQname($q['name']);
2881
		$this->SetNumber($q['number']);
2882
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2883
			$this->SetBandwidth($q['bandwidth']);
2884
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2885
				$this->SetBwscale($q['bandwidthtype']);
2886
		}
2887
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2888
              		$this->SetQlimit($q['qlimit']);
2889
		else
2890
              		$this->SetQlimit("");
2891
		if (isset($q['mask']) && $q['mask'] <> "")
2892
              		$this->SetMask($q['mask']);
2893
		else
2894
              		$this->SetMask("");
2895
		if (isset($q['buckets']) && $q['buckets'] <> "")
2896
              		$this->SetBuckets($q['buckets']);
2897
		else
2898
              		$this->SetBuckets("");
2899
            	if (isset($q['plr']) && $q['plr'] <> "")
2900
            		$this->SetPlr($q['plr']);
2901
		else
2902
            		$this->SetPlr("");
2903
		if (isset($q['delay']) && $q['delay'] <> "")
2904
            		$this->SetDelay($q['delay']);
2905
		else
2906
			$this->SetDelay(0);
2907
            	if (isset($q['description']) && $q['description'] <> "")
2908
			$this->SetDescription($q['description']);
2909
		else
2910
			$this->SetDescription("");
2911
		$this->SetEnabled($q['enabled']);
2912

    
2913
        }
2914

    
2915
	function build_tree() {
2916
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2917
		$tree .= $this->GetQname() . "</a>";
2918
		if (is_array($this->subqueues)) {
2919
			$tree .= "<ul>";
2920
			foreach ($this->subqueues as $q)  {
2921
				$tree .= $q->build_tree();
2922
			}	
2923
			$tree .= "</ul>";
2924
		}
2925
		$tree .= "</li>";
2926
		
2927
		return $tree;
2928
	}
2929

    
2930
        function build_rules() {
2931
		if ($this->GetEnabled() == "")
2932
			return;
2933

    
2934
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2935
		if ($this->GetBandwidth() && $this->GetBwscale())
2936
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2937
		if ($this->GetQlimit())
2938
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2939
		if ($this->GetPlr())
2940
			$pfq_rule .= " plr " . $this->GetPlr();
2941
		if ($this->GetBuckets())
2942
			$pfq_rule .= " buckets " . $this->GetBuckets();
2943
		if ($this->GetDelay())
2944
			$pfq_rule .= " delay " . $this->GetDelay();
2945

    
2946
		$mask = $this->GetMask();
2947
		if (!empty($mask)) {
2948
			/* XXX TODO extend this to support more complicated masks */
2949
			switch ($mask) {
2950
			case 'srcaddress':
2951
				$pfq_rule .= " mask src-ip 0xffffffff ";
2952
				break;
2953
			case 'dstaddress':
2954
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2955
				break;
2956
			default:
2957
				break;
2958
			}
2959
			$pfq_rule .= "\n";
2960

    
2961
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2962
       			        foreach ($this->subqueues as $q)
2963
				$pfq_rule .= $q->build_rules();
2964
               		}
2965
    		}            
2966
		$pfq_rule .= " \n";
2967

    
2968
		return $pfq_rule;
2969
        }
2970

    
2971
	function update_dn_data(&$data) { 
2972
		$this->ReadConfig($data);
2973
	}
2974

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

    
3052
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3053
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3054
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3055
		$form .= $this->GetDelay() . "\">";
3056
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3057
		$form .= "should specify 0 here (or leave the field empty)</span>";
3058
		$form .= "</td></tr><br/>";
3059
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3060
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3061
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3062
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3063
		$form .= $this->GetPlr() . "\">";
3064
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3065
        	$form .= "should specify 0 here (or leave the field empty).";
3066
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3067
		$form .= "</td></tr>";
3068
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3069
		$form .= "<td valign=\"center\" class=\"vncellreq\">Queue Size</td>";
3070
		$form .= "<td class=\"vncellreq\">";
3071
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3072
		$form .= $this->GetQlimit() . "\">";
3073
		$form .= "&nbsp;slots<br>";
3074
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3075
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
3076
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
3077
		$form .= "are delivered to their destination.</span>";
3078
		$form .= "</td></tr>";
3079
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3080
                $form .= "<td valign=\"center\" class=\"vncellreq\">Bucket Size</td>";
3081
                $form .= "<td class=\"vncellreq\">";
3082
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3083
                $form .= $this->GetBuckets() . "\">";
3084
                $form .= "&nbsp;slots<br>";
3085
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3086
                $form .= "should leave the field empty. It increases the hash size set.";
3087
                $form .= "</td></tr>";
3088

    
3089
		return $form;
3090
			
3091
		}
3092

    
3093
	function wconfig() {
3094
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3095
            	if (!is_array($cflink))
3096
            		$cflink = array();
3097
		$cflink['name'] = $this->GetQname();
3098
		$cflink['number'] = $this->GetNumber();
3099
            	$cflink['qlimit'] = $this->GetQlimit();
3100
            	$cflink['plr'] = $this->GetPlr();
3101
            	$cflink['description'] = $this->GetDescription();
3102
		$cflink['bandwidth'] = $this->GetBandwidth();
3103
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3104
		$cflink['enabled'] = $this->GetEnabled();
3105
		$cflink['buckets'] = $this->GetBuckets();
3106
		$cflink['mask'] = $this->GetMask();
3107
		$cflink['delay'] = $this->GetDelay();
3108
	}
3109

    
3110
}
3111

    
3112
class dnqueue_class extends dummynet_class {
3113
        var $pipeparent;
3114
        var $weight;
3115

    
3116
        function GetWeight() {
3117
                return $this->weight;
3118
        }
3119
        function SetWeight($weight) {
3120
                $this->weight = $weight;
3121
        }
3122
	function GetPipe() {
3123
		return $this->pipeparent;
3124
	}
3125
	function SetPipe($pipe) {
3126
		$this->pipeparent = $pipe;
3127
	}
3128

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

    
3132
	function delete_queue() {
3133
		cleanup_dnqueue_from_rules($this->GetQname());
3134
		unset_dn_object_by_reference($this->GetLink());
3135
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3136
        }
3137

    
3138
	function validate_input($data, &$input_errors) {
3139
		parent::validate_input($data, $input_errors);
3140

    
3141
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3142
			($data['weight'] < 1 && $data['weight'] > 100))) 
3143
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3144
	}
3145

    
3146
        /*
3147
         * Should search even its children
3148
         */
3149
        function &find_queue($pipe, $qname) {
3150
                if ($qname == $this->GetQname()) 
3151
                	return $this;
3152
		else
3153
			return NULL;
3154
        }
3155

    
3156
	function &find_parentqueue($pipe, $qname) {
3157
		return $this->qparent;
3158
        }
3159

    
3160
        function &get_queue_list(&$qlist) {
3161
		if ($this->GetEnabled() == "")
3162
			return;
3163
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3164
        }		
3165

    
3166
	function ReadConfig(&$q) {
3167
          	$this->SetQname($q['name']);
3168
		$this->SetNumber($q['number']);
3169
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3170
       		       	$this->SetQlimit($q['qlimit']);
3171
		else
3172
       		       	$this->SetQlimit("");
3173
		if (isset($q['mask']) && $q['mask'] <> "")
3174
              		$this->SetMask($q['mask']);
3175
		else
3176
              		$this->SetMask("");
3177
       		if (isset($q['weight']) && $q['weight'] <> "")
3178
            		$this->SetWeight($q['weight']);
3179
		else
3180
            		$this->SetWeight("");
3181
            	if (isset($q['description']) && $q['description'] <> "")
3182
			$this->SetDescription($q['description']);
3183
		else
3184
			$this->SetDescription("");
3185
		$this->SetEnabled($q['enabled']);
3186
        }
3187

    
3188
	function build_tree() {
3189
		$parent =& $this->GetParent();
3190
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3191
		$tree .= $this->GetQname() . "</a>";
3192
		$tree .= "</li>";
3193
		
3194
		return $tree;
3195
	}
3196

    
3197
        function build_rules() {
3198
		if ($this->GetEnabled() == "")
3199
			return; 
3200

    
3201
		$parent =& $this->GetParent();
3202
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3203
		if ($this->GetQlimit())
3204
                    	$pfq_rule .= " queue " . $this->GetQimit();
3205
		if ($this->GetWeight())
3206
			$pfq_rule .= " weight " . $this->GetWeight();
3207
		if ($this->GetBuckets())
3208
			$pfq_rule .= " buckets " . $this->GetBuckets();
3209
		$mask = $this->GetMask();
3210
		if (!empty($mask)) {
3211
			/* XXX TODO extend this to support more complicated masks */
3212
			switch ($mask) {
3213
			case 'srcaddress':
3214
				$pfq_rule .= " mask src-ip 0xffffffff ";
3215
				break;
3216
			case 'dstaddress':
3217
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3218
				break;
3219
			default:
3220
				break;
3221
			}
3222
			$pfq_rule .= "\n";
3223
		}
3224

    
3225
		return $pfq_rule;
3226
	}
3227

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

    
3318
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3319
		$form .= " value=\"" . $this->GetPipe() . "\">";
3320

    
3321
		return $form;
3322
			
3323
	}
3324

    
3325
        function update_dn_data(&$data) { 
3326
		$this->ReadConfig($data);
3327
	}
3328

    
3329
	function wconfig() {
3330
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3331
            	if (!is_array($cflink))
3332
            		$cflink = array();
3333
		$cflink['name'] = $this->GetQname();
3334
		$cflink['number'] = $this->GetNumber();
3335
            	$cflink['qlimit'] = $this->GetQlimit();
3336
            	$cflink['description'] = $this->GetDescription();
3337
		$cflink['weight'] = $this->GetWeight();
3338
		$cflink['enabled'] = $this->GetEnabled();
3339
		$cflink['buckets'] = $this->GetBuckets();
3340
		$cflink['mask'] = $this->GetMask();
3341
	}
3342
}
3343

    
3344
// List of layer7 objects
3345
$layer7_rules_list = array();
3346

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

    
3544
class l7rule {
3545
    
3546
    var $rprotocol; //protocol
3547
    var $rstructure; //action, limiter, queue
3548
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3549
    
3550
    //Auxiliary Functions
3551
    
3552
    function GetRProtocol() {
3553
        return $this->rprotocol;
3554
    }
3555
    function SetRProtocol($rprotocol) {
3556
        $this->rprotocol = $rprotocol;
3557
    }
3558
    function GetRStructure() {
3559
        return $this->rstructure;
3560
    }
3561
    function SetRStructure($rstructure) {
3562
        $this->rstructure = $rstructure;
3563
    }
3564
    function GetRBehaviour() {
3565
        return $this->rbehaviour;
3566
    }
3567
    function SetRBehaviour($rbehaviour) {
3568
        $this->rbehaviour = $rbehaviour;
3569
    }
3570
    
3571
    //XXX Do we need to test any particularity for AltQ queues?
3572
    function build_rules() {
3573
	global $dummynet_pipe_list;
3574
	switch ($this->GetRStructure()) {
3575
		case "limiter":
3576
			read_dummynet_config();
3577
			$dn_list =& get_unique_dnqueue_list();
3578
			$found = false;
3579
			if(is_array($dn_list)) {
3580
				foreach($dn_list as $key => $value) {
3581
					if($key == $this->GetRBehaviour()) {
3582
						if($value[0] == "?")
3583
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3584
						else
3585
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3586
						$found = true;
3587
					}
3588
					if($found)
3589
						break;
3590
				}
3591
			}
3592
			break;
3593
		default: //This is for action and for altq
3594
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3595
			break;
3596
	}
3597
        return $l7rule;
3598
    }
3599
}
3600

    
3601
/*
3602
 * This function allows to return an array with all the used divert socket ports
3603
 */
3604
function get_divert_ports() {
3605
    global $layer7_rules_list;
3606
    $dports = array();
3607
    
3608
    foreach($layer7_rules_list as $l7r)
3609
        $dports[] = $l7r->GetRPort();
3610
    
3611
    return $dports;
3612
}
3613

    
3614
function &get_l7c_reference_to_me_in_config(&$name) {
3615
	global $config;
3616
	
3617
	$ptr = NULL;
3618
	
3619
	if(is_array($config['l7shaper']['container'])) {
3620
		foreach($config['l7shaper']['container'] as $key => $value) {
3621
			if($value['name'] == $name)
3622
				$ptr =& $config['l7shaper']['container'][$key];
3623
		}
3624
	}	
3625
	return $ptr;
3626
// $ptr can be null. has to be checked later
3627
}
3628

    
3629
function unset_l7_object_by_reference(&$name) {
3630
	global $config;
3631
        
3632
	if(is_array($config['l7shaper']['container'])) {
3633
		foreach($config['l7shaper']['container'] as $key => $value) {
3634
			if($value['name'] == $name) {
3635
				unset($config['l7shaper']['container'][$key]['l7rules']);
3636
				unset($config['l7shaper']['container'][$key]);
3637
				break;
3638
			}
3639
		}
3640
	}
3641
}
3642

    
3643
function read_layer7_config() {
3644
    global $layer7_rules_list, $config;
3645
    
3646
    $l7cs = &$config['l7shaper']['container'];
3647
    
3648
    $layer7_rules_list = array();
3649
    
3650
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3651
	return;
3652
    
3653
    foreach ($l7cs as $conf) {
3654
	if (empty($conf['name']))
3655
		continue; /* XXX: grrrrrr at php */ 
3656
        $root =& new layer7();
3657
        $root->ReadConfig($conf['name'],$conf);
3658
        $layer7_rules_list[$root->GetRName()] = &$root;
3659
    }
3660
}
3661

    
3662
function generate_layer7_files() {
3663
    global $layer7_rules_list, $g;
3664
    
3665
    read_layer7_config();
3666
    
3667
    if (!empty($layer7_rules_list)) {
3668
	if (!is_module_loaded("ipdivert.ko"))
3669
		mwexec("/sbin/kldload ipdivert.ko");
3670

    
3671
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3672
    }
3673
    
3674
    foreach($layer7_rules_list as $l7rules) {
3675
        if($l7rules->GetREnabled()) {
3676
            $filename = $l7rules->GetRName() . ".l7";
3677
            $path = "{$g['tmp_path']}/" . $filename;
3678
        
3679
            $rules = $l7rules->build_l7_rules();
3680
        
3681
            $fp = fopen($path,'w');
3682
            fwrite($fp,$rules);
3683
            fclose($fp);
3684
        }
3685
    }
3686
}
3687

    
3688
function layer7_start_l7daemon() {
3689
    global $layer7_rules_list, $g;
3690

    
3691
    /*
3692
     * XXX: ermal - Needed ?!
3693
     * read_layer7_config();
3694
     */
3695

    
3696
    foreach($layer7_rules_list as $l7rules) {
3697
        if($l7rules->GetREnabled()) {
3698
            $filename = $l7rules->GetRName() . ".l7";
3699
            $path = "{$g['tmp_path']}/" . $filename;
3700

    
3701
	    unset($l7pid);
3702
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3703
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3704
	    if (count($l7pid) > 0) {
3705
		log_error("Sending HUP signal to {$l7pid[0]}");
3706
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3707
	    } else {
3708
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3709
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3710
		mwexec_bg($ipfw_classifyd_init);
3711
	    }
3712
        }
3713
    }
3714
}
3715

    
3716
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3717
function generate_protocols_array() {
3718
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3719
	$protocols_new = array();
3720
	if(is_array($protocols)) {
3721
		foreach($protocols as $key => $proto) {
3722
			if (strstr($proto, ".pat"))
3723
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3724
		}
3725
		sort($protocols_new);
3726
	}		
3727
	return $protocols_new;
3728
}
3729

    
3730
function get_l7_unique_list() {
3731
	global $layer7_rules_list;
3732
	
3733
	$l7list = array();
3734
	if(is_array($layer7_rules_list)) 
3735
		foreach($layer7_rules_list as $l7c)
3736
			if($l7c->GetREnabled())
3737
				$l7list[] = $l7c->GetRName();
3738
	
3739
	return $l7list;
3740
}
3741

    
3742
// Disable a removed l7 container from the filter
3743
function cleanup_l7_from_rules(&$name) {
3744
	global $config;
3745

    
3746
	if(is_array($config['filter']['rule']))
3747
		foreach ($config['filter']['rule'] as $key => $rule) {
3748
			if ($rule['l7container'] == $name)
3749
				unset($config['filter']['rule'][$key]['l7container']);
3750
		}
3751
}
3752

    
3753
function get_dummynet_name_list() {
3754
	
3755
	$dn_name_list =& get_unique_dnqueue_list();
3756
	$dn_name = array();
3757
	if(is_array($dn_name_list))
3758
		foreach($dn_name_list as $key => $value)
3759
			$dn_name[] = $key;
3760
	
3761
	return $dn_name;
3762
	
3763
}
3764

    
3765
function get_altq_name_list() {
3766
	$altq_name_list =& get_unique_queue_list();
3767
	$altq_name = array();
3768
	if(is_array($altq_name_list))
3769
		foreach($altq_name_list as $key => $aqobj)
3770
			$altq_name[] = $key;
3771
		
3772
	return $altq_name;
3773
}
3774

    
3775
/*
3776
 * XXX: TODO Make a class shaper to hide all these function
3777
 * from the global namespace.
3778
 */
3779

    
3780
/* 
3781
 * This is a layer violation but for now there is no way 
3782
 * i can find to properly do this with PHP.
3783
 */
3784
function altq_set_default_queue($interface, $value) {
3785
	global $altq_list_queues;
3786
		
3787
	$altq_tmp =& $altq_list_queues[$interface];
3788
	if ($altq_tmp) {
3789
		if ($value) {
3790
			$altq_tmp->SetDefaultQueuePresent("true");
3791
		}
3792
		else {
3793
			$altq_tmp->SetDefaultQueuePresent("false");
3794
		}
3795
	}
3796
}
3797

    
3798
function altq_get_default_queue($interface) {
3799
	global $altq_list_queues;
3800

    
3801
	$altq_tmp = $altq_list_queues[$interface];
3802
	if ($altq_tmp)  
3803
		return $altq_tmp->GetDefaultQueuePresent(); 
3804
}
3805

    
3806
function altq_check_default_queues() {
3807
	global $altq_list_queues;
3808

    
3809
	$count = 0;
3810
	if (is_array($altq_list_queues)) {
3811
		foreach($altq_list_queues as $altq) {
3812
			if ($altq->GetDefaultQueuePresent())
3813
				$count++;
3814
		}
3815
	}
3816
	else  $count++;;
3817
	
3818
	return 0;
3819
}
3820

    
3821
function &get_unique_queue_list() {
3822
	global $altq_list_queues;
3823
	
3824
	$qlist = array();
3825
	if (is_array($altq_list_queues)) {
3826
		foreach ($altq_list_queues as $altq) {
3827
			if ($altq->GetEnabled() == "")
3828
				continue;
3829
			$tmplist =& $altq->get_queue_list();
3830
			foreach ($tmplist as $qname => $link) {
3831
				if ($link->GetEnabled() <> "")
3832
					$qlist[$qname] = $link;	
3833
			}
3834
		}
3835
	}
3836
	return $qlist;
3837
}
3838

    
3839
function &get_unique_dnqueue_list() {
3840
	global $dummynet_pipe_list;
3841
	
3842
	$qlist = array();
3843
	if (is_array($dummynet_pipe_list)) {
3844
		foreach ($dummynet_pipe_list as $dn) {
3845
			if ($dn->GetEnabled() == "")
3846
				continue;
3847
			$tmplist =& $dn->get_queue_list();
3848
			foreach ($tmplist as $qname => $link) {
3849
				$qlist[$qname] = $link;	
3850
			}
3851
		}
3852
	}
3853
	return $qlist;
3854
}
3855

    
3856
function ref_on_altq_queue_list($parent, $qname) {
3857
	if (isset($GLOBALS['queue_list'][$qname]))
3858
		$GLOBALS['queue_list'][$qname]++;
3859
	else
3860
		$GLOBALS['queue_list'][$qname] = 1;
3861

    
3862
	unref_on_altq_queue_list($parent);
3863
}
3864

    
3865
function unref_on_altq_queue_list($qname) {
3866
	$GLOBALS['queue_list'][$qname]--;
3867
	if ($GLOBALS['queue_list'][$qname] <= 1)
3868
		unset($GLOBALS['queue_list'][$qname]);	
3869
}
3870

    
3871
function read_altq_config() {
3872
	global $altq_list_queues, $config;
3873
	$path = array();
3874
	
3875
	if (!is_array($config['shaper']))
3876
		$config['shaper'] = array();
3877
	if (!is_array($config['shaper']['queue']))
3878
		$config['shaper']['queue'] = array();
3879
	$a_int = &$config['shaper']['queue'];
3880

    
3881
	$altq_list_queues = array();
3882
	
3883
	if (!is_array($config['shaper']['queue']))
3884
		return;
3885

    
3886
	foreach ($a_int as $key => $conf) {
3887
		$int = $conf['interface'];
3888
		$root =& new altq_root_queue();
3889
		$root->SetInterface($int);
3890
		$altq_list_queues[$root->GetInterface()] = &$root;
3891
		$root->ReadConfig($conf);
3892
		array_push($path, $key);
3893
		$root->SetLink($path);
3894
		if (is_array($conf['queue'])) {
3895
			foreach ($conf['queue'] as $key1 => $q) {
3896
				array_push($path, $key1);
3897
				/* 
3898
				 * XXX: we compeletely ignore errors here but anyway we must have 
3899
				 *	checked them before so no harm should be come from this.
3900
				 */
3901
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3902
				array_pop($path);
3903
			} 	
3904
		}
3905
		array_pop($path);
3906
	}
3907
}
3908

    
3909
function read_dummynet_config() {
3910
	global $dummynet_pipe_list, $config;
3911
	$path = array();
3912
	$dnqueuenumber = 1;
3913
	$dnpipenumber = 1;
3914

    
3915
	if (!is_array($config['dnshaper']))
3916
		$config['dnshaper'] = array();
3917
	if (!is_array($config['dnshaper']['queue']))
3918
		$config['dnshaper']['queue'] = array();
3919
	$a_int = &$config['dnshaper']['queue'];
3920

    
3921
	$dummynet_pipe_list = array();
3922
	
3923
	if (!is_array($config['dnshaper']['queue'])
3924
		|| !count($config['dnshaper']['queue']))
3925
		return;
3926

    
3927
	foreach ($a_int as $key => $conf) {
3928
		if (empty($conf['name']))
3929
			continue; /* XXX: grrrrrr at php */ 
3930
		$root =& new dnpipe_class();
3931
		$root->ReadConfig($conf);
3932
		$root->SetNumber($dnpipenumber);	
3933
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3934
		array_push($path, $key);
3935
		$root->SetLink($path);
3936
		if (is_array($conf['queue'])) {
3937
			foreach ($conf['queue'] as $key1 => $q) {
3938
				array_push($path, $key1);
3939
				/* XXX: We cheat a little here till a better way is found. */
3940
				$q['number'] = $dnqueuenumber;
3941
				/* 
3942
				 * XXX: we compeletely ignore errors here but anyway we must have 
3943
				 *	checked them before so no harm should be come from this.
3944
				 */	
3945
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3946
				array_pop($path);
3947

    
3948
				$dnqueuenumber++;
3949
			} 	
3950
		}
3951
		array_pop($path);
3952
			
3953
		$dnpipenumber++;
3954
	}
3955
}
3956

    
3957
function get_interface_list_to_show() {
3958
	global $altq_list_queues, $config;
3959
	global $shaperIFlist;
3960

    
3961
	$tree = "";
3962
	foreach ($shaperIFlist as $shif => $shDescr) {
3963
		if ($altq_list_queues[$shif]) {
3964
			continue;
3965
		} else  {
3966
			if (!is_altq_capable(get_real_interface($shif)))
3967
				continue;
3968
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3969
		}
3970
	}
3971
	
3972
	return $tree;
3973
}
3974

    
3975
function filter_generate_altq_queues() {
3976
	global $altq_list_queues;
3977
	
3978
	read_altq_config();
3979

    
3980
	$altq_rules = "";
3981
	foreach ($altq_list_queues as $altq) 
3982
		$altq_rules .= $altq->build_rules();
3983

    
3984
	return $altq_rules;
3985
}
3986

    
3987
function filter_generate_dummynet_rules() {
3988
	global $g, $dummynet_pipe_list;
3989
	
3990
	read_dummynet_config();
3991
	
3992
	if (!empty($dummynet_pipe_list)) {
3993
		if (!is_module_loaded("dummynet.ko"))
3994
			mwexec("/sbin/kldload dummynet");
3995
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
3996
		//mwexec("pfctl -F dummynet");
3997
	}
3998

    
3999
	$dn_rules = "";
4000
	foreach ($dummynet_pipe_list as $dn) 
4001
		$dn_rules .= $dn->build_rules();
4002

    
4003
	if (!empty($dn_rules)) {
4004
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
4005
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
4006
	}
4007
	//return $dn_rules;
4008
}
4009

    
4010
function build_iface_without_this_queue($iface, $qname) {
4011
	global $g, $altq_list_queues;
4012

    
4013
	$altq =& $altq_list_queues[$iface];
4014
				if ($altq)
4015
						$scheduler = ": " . $altq->GetScheduler();
4016
	$form = "<tr><td width=\"20%\" >";
4017
	$form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
4018
		$form .= "</td></tr>";
4019
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
4020
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
4021
		$form .= $iface . "&queue=". $qname . "&action=add\">";
4022
		$form .= "<img src=\"";
4023
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
4024
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
4025
		$form .= " Clone shaper/queue on this interface</a></td></tr>";
4026

    
4027
		return $form;
4028

    
4029
}
4030

    
4031

    
4032
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
4033
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
4034
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
4035
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
4036
$default_shaper_msg .= " </p></strong></span>";
4037
$default_shaper_msg .= "</td></tr>";
4038

    
4039
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
4040
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
4041
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
4042
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
4043
$dn_default_shaper_msg .= " </p></strong></span>";
4044
$dn_default_shaper_msg .= "</td></tr>";
4045

    
4046
?>
(45-45/61)