Project

General

Profile

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

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

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

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

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

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

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

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

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

    
50
	return $ptr;
51
}
52

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

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

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

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

    
73
	return $ptr;
74
}
75

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
225
class altq_root_queue {
226
	var $interface;
227
	var $tbrconfig ;
228
	var $bandwidth;
229
	var $bandwidthtype; /* b, Kb, Mb */
230
	var $scheduler;
231
	var $qlimit;
232
	var $queues = array();
233
	var $qenabled = false;
234
	var $link;
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 GetDefaultQueuePresent() {
245
		if (!empty($this->queues)) {
246
			foreach ($this->queues as $q) {
247
				if ($q->GetDefault())
248
					return true;
249
			}
250
		}
251

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

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

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

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

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

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

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

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

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

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

    
453
		return $q;
454
	}
455

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

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

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

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

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

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

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

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

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

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

    
606
		return $form;
607

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

    
695

    
696
		return $form;
697
	}
698

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

    
727
}
728

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

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

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

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

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

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

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

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

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

    
920
	 }
921

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

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

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

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

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

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

    
1038
	}
1039

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

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

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

    
1107
		$pfq_rule .= " \n";
1108

    
1109
		return $pfq_rule;
1110
	}
1111

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

    
1189
		return $form;
1190
	}
1191

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

    
1229
	}
1230

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1846
		return $javascript;
1847
	}
1848

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

    
1950
		return $form;
1951
	}
1952

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

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

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

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

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

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

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

    
2110
		return $q;
2111
	}
2112

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

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

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

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

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

    
2203

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

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

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

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

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

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

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

    
2364
		return $form;
2365
	}
2366

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

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

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

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

    
2429

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

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

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

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

    
2478

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

    
2482

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

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

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

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

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

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

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

    
2685

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

    
2690

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2947
        }
2948

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

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

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

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

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

    
3002
		return $pfq_rule;
3003
        }
3004

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

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

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

    
3124
		return $form;
3125
			
3126
		}
3127

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

    
3145
}
3146

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3266
		return $pfq_rule;
3267
	}
3268

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

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

    
3363
		return $form;
3364
			
3365
	}
3366

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

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

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

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

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

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

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

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

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

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

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

    
3729
function layer7_start_l7daemon() {
3730
    global $layer7_rules_list, $g;
3731

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

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

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

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

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

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

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

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

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

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

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

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

    
3835
function altq_check_default_queues() {
3836
	global $altq_list_queues;
3837

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

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

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

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

    
3891
	unref_on_altq_queue_list($parent);
3892
}
3893

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

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

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

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

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

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

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

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

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

    
3986
function get_interface_list_to_show() {
3987
	global $altq_list_queues, $config;
3988
	global $shaperIFlist;
3989

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

    
4004
function filter_generate_altq_queues() {
4005
	global $altq_list_queues;
4006
	
4007
	read_altq_config();
4008

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

    
4013
	return $altq_rules;
4014
}
4015

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

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

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

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

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

    
4057
	return $form;
4058

    
4059
}
4060

    
4061

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

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

    
4076
?>
(48-48/65)