Project

General

Profile

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

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

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

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

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

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

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

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

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

    
49
	return $ptr;
50
}
51

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

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

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

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

    
72
	return $ptr;
73
}
74

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
449
		return $q;
450
	}
451

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

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

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

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

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

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

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

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

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

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

    
602
		return $form;
603

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

    
691

    
692
		return $form;
693
	}
694

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

    
723
}
724

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

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

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

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

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

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

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

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

    
905
	 }
906

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

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

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

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

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

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

    
1024
	}
1025

    
1026
	function build_tree() {
1027
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
1028
		$tree .= "\" ";
1029
		$tmpvalue = $this->GetDefault();
1030
		if (!empty($tmpvalue))
1031
			$tree .= " class=\"navlnk\"";
1032
		$tree .= " >" . $this->GetQname() . "</a>";
1033
		/* 
1034
		 * Not needed here!
1035
		 * if (is_array($queues) {
1036
		 *	  $tree .= "<ul>";
1037
		 *	  foreach ($q as $queues) 
1038
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1039
		 *	  endforeach	
1040
		 *	  $tree .= "</ul>";
1041
		 * }
1042
		 */
1043

    
1044
		$tree .= "</li>"; 
1045

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

    
1093
		$pfq_rule .= " \n";
1094

    
1095
		return $pfq_rule;
1096
	}
1097

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

    
1176
		return $form;
1177
	}
1178

    
1179
	function build_shortform() {
1180
		/* XXX: Hacks in site. Mostly layer violations!  */
1181
		global $g, $altq_list_queues;
1182

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

    
1215
	}
1216

    
1217
		function update_altq_queue_data(&$q) { 
1218
		$this->ReadConfig($q);
1219
	}
1220

    
1221
	function wconfig() {
1222
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1223
		if (!is_array($cflink))
1224
			$cflink = array();
1225
		$cflink['name'] = $this->GetQname();
1226
		$cflink['interface'] = $this->GetInterface();
1227
		$cflink['qlimit'] = trim($this->GetQlimit());
1228
		if (empty($cflink['qlimit']))
1229
			unset($cflink['qlimit']);
1230
		$cflink['priority'] = trim($this->GetQpriority());
1231
		if (empty($cflink['priority']))
1232
			unset($cflink['priority']);
1233
		$cflink['description'] = trim($this->GetDescription());
1234
		if (empty($cflink['description']))
1235
			unset($cflink['description']);
1236
		$cflink['enabled'] = trim($this->GetEnabled());
1237
		if (empty($cflink['enabled']))
1238
			unset($cflink['enabled']);
1239
		$cflink['default'] = trim($this->GetDefault());
1240
		if (empty($cflink['default']))
1241
			unset($cflink['default']);
1242
		$cflink['red'] = trim($this->GetRed());
1243
		if (empty($cflink['red']))
1244
			unset($cflink['red']);
1245
		$cflink['rio'] = trim($this->GetRio());
1246
		if (empty($cflink['rio']))
1247
			unset($cflink['rio']);
1248
		$cflink['ecn'] = trim($this->GetEcn());
1249
		if (empty($cflink['ecn']))
1250
			unset($cflink['ecn']);
1251
	}
1252
}
1253

    
1254
class hfsc_queue extends priq_queue {
1255
	/* realtime */
1256
	var $realtime;
1257
	var $r_m1;
1258
	var $r_d;
1259
	var $r_m2;
1260
	/* linkshare */
1261
	var $linkshare;
1262
	var $l_m1;
1263
	var $l_d;
1264
	var $l_m2;
1265
	/* upperlimit */
1266
	var $upperlimit;
1267
	var $u_m1;
1268
	var $u_d;
1269
	var $u_m2;
1270

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

    
1359
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1360

    
1361
		if (!is_array($this->subqueues))
1362
			$this->subqueues = array();
1363
		$q =& new hfsc_queue();
1364
		$q->SetInterface($this->GetInterface());
1365
		$q->SetParent(&$this);
1366
		$q->ReadConfig($qname);
1367
		$q->validate_input($qname, $input_errors);
1368
		if (count($input_errors)) {
1369
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
1370
			return $q;
1371
		}
1372

    
1373
		$q->SetEnabled("on");
1374
		$q->SetLink($path);
1375
		switch ($q->GetBwscale()) {
1376
		case "%":
1377
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1378
			break;
1379
		default:
1380
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1381
			break;
1382
		}
1383
		$q->SetAvailableBandwidth($myBw);
1384
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1385

    
1386
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1387
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1388
		if (is_array($qname['queue'])) {
1389
			foreach ($qname['queue'] as $key1 => $que) {
1390
				array_push($path, $key1);
1391
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1392
				array_pop($path);
1393
			}
1394
		}
1395
	
1396
		return $q;
1397
	}
1398

    
1399
        function copy_queue($interface, &$cflink) {
1400

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

    
1484
		if (is_array($this->subqueues)) {
1485
			$cflinkp['queue'] = array();
1486
			foreach ($this->subqueues as $q) {
1487
				$cflink['queue'][$q->GetQname()] = array();
1488
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1489
			}
1490
		}
1491
	}
1492

    
1493
	function delete_queue() { 
1494
		unref_on_altq_queue_list($this->GetQname());
1495
		$tmpvalue = $this->GetDefault();
1496
		if (!empty($tmpvalue)) 
1497
			altq_set_default_queue($this->GetInterface(), "false");
1498
		cleanup_queue_from_rules($this->GetQname());
1499
		$parent =& $this->GetParent();
1500
		foreach ($this->subqueues as $q)  {
1501
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1502
			$q->delete_queue();
1503
		}
1504
		unset_object_by_reference($this->GetLink());
1505
	}
1506

    
1507
	/*
1508
	 * Should search even its children
1509
	 */
1510
	function &find_queue($interface, $qname) {
1511
		if ($qname == $this->GetQname()) 
1512
			return $this;
1513

    
1514
		foreach ($this->subqueues as $q) {
1515
			$result =& $q->find_queue("", $qname);
1516
			if ($result)
1517
				return $result;
1518
		}
1519
	}
1520

    
1521
	function &find_parentqueue($interface, $qname) {
1522
		if ($this->subqueues[$qname]) 
1523
			return $this;
1524
		foreach ($this->subqueues as $q) {
1525
			$result = $q->find_parentqueue("", $qname);
1526
			if ($result)
1527
				return $result;
1528
		}
1529
	}
1530
	
1531
	function validate_input($data, &$input_errors) {
1532
		parent::validate_input($data, $input_errors);
1533
		
1534
		$reqdfields[] = "bandwidth";
1535
		$reqdfieldsn[] = "Bandwidth";
1536
		$reqdfields[] = "bandwidthtype";
1537
		$reqdfieldsn[] = "Bandwidthtype";
1538

    
1539
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1540
		
1541
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1542
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1543
                        	$input_errors[] = "Bandwidth must be an integer.";
1544

    
1545
                	if ($data['bandwidth'] < 0)
1546
                        	$input_errors[] = "Bandwidth cannot be negative.";
1547

    
1548
			if ($data['bandwidthtype'] == "%") {
1549
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1550
					$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1551
			}
1552
		/*
1553
			$parent =& $this->GetParent();
1554
			switch ($data['bandwidthtype']) {
1555
			case "%":
1556
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1557
			default:
1558
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1559
				break;
1560
			}
1561
			if ($parent->GetAvailableBandwidth() < $myBw)
1562
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1563
		*/
1564
		}
1565

    
1566
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1567
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1568
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1569
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1570
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1571
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1572
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1573
			$input_errors[] = ("upperlimit d value needs to be numeric");
1574
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1575
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1576

    
1577
		/*
1578
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1579
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1580
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1581
			if (floatval($bw_1) < floatval($bw_2)) 
1582
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1583

    
1584
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1585
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1586
		}
1587
		*/
1588
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1589
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1590
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1591
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1592
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1593
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1594
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1595
			$input_errors[] = ("linkshare d value needs to be numeric");
1596
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1597
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1598
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1599
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1600
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1601
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1602

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

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

    
1615
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1616
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1617
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1618
			$input_errors[] = ("realtime d value needs to be numeric");
1619
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1620
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1621

    
1622
		/*
1623
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1624
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1625
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1626
                	if (floatval($bw_1) < floatval($bw_2))
1627
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1628

    
1629
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1630
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1631
		}
1632
		*/
1633

    
1634
	}
1635

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

    
1688
	function build_tree() {
1689
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1690
		$tree .= "\" ";
1691
		$tmpvalue = $this->GetDefault();
1692
		if (!empty($tmpvalue))
1693
			$tree .= " class=\"navlnk\"";
1694
		$tree .= " >" . $this->GetQname() . "</a>";
1695
		if (is_array($this->subqueues)) {
1696
			$tree .= "<ul>";
1697
			foreach ($this->subqueues as $q)  {
1698
				$tree .= $q->build_tree();
1699
			}	
1700
			$tree .= "</ul>";
1701
		}
1702
		$tree .= "</li>";
1703
		return $tree;
1704
	}
1705

    
1706
	/* Even this should take children into consideration */
1707
	function build_rules(&$default = false) {
1708

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

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

    
1792
		 $pfq_rule .= " \n";
1793
			
1794
		return $pfq_rule;
1795
	}
1796

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

    
1836
		return $javascript;
1837
	}
1838

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

    
1940
		return $form;
1941
	}
1942

    
1943
	function update_altq_queue_data(&$data) { 
1944
		$this->ReadConfig($data);
1945
	}
1946

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

    
2051
class cbq_queue extends priq_queue {
2052
	var $qborrow = "";
2053

    
2054
	function GetBorrow() {
2055
		return $this->qborrow;
2056
	}
2057
	function SetBorrow($borrow) {
2058
		$this->qborrow = $borrow;
2059
	}
2060
	function CanHaveChildren() {
2061
		return true;
2062
	}
2063

    
2064
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2065

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

    
2088
		$q->SetEnabled("on");
2089
		$q->SetLink($path);
2090
		$this->subqueues[$q->GetQName()] = &$q;
2091
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2092
		if (is_array($qname['queue'])) {
2093
			foreach ($qname['queue'] as $key1 => $que) {
2094
				array_push($path, $key1);
2095
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2096
				array_pop($path);
2097
			}
2098
		}
2099

    
2100
		return $q;
2101
	}
2102

    
2103
	function copy_queue($interface, &$cflink) {
2104

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

    
2158
	function &find_parentqueue($interface, $qname) {
2159
		if ($this->subqueues[$qname])
2160
			return $this;
2161
		foreach ($this->subqueues as $q) {
2162
			$result = $q->find_parentqueue("", $qname);
2163
			if ($result)
2164
				return $result;
2165
		}
2166
	}
2167

    
2168
	function delete_queue() {
2169
		unref_on_altq_queue_list($this->GetQname());
2170
		if ($this->GetDefault())
2171
			altq_set_default_queue($this->GetInterface(), "false");
2172
		cleanup_queue_from_rules($this->GetQname());
2173
		foreach ($this->subqueues as $q) {
2174
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2175
			$q->delete_queue();
2176
		}
2177
		unset_object_by_reference($this->GetLink());
2178
	}
2179
	
2180
	function validate_input($data, &$input_errors) {
2181
		parent::validate_input($data, $input_errors);
2182
		
2183
		if ($data['priority'] > 7)
2184
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2185
		$reqdfields[] = "bandwidth";
2186
		$reqdfieldsn[] = "Bandwidth";
2187
		$reqdfields[] = "bandwidthtype";
2188
		$reqdfieldsn[] = "Bandwidthtype";
2189

    
2190
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2191
		
2192
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2193
			$input_errors[] = "Bandwidth must be an integer.";
2194

    
2195

    
2196
		if ($data['bandwidth'] < 0)
2197
                       $input_errors[] = "Bandwidth cannot be negative.";
2198

    
2199
		if ($data['bandwidthtype'] == "%") {
2200
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2201
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2202
		}
2203

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

    
2218
	function ReadConfig(&$q) {
2219
		parent::ReadConfig($q);
2220
		if (!empty($q['borrow']))
2221
			$this->SetBorrow("on");
2222
		else
2223
			$this->SetBorrow("");
2224
	}
2225
		
2226
	function build_javascript() {
2227
		return parent::build_javascript();
2228
	}
2229

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

    
2313
		$pfq_rule .= " \n";
2314
		return $pfq_rule;
2315
	}
2316

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

    
2355
		return $form;
2356
	}
2357

    
2358
	function update_altq_queue_data(&$data) { 
2359
		$this->ReadConfig($data);
2360
	}
2361

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

    
2400
class fairq_queue extends priq_queue {
2401
	var $hogs;
2402
	var $buckets;
2403

    
2404
	function GetBuckets() {
2405
		return $this->buckets;
2406
	}
2407
	function SetBuckets($buckets) {
2408
		$this->buckets = $buckets;
2409
	}
2410
	function GetHogs() {
2411
		return $this->hogs;
2412
	}
2413
	function SetHogs($hogs) {
2414
		$this->hogs = $hogs;
2415
	}
2416
	function CanHaveChildren() {
2417
		return false;
2418
	}
2419

    
2420

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

    
2446
	function find_parentqueue($interface, $qname) { return; }
2447

    
2448
	function delete_queue() {
2449
		unref_on_altq_queue_list($this->GetQname());
2450
		if ($this->GetDefault())
2451
			altq_set_default_queue($this->GetInterface(), "false");
2452
		cleanup_queue_from_rules($this->GetQname());
2453
		unset_object_by_reference($this->GetLink());
2454
	}
2455
	
2456
	function validate_input($data, &$input_errors) {
2457
		parent::validate_input($data, $input_errors);
2458
		
2459
		if ($data['priority'] > 255)
2460
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2461
		$reqdfields[] = "bandwidth";
2462
		$reqdfieldsn[] = "Bandwidth";
2463
		$reqdfields[] = "bandwidthtype";
2464
		$reqdfieldsn[] = "Bandwidthtype";
2465

    
2466
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2467
		
2468
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2469
	                 $input_errors[] = "Bandwidth must be an integer.";
2470

    
2471

    
2472
	        if ($data['bandwidth'] < 0)
2473
                       $input_errors[] = "Bandwidth cannot be negative.";
2474

    
2475

    
2476
        	if ($data['bandwidthtype'] == "%") {
2477
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2478
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2479
           	}
2480

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

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

    
2581
		$pfq_rule .= " \n";
2582
		return $pfq_rule;
2583
	}
2584

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

    
2633
	function update_altq_queue_data(&$data) { 
2634
		$this->ReadConfig($data);
2635
	}
2636

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

    
2678

    
2679
/*
2680
 * dummynet(4) wrappers.
2681
 */
2682

    
2683

    
2684
/*
2685
 * List of respective objects!
2686
 */
2687
$dummynet_pipe_list = array();
2688

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

    
2699
        var $buckets;
2700
        /* mask parameters */
2701
        var $mask;
2702
        var $noerror;
2703

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

    
2778
	function build_javascript() { return; } /* Do not remove */
2779

    
2780
	function validate_input($data, &$input_errors) {
2781
		$reqdfields[] = "bandwidth";
2782
		$reqdfieldsn[] = "Bandwidth";
2783
		$reqdfields[] = "bandwidthtype";
2784
		$reqdfieldsn[] = "Bandwidthtype";
2785
		$reqdfields[] = "newname";
2786
		$reqdfieldsn[] = "Name";
2787
	
2788
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2789

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

    
2805
class dnpipe_class extends dummynet_class {
2806
        var $delay;
2807
	var $qbandwidth;
2808
	var $qbandwidthtype;
2809

    
2810
		/* This is here to help on form building and building rules/lists */
2811
        var $subqueues = array();
2812

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

    
2842
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2843

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

    
2863
	function &get_queue_list($q = null) {
2864
		$qlist = array();
2865

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

    
2887
	function &find_parentqueue($pipe, $qname) {
2888
		return NULL;
2889
       	}
2890

    
2891
	function validate_input($data, &$input_errors) {
2892
		parent::validate_input($data, $input_errors);
2893

    
2894
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2895
       		     	$input_errors[] = "Bandwidth must be an integer.";
2896
		if ($data['delay'] && (!is_numeric($data['delay'])))
2897
            		$input_errors[] = "Delay must be an integer.";
2898
		}
2899

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

    
2940
        }
2941

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

    
2957
        function build_rules() {
2958
		if ($this->GetEnabled() == "")
2959
			return;
2960

    
2961
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2962
		if ($this->GetBandwidth() && $this->GetBwscale())
2963
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2964
		if ($this->GetQlimit())
2965
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2966
		if ($this->GetPlr())
2967
			$pfq_rule .= " plr " . $this->GetPlr();
2968
		if ($this->GetBuckets())
2969
			$pfq_rule .= " buckets " . $this->GetBuckets();
2970
		if ($this->GetDelay())
2971
			$pfq_rule .= " delay " . $this->GetDelay();
2972

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

    
2988
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2989
       			        foreach ($this->subqueues as $q)
2990
				$pfq_rule .= $q->build_rules();
2991
               		}
2992
    		}            
2993
		$pfq_rule .= " \n";
2994

    
2995
		return $pfq_rule;
2996
        }
2997

    
2998
	function update_dn_data(&$data) { 
2999
		$this->ReadConfig($data);
3000
	}
3001

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

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

    
3118
		return $form;
3119
			
3120
		}
3121

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

    
3139
}
3140

    
3141
class dnqueue_class extends dummynet_class {
3142
        var $pipeparent;
3143
        var $weight;
3144

    
3145
        function GetWeight() {
3146
                return $this->weight;
3147
        }
3148
        function SetWeight($weight) {
3149
                $this->weight = $weight;
3150
        }
3151
	function GetPipe() {
3152
		return $this->pipeparent;
3153
	}
3154
	function SetPipe($pipe) {
3155
		$this->pipeparent = $pipe;
3156
	}
3157

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

    
3161
	function delete_queue() {
3162
		cleanup_dnqueue_from_rules($this->GetQname());
3163
		unset_dn_object_by_reference($this->GetLink());
3164
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3165
        }
3166

    
3167
	function validate_input($data, &$input_errors) {
3168
		parent::validate_input($data, $input_errors);
3169

    
3170
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3171
			($data['weight'] < 1 && $data['weight'] > 100))) 
3172
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3173
	}
3174

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

    
3185
	function &find_parentqueue($pipe, $qname) {
3186
		return $this->qparent;
3187
        }
3188

    
3189
        function &get_queue_list(&$qlist) {
3190
		if ($this->GetEnabled() == "")
3191
			return;
3192
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3193
        }		
3194

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

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

    
3232
        function build_rules() {
3233
		if ($this->GetEnabled() == "")
3234
			return; 
3235

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

    
3260
		return $pfq_rule;
3261
	}
3262

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

    
3355
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3356
		$form .= " value=\"" . $this->GetPipe() . "\">";
3357

    
3358
		return $form;
3359
			
3360
	}
3361

    
3362
        function update_dn_data(&$data) { 
3363
		$this->ReadConfig($data);
3364
	}
3365

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

    
3381
// List of layer7 objects
3382
$layer7_rules_list = array();
3383

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

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

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

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

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

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

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

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

    
3725
function layer7_start_l7daemon() {
3726
    global $layer7_rules_list, $g;
3727

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

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

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

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

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

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

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

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

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

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

    
3817
/* 
3818
 * This is a layer violation but for now there is no way 
3819
 * i can find to properly do this with PHP.
3820
 */
3821
function altq_set_default_queue($interface, $value) {
3822
	global $altq_list_queues;
3823
		
3824
	$altq_tmp =& $altq_list_queues[$interface];
3825
	if ($altq_tmp) {
3826
		if ($value) {
3827
			$altq_tmp->SetDefaultQueuePresent("true");
3828
		}
3829
		else {
3830
			$altq_tmp->SetDefaultQueuePresent("false");
3831
		}
3832
	}
3833
}
3834

    
3835
function altq_get_default_queue($interface) {
3836
	global $altq_list_queues;
3837

    
3838
	$altq_tmp = $altq_list_queues[$interface];
3839
	if ($altq_tmp)  
3840
		return $altq_tmp->GetDefaultQueuePresent(); 
3841
}
3842

    
3843
function altq_check_default_queues() {
3844
	global $altq_list_queues;
3845

    
3846
	$count = 0;
3847
	if (is_array($altq_list_queues)) {
3848
		foreach($altq_list_queues as $altq) {
3849
			if ($altq->GetDefaultQueuePresent())
3850
				$count++;
3851
		}
3852
	}
3853
	else  $count++;;
3854
	
3855
	return 0;
3856
}
3857

    
3858
function &get_unique_queue_list() {
3859
	global $altq_list_queues;
3860
	
3861
	$qlist = array();
3862
	if (is_array($altq_list_queues)) {
3863
		foreach ($altq_list_queues as $altq) {
3864
			if ($altq->GetEnabled() == "")
3865
				continue;
3866
			$tmplist =& $altq->get_queue_list();
3867
			foreach ($tmplist as $qname => $link) {
3868
				if ($link->GetEnabled() <> "")
3869
					$qlist[$qname] = $link;	
3870
			}
3871
		}
3872
	}
3873
	return $qlist;
3874
}
3875

    
3876
function &get_unique_dnqueue_list() {
3877
	global $dummynet_pipe_list;
3878
	
3879
	$qlist = array();
3880
	if (is_array($dummynet_pipe_list)) {
3881
		foreach ($dummynet_pipe_list as $dn) {
3882
			if ($dn->GetEnabled() == "")
3883
				continue;
3884
			$tmplist =& $dn->get_queue_list();
3885
			foreach ($tmplist as $qname => $link) {
3886
				$qlist[$qname] = $link;	
3887
			}
3888
		}
3889
	}
3890
	return $qlist;
3891
}
3892

    
3893
function ref_on_altq_queue_list($parent, $qname) {
3894
	if (isset($GLOBALS['queue_list'][$qname]))
3895
		$GLOBALS['queue_list'][$qname]++;
3896
	else
3897
		$GLOBALS['queue_list'][$qname] = 1;
3898

    
3899
	unref_on_altq_queue_list($parent);
3900
}
3901

    
3902
function unref_on_altq_queue_list($qname) {
3903
	$GLOBALS['queue_list'][$qname]--;
3904
	if ($GLOBALS['queue_list'][$qname] <= 1)
3905
		unset($GLOBALS['queue_list'][$qname]);	
3906
}
3907

    
3908
function read_altq_config() {
3909
	global $altq_list_queues, $config;
3910
	$path = array();
3911
	
3912
	if (!is_array($config['shaper']))
3913
		$config['shaper'] = array();
3914
	if (!is_array($config['shaper']['queue']))
3915
		$config['shaper']['queue'] = array();
3916
	$a_int = &$config['shaper']['queue'];
3917

    
3918
	$altq_list_queues = array();
3919
	
3920
	if (!is_array($config['shaper']['queue']))
3921
		return;
3922

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

    
3946
function read_dummynet_config() {
3947
	global $dummynet_pipe_list, $config;
3948
	$path = array();
3949
	$dnqueuenumber = 1;
3950
	$dnpipenumber = 1;
3951

    
3952
	if (!is_array($config['dnshaper']))
3953
		$config['dnshaper'] = array();
3954
	if (!is_array($config['dnshaper']['queue']))
3955
		$config['dnshaper']['queue'] = array();
3956
	$a_int = &$config['dnshaper']['queue'];
3957

    
3958
	$dummynet_pipe_list = array();
3959
	
3960
	if (!is_array($config['dnshaper']['queue'])
3961
		|| !count($config['dnshaper']['queue']))
3962
		return;
3963

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

    
3985
				$dnqueuenumber++;
3986
			} 	
3987
		}
3988
		array_pop($path);
3989
			
3990
		$dnpipenumber++;
3991
	}
3992
}
3993

    
3994
function get_interface_list_to_show() {
3995
	global $altq_list_queues, $config;
3996
	global $shaperIFlist;
3997

    
3998
	$tree = "";
3999
	foreach ($shaperIFlist as $shif => $shDescr) {
4000
		if ($altq_list_queues[$shif]) {
4001
			continue;
4002
		} else  {
4003
			if (!is_altq_capable(get_real_interface($shif)))
4004
				continue;
4005
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
4006
		}
4007
	}
4008
	
4009
	return $tree;
4010
}
4011

    
4012
function filter_generate_altq_queues() {
4013
	global $altq_list_queues;
4014
	
4015
	read_altq_config();
4016

    
4017
	$altq_rules = "";
4018
	foreach ($altq_list_queues as $altq) 
4019
		$altq_rules .= $altq->build_rules();
4020

    
4021
	return $altq_rules;
4022
}
4023

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

    
4036
	$dn_rules = "";
4037
	foreach ($dummynet_pipe_list as $dn) 
4038
		$dn_rules .= $dn->build_rules();
4039

    
4040
	if (!empty($dn_rules)) {
4041
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
4042
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
4043
	}
4044
	//return $dn_rules;
4045
}
4046

    
4047
function build_iface_without_this_queue($iface, $qname) {
4048
	global $g, $altq_list_queues;
4049

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

    
4064
	return $form;
4065

    
4066
}
4067

    
4068

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

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

    
4083
?>
(45-45/61)