Project

General

Profile

Download (146 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
		if ($this->GetScheduler() == "CODELQ")
268
			return false;
269
		else
270
			return true;
271
	}
272
	function CanBeDeleted() {
273
		return false;
274
	}
275
	function GetQname() {
276
		return $this->interface;
277
	}
278
	function SetQname($name) {
279
		$this->interface = trim($name);
280
	}
281
	function GetInterface() {
282
		return $this->interface;
283
	}
284
	function SetInterface($name) {
285
		$this->interface = trim($name);
286
	}
287
	function GetTbrConfig() {
288
		return $this->tbrconfig;
289
	}
290
	function SetTbrConfig($tbrconfig) {
291
		$this->tbrconfig = $tbrconfig;
292
	}
293
	function GetBandwidth() {
294
		return $this->bandwidth;
295
	}
296
	function SetBandwidth($bw) {
297
		$this->bandwidth = $bw;
298
	}
299
	function GetBwscale() {
300
		return $this->bandwidthtype;
301
	}
302
	function SetBwscale($bwscale) {
303
		$this->bandwidthtype = $bwscale;
304
	}
305
	function GetScheduler() {
306
		return $this->scheduler;
307
	}
308
	function SetScheduler($scheduler) {
309
		$this->scheduler = trim($scheduler);
310
	}
311
	function GetQlimit() {
312
		return $this->qlimit;
313
	}
314
	function SetQlimit($limit) {
315
		$this->qlimit = $limit;
316
	}
317

    
318
	function validate_input($data, &$input_errors) {
319

    
320
		$reqdfields[] = "bandwidth";
321
		$reqdfieldsn[] = gettext("Bandwidth");
322
		$reqdfields[] = "bandwidthtype";
323
		$reqdfieldsn[] = gettext("Bandwidthtype");
324

    
325
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
326

    
327
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
328
			$input_errors[] = gettext("Bandwidth must be an integer.");
329
                if ($data['bandwidth'] < 0)
330
			$input_errors[] = gettext("Bandwidth cannot be negative.");
331
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
332
			$input_errors[] = gettext("Qlimit must be an integer.");
333
	 	if ($data['qlimit'] < 0)
334
			$input_errors[] = gettext("Qlimit must be positive.");
335
                if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig'])))
336
			$input_errors[] = gettext("Tbrsize must be an integer.");
337
                if ($data['tbrconfig'] < 0)
338
			$input_errors[] = gettext("Tbrsize must be positive.");
339
	}
340

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

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

    
389
	function &get_queue_list(&$q = null) {
390
		$qlist = array();
391

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

    
400
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
401

    
402
		if (!is_array($this->queues))
403
			$this->queues = array();
404

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

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

    
456
		return $q;
457
	}
458

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

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

    
485
	function build_tree() {
486
		global $shaperIFlist;
487

    
488
		$tree = " <li><a href=\"firewall_shaper.php?interface=".$this->GetInterface()."&amp;queue=". $this->GetInterface()."&amp;action=show"; 
489
		$tree .= "\">" . $shaperIFlist[$this->GetInterface()] . "</a>";
490
		if (is_array($this->queues)) {
491
			$tree .= "<ul>";
492
			foreach ($this->queues as $q)  {
493
				$tree .= $q->build_tree();
494
			}
495
		$tree .= "</ul>";
496
		}
497
		$tree .= "</li>";
498
		return $tree;
499
	}
500

    
501
	function delete_queue() { 
502
		foreach ($this->queues as $q) {
503
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
504
			$q->delete_queue();			
505
		}
506
		unset_object_by_reference($this->GetLink());
507
	 }
508

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

    
520
	/*
521
	 * First it spits:
522
	 * altq on $interface ..............
523
	 *      then it goes like
524
	 *      foreach ($queues as $qkey => $queue)
525
	 *              this->queues[$qkey]->build_rule();
526
	 */
527
	function build_rules(&$default = false) {
528
		if (count($this->queues) > 0 && $this->GetEnabled() == "on") {
529
			$default = false;
530
			$rules = " altq on  " . get_real_interface($this->GetInterface());
531
			if ($this->GetScheduler())
532
				$rules .= " ".strtolower($this->GetScheduler());
533
			if ($this->GetBandwidth()) {
534
				$rules .= " bandwidth ".trim($this->GetBandwidth());
535
				if ($this->GetBwscale())
536
					$rules .= $this->GetBwscale();
537
			}
538
			if ($this->GetTbrConfig())
539
				$rules .= " tbrsize ".$this->GetTbrConfig();
540
			if (count($this->queues)) {
541
				$i = count($this->queues);
542
				$rules .= " queue { ";
543
				foreach ($this->queues as $qkey => $qnone) {
544
					if ($i > 1) {
545
						$i--;
546
						$rules .= " {$qkey}, ";
547
					} else
548
						$rules .= " {$qkey} ";
549
				}
550
				$rules .= " } \n";
551
				foreach ($this->queues as $q) {
552
					$rules .= $q->build_rules($default);
553
				}
554
			}
555

    
556
			if ($default == false) {
557
				$error = "SHAPER: no default queue specified for interface ". $this->GetInterface() . ". The interface queue will be enforced as default.";
558
				file_notice("Shaper", $error, "Error occurred", "");
559
				unset($error);
560
				return "\n";
561
			} 
562
			$frule .= $rules;
563
		} else if ($this->GetEnabled() == "on" && $this->GetScheduler() == "CODELQ") {
564
			$rules = " altq on  " . get_real_interface($this->GetInterface());
565
			if ($this->GetScheduler())
566
				$rules .= " ".strtolower($this->GetScheduler());
567
			if ($this->GetQlimit() > 0)
568
				$rules .= " ( qlimit " . $this->GetQlimit() . " ) ";
569
			if ($this->GetBandwidth()) {
570
				$rules .= " bandwidth ".trim($this->GetBandwidth());
571
				if ($this->GetBwscale())
572
					$rules .= $this->GetBwscale();
573
			}
574
			if ($this->GetTbrConfig())
575
				$rules .= " tbrsize ".$this->GetTbrConfig();
576

    
577
			$rules .= " queue";
578
		}
579

    
580
		$rules .= " \n";
581
		return $rules;
582
	}
583

    
584
	function build_javascript() {
585
		$javascript = "<script type=\"text/javascript\">";
586
		$javascript .= "//<![CDATA[\n";
587
		$javascript .= "function mySuspend() {";
588
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null) ";
589
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden'; ";
590
		$javascript .= "else if (document.all)";
591
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';";
592
		$javascript .= "}";
593

    
594
		$javascript .= "function myResume() {";
595
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null) ";
596
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';";
597
		$javascript .= "else if (document.all) ";
598
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';";
599
		$javascript .= "}";
600
		$javascript .= "//]]>";
601
		$javascript .= "</script>";
602

    
603
		return $javascript;
604
	}
605

    
606
	function build_shortform() {
607
		global $g;
608

    
609
		$altq =& $this;
610
		if ($altq)
611
			$scheduler = ": " . $altq->GetScheduler();
612
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
613
		$form .= "<a href=\"firewall_shaper.php?interface=" . $this->GetInterface() . "&amp;queue=". $this->GetInterface()."&amp;action=show\">". $shaperIFlist[$this->GetInterface()] .": ".$scheduler."</a>";
614
		$form .= "</td></tr>";
615
		$form .= "<tr>";
616
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
617
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
618
		$form .= "</td><td width=\"50%\"></td></tr>";
619
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
620
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
621
		$form .= $this->GetInterface() . "&amp;queue=";
622
		$form .= $this->GetQname() . "&amp;action=delete\">";
623
		$form .= "<img src=\"";
624
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
625
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Disable shaper on interface\" alt=\"disable\" />";
626
		$form .= "<span>Disable shaper on interface</span></a></td></tr>";
627

    
628
		return $form;
629

    
630
	}
631
	/*
632
	 * For requesting the parameters of the root queues
633
	 * to the user like the traffic wizard does.
634
	 */
635
	function build_form() { 
636
		$form = "<tr><td valign=\"middle\" class=\"vncellreq\"><br/>";
637
		$form .= gettext("Enable/Disable");
638
		$form .= "<br/></td><td class=\"vncellreq\">";
639
		$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
640
                if ($this->GetEnabled() == "on")
641
                        $form .=  " checked=\"checked\"";
642
		$form .= " /><span class=\"vexpl\"> " . gettext("Enable/disable discipline and its children") . "</span>";
643
		$form .= "</td></tr>";
644
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\"><br/><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
645
		$form .= "<td class=\"vncellreq\">";
646
		$form .= "<strong>".$this->GetQname()."</strong>";
647
		$form .= "</td></tr>";
648
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Scheduler Type ");
649
		$form .= "</td>";
650
		$form .= "<td class=\"vncellreq\">";
651
		$form .= "<select id=\"scheduler\" name=\"scheduler\" class=\"formselect\">";
652
		$form .= "<option value=\"HFSC\"";
653
		if ($this->GetScheduler() == "HFSC")
654
			$form .= " selected=\"selected\"";
655
		$form .= ">HFSC</option>";
656
		$form .= "<option value=\"CBQ\"";
657
		if ($this->GetScheduler() == "CBQ")
658
			$form .= " selected=\"selected\"";
659
		$form .= ">CBQ</option>";
660
		$form .= "<option value=\"FAIRQ\"";
661
                if ($this->GetScheduler() == "FAIRQ")
662
                	$form .= " selected=\"selected\"";
663
                $form .= ">FAIRQ</option>";
664
		$form .= "<option value=\"CODELQ\"";
665
                if ($this->GetScheduler() == "CODELQ")
666
                	$form .= " selected=\"selected\"";
667
                $form .= ">CODELQ</option>";
668
		$form .= "<option value=\"PRIQ\"";
669
		if ($this->GetScheduler() == "PRIQ")
670
			$form .= " selected=\"selected\"";
671
		$form .= ">PRIQ</option>";
672
		$form .= "</select>";
673
		$form .= "<br/> <span class=\"vexpl\">";
674
		$form .= gettext("NOTE: Changing this changes all child queues!");
675
		$form .= gettext(" Beware you can lose information.");
676
		$form .= "</span>";
677
		$form .= "</td></tr>";
678
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth");
679
		$form .= "</td><td class=\"vncellreq\">";
680
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
681
		$form .= $this->GetBandwidth() . "\" />"; 
682
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
683
		$form .= "<option value=\"Kb\"";
684
		if ($this->GetBwscale() == "Kb")
685
			$form .= " selected=\"selected\"";
686
		$form .= ">Kbit/s</option>";
687
		$form .= "<option value=\"Mb\"";
688
		if ($this->GetBwscale() == "Mb")
689
			$form .= " selected=\"selected\"";
690
		$form .= ">Mbit/s</option>";
691
		$form .= "<option value=\"Gb\"";
692
		if ($this->GetBwscale() == "Gb")
693
			$form .= " selected=\"selected\"";
694
		$form .= ">Gbit/s</option>";		
695
		$form .= "<option value=\"b\"";
696
		if ($this->GetBwscale() == "b")
697
			$form .= " selected=\"selected\"";
698
		$form .= ">Bit/s</option>";
699
		$form .= "</select>";
700
		$form .= "</td></tr>";
701
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">Queue Limit</td>";
702
		$form .= "<td class=\"vncellreq\">";
703
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
704
		$form .= $this->GetQlimit();
705
		$form .= "\" />";
706
		$form .= "</td></tr>";
707
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">TBR Size</td>";
708
		$form .= "<td class=\"vncellreq\">";
709
		$form .= "<br /><input type=\"text\" id=\"tbrconfig\" name=\"tbrconfig\" value=\"";
710
		$form .= $this->GetTbrConfig();
711
		$form .= "\" />";
712
		$form .= "<br/> <span class=\"vexpl\">";
713
		$form .= gettext("Adjusts the size, in bytes, of the token bucket regulator. "
714
		      .  "If not specified, heuristics based on the interface "
715
		      .  "bandwidth are used to determine the size.");
716
		$form .= "</span></td></tr>";
717
		$form .= "<input type=\"hidden\" id=\"interface\" name=\"interface\"";
718
		$form .= " value=\"" . $this->GetInterface() . "\" />";
719
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"".$this->GetQname()."\" />";
720

    
721

    
722
		return $form;
723
	}
724

    
725
	function update_altq_queue_data(&$data) { 
726
		$this->ReadConfig($data);
727
	}
728

    
729
	/*
730
	 * Should call on each of it queues and subqueues
731
	 * the same function much like build_rules();
732
	 */
733
	function wconfig() { 
734
		$cflink = &get_reference_to_me_in_config($this->GetLink());
735
		if (!is_array($cflink))
736
			$cflink = array();
737
		$cflink['interface'] = $this->GetInterface();	
738
		$cflink['name'] = $this->GetQname();
739
		$cflink['scheduler'] = $this->GetScheduler();
740
		$cflink['bandwidth'] = $this->GetBandwidth();
741
		$cflink['bandwidthtype'] = $this->GetBwscale();
742
		$cflink['qlimit'] = trim($this->GetQlimit());
743
		if (empty($cflink['qlimit']))
744
			unset($cflink['qlimit']);
745
		$cflink['tbrconfig'] = trim($this->GetTbrConfig());
746
		if (empty($cflink['tbrconfig']))
747
			unset($cflink['tbrconfig']);
748
		$cflink['enabled'] = $this->GetEnabled();
749
		if (empty($cflink['enabled']))
750
			unset($cflink['enabled']);
751
	}
752

    
753
}
754

    
755
class priq_queue {
756
	var $qname;
757
	var $qinterface; 
758
	var $qlimit;
759
	var $qpriority;
760
	var $description;
761
	var $isparent;
762
	var $qbandwidth;
763
	var $qbandwidthtype;
764
	var $qdefault = "";
765
	var $qrio = "";
766
	var $qred = "";
767
	var $qcodel = "";
768
	var $qecn = "";
769
	var $qack;
770
	var $qenabled = "";
771
	var $qparent;
772
	var $link;
773
	var $available_bw; /* in b/s */
774

    
775
	/* This is here to help with form building and building rules/lists */
776
	var $subqueues = array();
777

    
778
	/* Accesor functions */
779
	function GetAvailableBandwidth() {
780
		return $this->available_bw;
781
	}
782
	function SetAvailableBandwidth($bw) {
783
		$this->available_bw = $bw;
784
	}
785
	function SetLink($link) {
786
		$this->link = $link;
787
	}
788
	function GetLink() {
789
		return $this->link;
790
	}
791
	function &GetParent() {
792
		return $this->qparent;
793
	}
794
	function SetParent(&$parent) {
795
		$this->qparent = &$parent;
796
	}
797
	function GetEnabled() {
798
		return $this->qenabled;
799
	}
800
	function SetEnabled($value) {
801
		$this->qenabled = $value;
802
	}
803
	function CanHaveChildren() {
804
		return false;
805
	}
806
	function CanBeDeleted() {
807
		return true;
808
	}
809
	function GetQname() {
810
		return $this->qname;
811
	}
812
	function SetQname($name) {
813
		$this->qname = trim($name);
814
	}
815
	function GetBandwidth() {
816
		return $this->qbandwidth;
817
	}
818
	function SetBandwidth($bandwidth) {
819
		$this->qbandwidth = $bandwidth;
820
	}
821
	function GetInterface() {
822
		return $this->qinterface;
823
	}
824
	function SetInterface($name) {
825
		$this->qinterface = trim($name);
826
	}
827
	function GetQlimit() {
828
		return $this->qlimit;
829
	}
830
	function SetQlimit($limit) {
831
		$this->qlimit = $limit;
832
	}
833
	function GetQpriority() {
834
		return $this->qpriority;
835
	}
836
	function SetQpriority($priority) {
837
		$this->qpriority = $priority;
838
	}
839
	function GetDescription() {
840
		return $this->description;
841
	}
842
	function SetDescription($str) {
843
		$this->description = trim($str);
844
	}
845
	function GetFirstime() {
846
		return $this->firsttime;
847
	}
848
	function SetFirsttime($number) {
849
		$this->firsttime = $number;
850
	}
851
	function GetBwscale() {
852
		return $this->qbandwidthtype;
853
	}
854
	function SetBwscale($scale) {
855
		$this->qbandwidthtype = $scale;
856
	}
857
	function GetDefaultQueuePresent() {
858
		if ($this->GetDefault())
859
			return true;
860
		if (!empty($this->subqueues)) {
861
			foreach ($this->subqueues as $q) {
862
				if ($q->GetDefault())
863
					return true;
864
			}
865
		}
866

    
867
		return false;
868
	}
869
	function GetDefault() {
870
		return $this->qdefault;
871
	}
872
	function SetDefault($value = false) {
873
		$this->qdefault = $value;
874
	}
875
	function GetCodel() {
876
		return $this->codel;
877
	}
878
	function SetCodel($codel = false) {
879
		$this->codel = $codel;
880
	}
881
	function GetRed() {
882
		return $this->qred;
883
	}
884
	function SetRed($red = false) {
885
		$this->qred = $red;
886
	}
887
	function GetRio() {
888
		return $this->qrio;
889
	}
890
	function SetRio($rio = false) {
891
		$this->qrio = $rio;
892
	}
893
	function GetEcn() {
894
		return $this->qecn;
895
	}
896
	function SetEcn($ecn = false) {
897
		$this->qecn = $ecn;
898
	}
899
	function GetAck() {
900
		return $this->qack;
901
	}
902
	function SetAck($ack = false) {
903
		$this->qack = $ack;
904
	}
905

    
906
	function build_javascript() {
907
		$javascript = "<script type=\"text/javascript\">";
908
		$javascript .= "//<![CDATA[\n";
909
		$javascript .= "function mySuspend() { \n";
910
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
911
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
912
		$javascript .= "else if (document.all)\n";
913
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
914
		$javascript .= "}\n";
915

    
916
		$javascript .= "function myResume() {\n";
917
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
918
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
919
		$javascript .= "else if (document.all)\n";
920
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
921
		$javascript .= "}\n";
922
		$javascript .= "//]]>";
923
		$javascript .= "</script>";
924

    
925
		return $javascript;
926
	}
927

    
928
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
929

    
930
	/* 
931
	 * Currently this will not be called unless we decide to clone a whole 
932
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
933
	 */
934
	 function copy_queue($interface, &$cflink) {
935

    
936
 		$cflink['name'] = $this->GetQname();
937
                $cflink['interface'] = $interface;
938
                $cflink['qlimit'] = $this->GetQlimit();
939
                $cflink['priority'] = $this->GetQpriority();
940
                $cflink['description'] = $this->GetDescription();
941
                $cflink['enabled'] = $this->GetEnabled();
942
                $cflink['default'] = $this->GetDefault();
943
                $cflink['red'] = $this->GetRed();
944
                $cflink['codel'] = $this->GetCodel();
945
                $cflink['rio'] = $this->GetRio();
946
                $cflink['ecn'] = $this->GetEcn();
947

    
948
                if (is_array($this->subqueues)) {
949
                        $cflinkp['queue'] = array();
950
                        foreach ($this->subqueues as $q) {
951
				 $cflink['queue'][$q->GetQname()] = array();
952
                                $q->copy_queue($interface, $cflink['queue'][$q->GetQname()]);
953
			}
954
                }
955

    
956
	 }
957

    
958
	function clean_queue($sched) {
959
		clean_child_queues($sched, $this->GetLink());
960
		if (is_array($this->subqueues)) {
961
			foreach ($this->subqueues as $q)
962
				$q->clean_queue($sched);
963
		}
964
	}
965

    
966
        function &get_queue_list(&$qlist) {
967

    
968
		$qlist[$this->GetQname()] = & $this;
969
		if (is_array($this->subqueues)) {
970
			foreach ($this->subqueues as $queue)
971
				$queue->get_queue_list($qlist);
972
		}
973
	}
974

    
975
	function delete_queue() {
976
		unref_on_altq_queue_list($this->GetQname());
977
		cleanup_queue_from_rules($this->GetQname());
978
		unset_object_by_reference($this->GetLink());
979
	}
980

    
981
	function delete_all() {
982
                if (count($this->subqueues)) {
983
                        foreach ($this->subqueues as $q) {
984
                                $q->delete_all();
985
                                unset_object_by_reference($q->GetLink());
986
                                unset($q);
987
                        }
988
                        unset($this->subqueues);
989
                }
990
        }
991

    
992
	 function &find_queue($interface, $qname) { 
993
		if ($qname == $this->GetQname())
994
			return $this; 
995
	}
996

    
997
	function find_parentqueue($interface, $qname) { return; }
998

    
999
	function validate_input($data, &$input_errors) {
1000

    
1001
		$reqdfields[] = "name";
1002
		$reqdfieldsn[] = gettext("Name");
1003
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1004

    
1005
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1006
			$input_errors[] = "Bandwidth must be an integer.";
1007
		if ($data['bandwidth'] < 0)
1008
			$input_errors[] = "Bandwidth cannot be negative.";
1009
		if ($data['priority'] && (!is_numeric($data['priority'])
1010
		    || ($data['priority'] < 1) || ($data['priority'] > 15))) {
1011
			$input_errors[] = gettext("The priority must be an integer between 1 and 15.");
1012
		}
1013
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
1014
				$input_errors[] = gettext("Queue limit must be an integer");
1015
		if ($data['qlimit'] < 0)
1016
				$input_errors[] = gettext("Queue limit must be positive");
1017
		if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['newname']))
1018
			 $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
1019
		if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
1020
			 $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
1021
		$default = $this->GetDefault();
1022
		if (!empty($data['default']) && altq_get_default_queue($data['interface']) && empty($default))
1023
			$input_errors[] = gettext("Only one default queue per interface is allowed.");
1024
	}
1025

    
1026
	function ReadConfig(&$q) {
1027
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
1028
			$this->SetQname($q['newname']);
1029
		} else if (!empty($q['newname'])) {
1030
			$this->SetQname($q['newname']);
1031
		} else if (isset($q['name']))
1032
			$this->SetQname($q['name']);
1033
		if (isset($q['interface']))
1034
			$this->SetInterface($q['interface']);
1035
		$this->SetBandwidth($q['bandwidth']);
1036
		if ($q['bandwidthtype'] <> "")
1037
			$this->SetBwscale($q['bandwidthtype']);
1038
		if (!empty($q['qlimit']))
1039
			$this->SetQlimit($q['qlimit']);
1040
		else
1041
			$this->SetQlimit(""); // Default
1042
		if (!empty($q['priority']))
1043
			$this->SetQPriority($q['priority']);
1044
		else
1045
			$this->SetQpriority("");
1046
		if (!empty($q['description']))
1047
			$this->SetDescription($q['description']);
1048
		else
1049
			$this->SetDescription("");
1050
		if (!empty($q['red']))
1051
			$this->SetRed($q['red']);
1052
		else
1053
			$this->SetRed();
1054
		if (!empty($q['codel']))
1055
			$this->SetCodel($q['codel']);
1056
		else
1057
			$this->SetCodel();
1058
		if (!empty($q['rio']))
1059
			$this->SetRio($q['rio']);
1060
		else
1061
			$this->SetRio();
1062
		if (!empty($q['ecn']))
1063
			$this->SetEcn($q['ecn']);
1064
		else
1065
			$this->SetEcn();
1066
		if (!empty($q['default']))
1067
			$this->SetDefault($q['default']);
1068
		else
1069
			$this->SetDefault();
1070
		if (!empty($q['enabled']))
1071
			$this->SetEnabled($q['enabled']);
1072
		else
1073
			$this->SetEnabled("");
1074

    
1075
	}
1076

    
1077
	function build_tree() {
1078
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&amp;queue=". $this->GetQname()."&amp;action=show"; 
1079
		$tree .= "\" ";
1080
		$tmpvalue = $this->GetDefault();
1081
		if (!empty($tmpvalue))
1082
			$tree .= " class=\"navlnk\"";
1083
		$tree .= " >" . $this->GetQname() . "</a>";
1084
		/* 
1085
		 * Not needed here!
1086
		 * if (is_array($queues) {
1087
		 *	  $tree .= "<ul>";
1088
		 *	  foreach ($q as $queues) 
1089
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1090
		 *	  endforeach	
1091
		 *	  $tree .= "</ul>";
1092
		 * }
1093
		 */
1094

    
1095
		$tree .= "</li>"; 
1096

    
1097
		return $tree;
1098
	}
1099

    
1100
	/* Should return something like:
1101
	 * queue $qname on $qinterface bandwidth ....
1102
	 */
1103
	function build_rules(&$default = false) {
1104
		$pfq_rule = " queue ". $this->qname;
1105
		if ($this->GetInterface())
1106
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1107
		$tmpvalue = $this->GetQpriority();
1108
		if (!empty($tmpvalue))
1109
			$pfq_rule .= " priority ".$this->GetQpriority();
1110
		$tmpvalue = $this->GetQlimit();
1111
		if (!empty($tmpvalue))
1112
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1113
		if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault() || $this->GetCodel()) {
1114
			$pfq_rule .= " priq ( ";
1115
			$tmpvalue = $this->GetRed();
1116
			if (!empty($tmpvalue)) {
1117
				$comma = 1;
1118
				$pfq_rule .= " red ";
1119
			}
1120
			$tmpvalue = $this->GetRio();
1121
			if (!empty($tmpvalue)) {
1122
				if ($comma) 
1123
					$pfq_rule .= " ,";
1124
				$comma = 1;
1125
				$pfq_rule .= " rio ";
1126
			}
1127
			$tmpvalue = $this->GetEcn();
1128
			if (!empty($tmpvalue)) {
1129
				if ($comma) 
1130
					$pfq_rule .= " ,";
1131
				$comma = 1;
1132
				$pfq_rule .= " ecn ";
1133
			}
1134
			$tmpvalue = $this->GetCodel();
1135
			if (!empty($tmpvalue)) {
1136
				if ($comma) 
1137
					$pfq_rule .= " ,";
1138
				$comma = 1;
1139
				$pfq_rule .= " codel ";
1140
			}
1141
			$tmpvalue = $this->GetDefault();
1142
			if (!empty($tmpvalue)) {
1143
				if ($comma)
1144
					$pfq_rule .= " ,";
1145
				$pfq_rule .= " default ";
1146
				$default = true;
1147
			}
1148
			$pfq_rule .= " ) ";
1149
		}
1150

    
1151
		$pfq_rule .= " \n";
1152

    
1153
		return $pfq_rule;
1154
	}
1155

    
1156
	/*
1157
	 * To return the html form to show to user
1158
	 * for getting the parameters.
1159
	 * Should do even for first time when the
1160
	 * object is created and later when we may
1161
	 * need to update it.
1162
	 */
1163
	function build_form() {
1164
		$form = "<tr><td valign=\"middle\" class=\"vncellreq\"><br/>";
1165
                $form .= gettext("Enable/Disable");
1166
                $form .= "<br/></td><td class=\"vncellreq\">";
1167
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
1168
                if ($this->GetEnabled() == "on")
1169
                        $form .=  " checked=\"checked\"";
1170
                $form .= " /><span class=\"vexpl\"> " . gettext("Enable/Disable queue and its children") . "</span>";
1171
                $form .= "</td></tr>";
1172
		$form .= "<tr>";
1173
		$form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">";
1174
		$form .= gettext("Queue Name") . "</td><td width=\"78%\" class=\"vtable\">";
1175
		$form .= "<input name=\"newname\" type=\"text\" id=\"newname\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1176
		$form .= htmlspecialchars($this->GetQname());
1177
		$form .= "\" />";
1178
		$form .= "<input name=\"name\" type=\"hidden\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1179
		$form .= htmlspecialchars($this->GetQname());
1180
		$form .= "\" />";
1181
		$form .= "<br /> <span class=\"vexpl\">" . gettext("Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.");
1182
		$form .= "</span><br /></td>";
1183
		$form .= "</tr><tr>";
1184
		$form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">" . gettext("Priority") . "</td>";
1185
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
1186
		$form .= htmlspecialchars($this->GetQpriority());
1187
		$form .= "\" />";
1188
		$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>";
1189
		$form .= "</tr>";
1190
		$form .= "<tr>";
1191
		$form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">" . gettext("Queue limit") . "</td>";
1192
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"8\" value=\"";
1193
		$form .= htmlspecialchars($this->GetQlimit());
1194
		$form .= "\" />";
1195
		$form .= "<br/> <span class=\"vexpl\">" . gettext("Queue limit in packets."); 
1196
		$form .= "</span></td></tr>";
1197
		$form .= "<tr>";
1198
		$form .= "<td width=\"22%\" valign=\"middle\" class=\"vncell\">" . gettext("Scheduler options") . "</td>";
1199
		$form .= "<td width=\"78%\" class=\"vtable\">";
1200
		if (empty($this->subqueues)) {
1201
			if ($this->GetDefault()) { 
1202
				$form .= "<input type=\"checkbox\" id=\"default\" checked=\"checked\" name=\"default\" value=\"default\"";
1203
				$form .= " /> " . gettext("Default queue") . "<br/>";
1204
			} else {
1205
				$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\" value=\"default\"";
1206
				$form .= " /> " . gettext("Default queue") . "<br/>";
1207
			}
1208
		}
1209
		$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\" value=\"red\" ";
1210
		$tmpvalue = $this->GetRed();
1211
		if(!empty($tmpvalue)) 
1212
			$form .=  " checked=\"checked\"";
1213
		$form .= " /> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">" . gettext("Random Early Detection") . "</a><br/>";
1214
		$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\" value=\"rio\"";
1215
		$tmpvalue = $this->GetRio();
1216
		if(!empty($tmpvalue)) 
1217
			$form .=  " checked=\"checked\"";
1218
		$form .= " /> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">" . gettext("Random Early Detection In and Out") . "</a><br/>";
1219
		$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\" value=\"ecn\"";
1220
		$tmpvalue = $this->GetEcn();
1221
		if(!empty($tmpvalue)) 
1222
			$form .=  " checked=\"checked\"";
1223
		$form .= " /> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">" . gettext("Explicit Congestion Notification") . "</a><br/>";
1224
		$form .= "<input type=\"checkbox\" id=\"codel\" name=\"codel\" value=\"codel\"";
1225
		$tmpvalue = $this->GetCodel();
1226
		if(!empty($tmpvalue)) 
1227
			$form .=  " checked=\"checked\"";
1228
		$form .= " /> <a target=\"_new\" href=\"http://www.bufferbloat.net/projects/codel/wiki\">" . gettext("Codel Active Queue") . "</a><br/>";
1229
		$form .= "<span class=\"vexpl\"><br/>" . gettext("Select options for this queue");
1230
		$form .= "</span></td></tr><tr>";
1231
		$form .= "<td width=\"22%\" class=\"vncellreq\">" . gettext("Description") . "</td>";
1232
		$form .= "<td width=\"78%\" class=\"vtable\">";
1233
		$form .= "<input type=\"text\" name=\"description\" size=\"40\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\" />";
1234
		$form .= "</td></tr>";
1235
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1236
		$form .= " value=\"".$this->GetInterface()."\" />";
1237

    
1238
		return $form;
1239
	}
1240

    
1241
	function build_shortform() {
1242
		/* XXX: Hacks in site. Mostly layer violations!  */
1243
		global $g, $altq_list_queues;
1244
		global $shaperIFlist;
1245

    
1246
		$altq =& $altq_list_queues[$this->GetInterface()];
1247
		if ($altq)
1248
			$scheduler = ": " . $altq->GetScheduler();
1249
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
1250
		$form .= "<a href=\"firewall_shaper.php?interface=" . $this->GetInterface() . "&amp;queue=" . $this->GetQname()."&amp;action=show\">". $shaperIFlist[$this->GetInterface()] .$scheduler."</a>";
1251
		$form .= "</td></tr>";
1252
		/* 
1253
		 * XXX: Hack in sight maybe fix with a class that wraps all
1254
		 * of this layer violations
1255
		 */
1256
		$form .= "<tr>";
1257
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1258
		$form .= gettext("Bandwidth:") . " " . $this->GetBandwidth().$this->GetBwscale();
1259
		$form .= "</td><td width=\"50%\"></td></tr>";
1260
		$tmpvalue = $this->GetQpriority();
1261
		if (!empty($tmpvalue))
1262
			$form .= "<tr><td width=\"20%\" class=\"vncellreq\">" .gettext("Priority: on") . " </td></tr>";
1263
		$tmpvalue = $this->GetDefault();
1264
		if (!empty($tmpvalue))
1265
			$form .= "<tr><td class=\"vncellreq\">" . gettext("Default: on") . " </td></tr>";
1266
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1267
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1268
		$form .= $this->GetInterface() . "&amp;queue=";
1269
		$form .= $this->GetQname() . "&amp;action=delete\">";
1270
		$form .= "<img src=\"";
1271
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1272
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("Delete queue from interface") . "\" alt=\"delete\" />";
1273
		$form .= "<span>" . gettext("Delete queue from interface") . "</span></a></td></tr>";
1274

    
1275
		return $form;
1276

    
1277
	}
1278

    
1279
		function update_altq_queue_data(&$q) { 
1280
		$this->ReadConfig($q);
1281
	}
1282

    
1283
	function wconfig() {
1284
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1285
		if (!is_array($cflink))
1286
			$cflink = array();
1287
		$cflink['name'] = $this->GetQname();
1288
		$cflink['interface'] = $this->GetInterface();
1289
		$cflink['qlimit'] = trim($this->GetQlimit());
1290
		if (empty($cflink['qlimit']))
1291
			unset($cflink['qlimit']);
1292
		$cflink['priority'] = trim($this->GetQpriority());
1293
		if (empty($cflink['priority']))
1294
			unset($cflink['priority']);
1295
		$cflink['description'] = trim($this->GetDescription());
1296
		if (empty($cflink['description']))
1297
			unset($cflink['description']);
1298
		$cflink['enabled'] = trim($this->GetEnabled());
1299
		if (empty($cflink['enabled']))
1300
			unset($cflink['enabled']);
1301
		$cflink['default'] = trim($this->GetDefault());
1302
		if (empty($cflink['default']))
1303
			unset($cflink['default']);
1304
		$cflink['red'] = trim($this->GetRed());
1305
		if (empty($cflink['red']))
1306
			unset($cflink['red']);
1307
		$cflink['codel'] = trim($this->GetCodel());
1308
		if (empty($cflink['codel']))
1309
			unset($cflink['codel']);
1310
		$cflink['rio'] = trim($this->GetRio());
1311
		if (empty($cflink['rio']))
1312
			unset($cflink['rio']);
1313
		$cflink['ecn'] = trim($this->GetEcn());
1314
		if (empty($cflink['ecn']))
1315
			unset($cflink['ecn']);
1316
	}
1317
}
1318

    
1319
class hfsc_queue extends priq_queue {
1320
	/* realtime */
1321
	var $realtime;
1322
	var $r_m1;
1323
	var $r_d;
1324
	var $r_m2;
1325
	/* linkshare */
1326
	var $linkshare;
1327
	var $l_m1;
1328
	var $l_d;
1329
	var $l_m2;
1330
	/* upperlimit */
1331
	var $upperlimit;
1332
	var $u_m1;
1333
	var $u_d;
1334
	var $u_m2;
1335

    
1336
	/*
1337
	 * HFSC can have nested queues.
1338
	 */
1339
	function CanHaveChildren() {
1340
		return true;
1341
	}
1342
	function GetRealtime() {
1343
           return $this->realtime;
1344
	}
1345
	function GetR_m1() {
1346
		return $this->r_m1;
1347
	}
1348
	function GetR_d() {
1349
		return $this->r_d;
1350
	}
1351
	function GetR_m2() {
1352
		return $this->r_m2;
1353
	}
1354
	function SetRealtime() {
1355
		$this->realtime = "on";
1356
	}
1357
	function DisableRealtime() {
1358
		$this->realtime = "";
1359
	}
1360
	function SetR_m1($value) {
1361
		$this->r_m1 = $value;
1362
	}
1363
	function SetR_d($value) {
1364
		$this->r_d = $value;
1365
	}
1366
	function SetR_m2($value) {
1367
		$this->r_m2 = $value;
1368
	}
1369
	function GetLinkshare() {
1370
		return $this->linkshare;
1371
	}
1372
	function DisableLinkshare() {
1373
		$this->linkshare = "";
1374
	}
1375
	function GetL_m1() {
1376
		return $this->l_m1;
1377
	}
1378
	function GetL_d() {
1379
		return $this->l_d;
1380
	}
1381
	function GetL_m2() {
1382
		return $this->l_m2;
1383
	}
1384
	function SetLinkshare() {
1385
		$this->linkshare = "on";
1386
	}
1387
	function SetL_m1($value) {
1388
		$this->l_m1 = $value;
1389
	}
1390
	function SetL_d($value) {
1391
		$this->l_d = $value;
1392
	}
1393
	function SetL_m2($value) {
1394
		$this->l_m2 = $value;
1395
	}
1396
	function GetUpperlimit() {
1397
		return $this->upperlimit;
1398
	}
1399
	function GetU_m1() {
1400
		return $this->u_m1;
1401
	}
1402
	function GetU_d() {
1403
		return $this->u_d;
1404
	}
1405
	function GetU_m2() {
1406
		return $this->u_m2;
1407
	}
1408
	function SetUpperlimit() {
1409
		$this->upperlimit = "on";
1410
	}
1411
	function DisableUpperlimit() {
1412
		$this->upperlimit = "";
1413
	}
1414
	function SetU_m1($value) {
1415
		$this->u_m1 = $value;
1416
	}
1417
	function SetU_d($value) {
1418
		$this->u_d = $value;
1419
	}
1420
	function SetU_m2($value) {
1421
		$this->u_m2 = $value;
1422
	}
1423

    
1424
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1425

    
1426
		if (!is_array($this->subqueues))
1427
			$this->subqueues = array();
1428
		$q =& new hfsc_queue();
1429
		$q->SetInterface($this->GetInterface());
1430
		$q->SetParent($this);
1431
		$q->ReadConfig($qname);
1432
		$q->validate_input($qname, $input_errors);
1433
		if (count($input_errors)) {
1434
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
1435
			return $q;
1436
		}
1437

    
1438
		$q->SetEnabled("on");
1439
		$q->SetLink($path);
1440
		switch ($q->GetBwscale()) {
1441
		case "%":
1442
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1443
			break;
1444
		default:
1445
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1446
			break;
1447
		}
1448
		$q->SetAvailableBandwidth($myBw);
1449
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1450

    
1451
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1452
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1453
		if (is_array($qname['queue'])) {
1454
			foreach ($qname['queue'] as $key1 => $que) {
1455
				array_push($path, $key1);
1456
				$q->add_queue($q->GetInterface(), $que, $path, $input_errors);
1457
				array_pop($path);
1458
			}
1459
		}
1460

    
1461
		return $q;
1462
	}
1463

    
1464
        function copy_queue($interface, &$cflink) {
1465

    
1466
		$cflink['name'] = $this->GetQname();
1467
		$cflink['interface'] = $interface;
1468
		$cflink['qlimit'] = trim($this->GetQlimit());
1469
		if (empty($cflink['qlimit']))
1470
			unset($cflink['qlimit']);
1471
		$cflink['priority'] = trim($this->GetQpriority());
1472
		if (empty($cflink['priority']))
1473
			unset($cflink['priority']);
1474
		$cflink['description'] = trim($this->GetDescription());
1475
		if (empty($cflink['description']))
1476
			unset($cflink['description']);
1477
		$cflink['bandwidth'] = $this->GetBandwidth();
1478
		$cflink['bandwidthtype'] = $this->GetBwscale();
1479
		$cflink['enabled'] = trim($this->GetEnabled());
1480
		if (empty($cflink['enabled']))
1481
			unset($cflink['enabled']);
1482
		$cflink['default'] = trim($this->GetDefault());
1483
		if (empty($cflink['default']))
1484
			unset($cflink['default']);
1485
		$cflink['red'] = trim($this->GetRed());
1486
		if (empty($cflink['red']))
1487
			unset($cflink['red']);
1488
		$cflink['rio'] = trim($this->GetRio());
1489
		if (empty($cflink['rio']))
1490
			unset($cflink['rio']);
1491
		$cflink['ecn'] = trim($this->GetEcn());
1492
		if (empty($cflink['ecn']))
1493
			unset($cflink['ecn']);
1494
		if ($this->GetLinkshare() <> "") {
1495
			if ($this->GetL_m1() <> "") {
1496
				$cflink['linkshare1'] = $this->GetL_m1();
1497
				$cflink['linkshare2'] = $this->GetL_d();
1498
				$cflink['linkshare'] = "on";
1499
			} else {
1500
				unset($cflink['linkshare1']);
1501
				unset($cflink['linkshare2']);
1502
				unset($cflink['linkshare']);
1503
			}
1504
			if ($this->GetL_m2() <> "") {
1505
				$cflink['linkshare3'] = $this->GetL_m2();
1506
				$cflink['linkshare'] = "on";
1507
			} else {
1508
				unset($cflink['linkshare3']);
1509
				unset($cflink['linkshare']);
1510
			}
1511
		}
1512
		if ($this->GetRealtime() <> "") {
1513
			if ($this->GetR_m1() <> "") {
1514
				$cflink['realtime1'] = $this->GetR_m1();
1515
				$cflink['realtime2'] = $this->GetR_d();
1516
				$cflink['realtime'] = "on";
1517
			} else {
1518
				unset($cflink['realtime1']);
1519
                                unset($cflink['realtime2']);
1520
                                unset($cflink['realtime']);
1521
			}
1522
			if ($this->GetR_m2() <> "") {
1523
				$cflink['realtime3'] = $this->GetR_m2();
1524
				$cflink['realtime'] = "on";
1525
			} else {
1526
				unset($cflink['realtime3']);
1527
				unset($cflink['realtime']);
1528
			}
1529
		}
1530
		if ($this->GetUpperlimit() <> "") {
1531
			if ($this->GetU_m1() <> "") {
1532
				$cflink['upperlimit1'] = $this->GetU_m1();
1533
				$cflink['upperlimit2'] = $this->GetU_d();
1534
				$cflink['upperlimit'] = "on";
1535
			} else {
1536
				unset($cflink['upperlimit']);
1537
				unset($cflink['upperlimit1']);
1538
				unset($cflink['upperlimit2']);
1539
			}
1540
			if ($this->GetU_m2() <> "") {
1541
				$cflink['upperlimit3'] = $this->GetU_m2();
1542
				$cflink['upperlimit'] = "on";
1543
			} else {
1544
				unset($cflink['upperlimit3']);
1545
				unset($cflink['upperlimit']);
1546
			}
1547
		}
1548

    
1549
		if (is_array($this->subqueues)) {
1550
			$cflinkp['queue'] = array();
1551
			foreach ($this->subqueues as $q) {
1552
				$cflink['queue'][$q->GetQname()] = array();
1553
				$q->copy_queue($interface, $cflink['queue'][$q->GetQname()]);
1554
			}
1555
		}
1556
	}
1557

    
1558
	function delete_queue() { 
1559
		unref_on_altq_queue_list($this->GetQname());
1560
		cleanup_queue_from_rules($this->GetQname());
1561
		$parent =& $this->GetParent();
1562
		foreach ($this->subqueues as $q)  {
1563
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1564
			$q->delete_queue();
1565
		}
1566
		unset_object_by_reference($this->GetLink());
1567
	}
1568

    
1569
	/*
1570
	 * Should search even its children
1571
	 */
1572
	function &find_queue($interface, $qname) {
1573
		if ($qname == $this->GetQname()) 
1574
			return $this;
1575

    
1576
		foreach ($this->subqueues as $q) {
1577
			$result =& $q->find_queue("", $qname);
1578
			if ($result)
1579
				return $result;
1580
		}
1581
	}
1582

    
1583
	function &find_parentqueue($interface, $qname) {
1584
		if ($this->subqueues[$qname]) 
1585
			return $this;
1586
		foreach ($this->subqueues as $q) {
1587
			$result = $q->find_parentqueue("", $qname);
1588
			if ($result)
1589
				return $result;
1590
		}
1591
	}
1592

    
1593
	function validate_input($data, &$input_errors) {
1594
		parent::validate_input($data, $input_errors);
1595

    
1596
		$reqdfields[] = "bandwidth";
1597
		$reqdfieldsn[] = gettext("Bandwidth");
1598
		$reqdfields[] = "bandwidthtype";
1599
		$reqdfieldsn[] = gettext("Bandwidthtype");
1600

    
1601
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1602

    
1603
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1604
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1605
				$input_errors[] = gettext("Bandwidth must be an integer.");
1606

    
1607
			if ($data['bandwidth'] < 0)
1608
				$input_errors[] = gettext("Bandwidth cannot be negative.");
1609

    
1610
			if ($data['bandwidthtype'] == "%") {
1611
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1612
					$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
1613
			}
1614
		/*
1615
			$parent =& $this->GetParent();
1616
			switch ($data['bandwidthtype']) {
1617
			case "%":
1618
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1619
			default:
1620
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1621
				break;
1622
			}
1623
			if ($parent->GetAvailableBandwidth() < $myBw)
1624
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1625
		*/
1626
		}
1627

    
1628
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1629
			$input_errors[] = gettext("upperlimit service curve defined but missing (d) value");
1630
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1631
			$input_errors[] = gettext("upperlimit service curve defined but missing initial bandwidth (m1) value");
1632
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1633
			$input_errors[] = gettext("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1634
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1635
			$input_errors[] = gettext("upperlimit d value needs to be numeric");
1636
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1637
			$input_errors[] = gettext("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1638

    
1639
		/*
1640
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1641
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1642
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1643
			if (floatval($bw_1) < floatval($bw_2)) 
1644
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1645

    
1646
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1647
				$input_errors[] = ("upperlimit specification exceeds 80% of allowable allocation.");
1648
		}
1649
		*/
1650
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1651
			$input_errors[] = gettext("linkshare service curve defined but missing (d) value");
1652
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1653
			$input_errors[] = gettext("linkshare service curve defined but missing initial bandwidth (m1) value");
1654
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1655
			$input_errors[] = gettext("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1656
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1657
			$input_errors[] = gettext("linkshare d value needs to be numeric");
1658
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1659
			$input_errors[] = gettext("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1660
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1661
			$input_errors[] = gettext("realtime service curve defined but missing (d) value");
1662
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1663
			$input_errors[] = gettext("realtime service curve defined but missing initial bandwidth (m1) value");
1664

    
1665
		/*
1666
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1667
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1668
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1669
                	if (floatval($bw_1) < floatval($bw_2))
1670
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1671

    
1672
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1673
                        	$input_errors[] = ("linkshare specification exceeds 80% of allowable allocation.");
1674
		}
1675
		*/
1676

    
1677
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1678
			$input_errors[] = gettext("realtime m1 value needs to be Kb, Mb, Gb, or %");
1679
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1680
			$input_errors[] = gettext("realtime d value needs to be numeric");
1681
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1682
			$input_errors[] = gettext("realtime m2 value needs to be Kb, Mb, Gb, or %");
1683

    
1684
		/*
1685
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1686
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1687
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1688
                	if (floatval($bw_1) < floatval($bw_2))
1689
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1690

    
1691
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1692
				$input_errors[] = ("realtime specification exceeds 80% of allowable allocation.");
1693
		}
1694
		*/
1695
	}
1696

    
1697
	function ReadConfig(&$cflink) {
1698
		if (!empty($cflink['linkshare'])) {
1699
			if (!empty($cflink['linkshare1'])) {
1700
				$this->SetL_m1($cflink['linkshare1']);
1701
                                $this->SetL_d($cflink['linkshare2']);
1702
				$this->SetLinkshare();
1703
			} else {
1704
				$this->SetL_m1("");
1705
                                $this->SetL_d("");
1706
				$this->DisableLinkshare();
1707
			}
1708
			if (!empty($cflink['linkshare3'])) {
1709
                                $this->SetL_m2($cflink['linkshare3']);
1710
				$this->SetLinkshare();
1711
			}
1712
		} else
1713
			$this->DisableLinkshare();
1714
		if (!empty($cflink['realtime'])) {
1715
                        if (!empty($cflink['realtime1'])) {
1716
                                $this->SetR_m1($cflink['realtime1']);
1717
                                $this->SetR_d($cflink['realtime2']);
1718
				$this->SetRealtime();
1719
			} else {
1720
                                $this->SetR_m1("");
1721
                                $this->SetR_d("");
1722
				$this->DisableRealtime();
1723
			}
1724
                        if (!empty($cflink['realtime3'])) {
1725
                                $this->SetR_m2($cflink['realtime3']);
1726
				$this->SetRealtime();
1727
			}
1728
		} else
1729
			$this->DisableRealtime(); 
1730
		if (!empty($cflink['upperlimit'])) {
1731
                        if (!empty($cflink['upperlimit1'])) {
1732
                                $this->SetU_m1($cflink['upperlimit1']);
1733
                                $this->SetU_d($cflink['upperlimit2']);
1734
				$this->SetUpperlimit();
1735
			} else {
1736
                                $this->SetU_m1("");
1737
                                $this->SetU_d("");
1738
				$this->DisableUpperlimit();
1739
			}
1740
                        if (!empty($cflink['upperlimit3'])) {
1741
                                $this->SetU_m2($cflink['upperlimit3']);
1742
				$this->SetUpperlimit();
1743
			}
1744
		} else
1745
			$this->DisableUpperlimit();
1746
		parent::ReadConfig($cflink);
1747
	}
1748

    
1749
	function build_tree() {
1750
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&amp;queue=" . $this->GetQname()."&amp;action=show"; 
1751
		$tree .= "\" ";
1752
		$tmpvalue = $this->GetDefault();
1753
		if (!empty($tmpvalue))
1754
			$tree .= " class=\"navlnk\"";
1755
		$tree .= " >" . $this->GetQname() . "</a>";
1756
		if (is_array($this->subqueues)) {
1757
			$tree .= "<ul>";
1758
			foreach ($this->subqueues as $q)  {
1759
				$tree .= $q->build_tree();
1760
			}	
1761
			$tree .= "</ul>";
1762
		}
1763
		$tree .= "</li>";
1764
		return $tree;
1765
	}
1766

    
1767
	/* Even this should take children into consideration */
1768
	function build_rules(&$default = false) {
1769

    
1770
		$pfq_rule = " queue ". $this->qname;
1771
		if ($this->GetInterface())
1772
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1773
		if ($this->GetBandwidth() && $this->GetBwscale())
1774
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1775

    
1776
		$tmpvalue = $this->GetQlimit();
1777
		if (!empty($tmpvalue))
1778
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1779
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetCodel() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1780
			$pfq_rule .= " hfsc ( ";
1781
			$tmpvalue = $this->GetRed();
1782
			if (!empty($tmpvalue)) {
1783
				$comma = 1;
1784
				$pfq_rule .= " red ";
1785
			}
1786

    
1787
			$tmpvalue = $this->GetRio();
1788
			if (!empty($tmpvalue)) {
1789
				if ($comma) 
1790
					$pfq_rule .= " ,";
1791
				$comma = 1;
1792
				$pfq_rule .= " rio ";
1793
			}
1794
			$tmpvalue = $this->GetEcn();
1795
			if (!empty($tmpvalue)) {
1796
				if ($comma) 
1797
					$pfq_rule .= " ,";
1798
				$comma = 1;
1799
				$pfq_rule .= " ecn ";
1800
			}
1801
			$tmpvalue = $this->GetCodel();
1802
			if (!empty($tmpvalue)) {
1803
				if ($comma) 
1804
					$pfq_rule .= " ,";
1805
				$comma = 1;
1806
				$pfq_rule .= " codel ";
1807
			}
1808
			$tmpvalue = $this->GetDefault();
1809
			if (!empty($tmpvalue)) {
1810
				if ($comma)
1811
					$pfq_rule .= " ,";
1812
				$comma = 1;
1813
				$pfq_rule .= " default ";
1814
				$default = true;
1815
			}
1816

    
1817
			if ($this->GetRealtime() <> "")  {
1818
				if ($comma) 
1819
					$pfq_rule .= " , ";
1820
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1821
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1822
				else  if ($this->GetR_m2() <> "")
1823
					$pfq_rule .= " realtime " . $this->GetR_m2();
1824
				$comma = 1;
1825
			}
1826
			if ($this->GetLinkshare() <> "") {
1827
				if ($comma)
1828
					$pfq_rule .= " ,";
1829
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1830
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1831
				else if ($this->GetL_m2() <> "")
1832
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1833
				$comma = 1;
1834
			}
1835
			if ($this->GetUpperlimit() <> "") {
1836
				if ($comma)
1837
					$pfq_rule .= " ,";
1838
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1839
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1840
				else if ($this->GetU_m2() <> "")
1841
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1842
			}
1843
			$pfq_rule .= " ) ";
1844
		}
1845
		if (count($this->subqueues)) {
1846
			$i = count($this->subqueues);
1847
			$pfq_rule .= " { ";
1848
			foreach ($this->subqueues as $qkey => $qnone) {
1849
				if ($i > 1) {
1850
					$i--;
1851
					$pfq_rule .= " {$qkey}, ";
1852
				} else
1853
					$pfq_rule .= " {$qkey} ";
1854
			}
1855
			$pfq_rule .= " } \n";
1856
			foreach ($this->subqueues as $q)
1857
				$pfq_rule .= $q->build_rules($default);
1858
		}
1859

    
1860
		 $pfq_rule .= " \n";
1861

    
1862
		return $pfq_rule;
1863
	}
1864

    
1865
	function build_javascript() {
1866
		$javascript = parent::build_javascript();
1867
		$javascript .= "<script type=\"text/javascript\">";
1868
		$javascript .= "//<![CDATA[\n";
1869
		$javascript .= "function enable_realtime(enable_over) { \n";
1870
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1871
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1872
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1873
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1874
		$javascript .= " } else { \n";
1875
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1876
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1877
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1878
		$javascript .= " } \n";
1879
		$javascript .= " } \n";
1880
		$javascript .= "function enable_linkshare(enable_over) { \n";
1881
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1882
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1883
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1884
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1885
		$javascript .= " } else { \n";
1886
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1887
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1888
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1889
		$javascript .= " } \n";
1890
		$javascript .= " } \n";
1891
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1892
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1893
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1894
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1895
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1896
		$javascript .= " } else { \n";
1897
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1898
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1899
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1900
		$javascript .= " } \n";
1901

    
1902
		$javascript .= "} \n";
1903
		$javascript .= "//]]>";
1904
		$javascript .= "</script>";
1905

    
1906
		return $javascript;
1907
	}
1908

    
1909
	function build_form() {
1910
		$form = parent::build_form();
1911
		$form .= "<tr>";
1912
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
1913
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1914
		$form .= htmlspecialchars($this->GetBandwidth());
1915
		$form .= "\" />";
1916
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1917
		$form .= "<option value=\"Gb\"";
1918
		if ($this->GetBwscale() == "Gb")
1919
			$form .= " selected=\"selected\"";
1920
		$form .= ">" . gettext("Gbit/s") . "</option>";
1921
		$form .= "<option value=\"Mb\"";
1922
		if ($this->GetBwscale() == "Mb")
1923
			$form .= " selected=\"selected\"";
1924
		$form .= ">" . gettext("Mbit/s") . "</option>";
1925
		$form .= "<option value=\"Kb\"";
1926
		if ($this->GetBwscale() == "Kb")
1927
			$form .= " selected=\"selected\"";
1928
		$form .= ">" . gettext("Kbit/s") . "</option>";
1929
		$form .= "<option value=\"b\"";
1930
		if ($this->GetBwscale() == "b")
1931
			$form .= " selected=\"selected\"";
1932
		$form .= ">" . gettext("Bit/s") . "</option>";
1933
		$form .= "<option value=\"%\"";
1934
		if ($this->GetBwscale() == "%")
1935
			$form .= " selected=\"selected\"";
1936
		$form .= ">%</option>";
1937
		$form .= "</select> <br/>";
1938
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
1939
		$form .= "</span></td></tr>";
1940
		$form .= "<tr>";
1941
		$form .= "<td width=\"22%\" valign=\"middle\" class=\"vncellreq\">" . gettext("Service Curve (sc)") . "</td>";
1942
		$form .= "<td width=\"78%\" class=\"vtable\">";
1943
		$form .= "<table>";
1944
		$form .= "<tr><td>&nbsp;</td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>";
1945
		$form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\"";
1946
		if($this->GetUpperlimit()<> "") 
1947
			$form .=  " checked=\"checked\" ";
1948
		$form .= "onchange=\"enable_upperlimit()\" /> " . gettext("Upperlimit:") . "</td><td><input size=\"6\" value=\"";
1949
		$form .= htmlspecialchars($this->GetU_m1());
1950
		$form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" ";
1951
		if ($this->GetUpperlimit() == "")
1952
			$form .= " disabled=\"disabled\"";
1953
		$form .= " /></td><td><input size=\"6\" value=\"";
1954
		$form .= htmlspecialchars($this->GetU_d());
1955
		$form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" ";
1956
		if ($this->GetUpperlimit() == "")
1957
			$form .= " disabled=\"disabled\"";
1958
		$form .= " /></td><td><input size=\"6\" value=\"";
1959
		$form .= htmlspecialchars($this->GetU_m2());
1960
		$form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" ";
1961
		if ($this->GetUpperlimit() == "")
1962
			$form .= " disabled=\"disabled\"";
1963
		$form .= " /></td><td>" . gettext("The maximum allowed bandwidth for the queue.") . "</td></tr>";
1964
		$form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\"";
1965
		if($this->GetRealtime() <> "") 
1966
			$form .=  " checked=\"checked\" ";
1967
		$form .= "onchange=\"enable_realtime()\" /> " . gettext("Real time:") . "</td><td><input size=\"6\" value=\"";
1968
		$form .= htmlspecialchars($this->GetR_m1());
1969
		$form .= "\" id=\"realtime1\" name=\"realtime1\" ";
1970
		if ($this->GetRealtime() == "")
1971
			$form .= " disabled=\"disabled\"";
1972
		$form .= " /></td><td><input size=\"6\" value=\"";
1973
		$form .= htmlspecialchars($this->GetR_d());
1974
		$form .= "\" id=\"realtime2\" name=\"realtime2\" ";
1975
		if ($this->GetRealtime() == "")
1976
			$form .= " disabled=\"disabled\"";
1977
		$form .= " /></td><td><input size=\"6\" value=\"";
1978
		$form .= htmlspecialchars($this->GetR_m2());
1979
		$form .= "\" id=\"realtime3\" name=\"realtime3\" ";
1980
		if ($this->GetRealtime() == "")
1981
			$form .= " disabled=\"disabled\"";
1982
		$form .= " /></td><td>" . gettext("The minimum required bandwidth for the queue.") . "</td></tr>";
1983
		$form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" name=\"linkshare\"";
1984
		if($this->GetLinkshare() <> "") 
1985
			$form .=  " checked=\"checked\" ";
1986
		$form .= "onchange=\"enable_linkshare()\" /> " . gettext("Link share:") . "</td><td><input size=\"6\" value=\"";
1987
		$form .= htmlspecialchars($this->GetL_m1());
1988
		$form .= "\" id=\"linkshare1\" name=\"linkshare1\" ";
1989
		if ($this->GetLinkshare() == "")
1990
			$form .= " disabled=\"disabled\"";
1991
		$form .= " /></td><td><input size=\"6\" value=\"";
1992
		$form .= htmlspecialchars($this->GetL_d());
1993
		$form .= "\" id=\"linkshare2\" name=\"linkshare2\" ";
1994
		if ($this->GetLinkshare() == "")
1995
			$form .= " disabled=\"disabled\"";
1996
		$form .= " /></td><td><input size=\"6\" value=\"";
1997
		$form .= htmlspecialchars($this->GetL_m2());
1998
		$form .= "\" id=\"linkshare3\" name=\"linkshare3\" ";
1999
		if ($this->GetLinkshare() == "")
2000
			$form .= " disabled=\"disabled\"";
2001
		$form .= " /></td><td>" . gettext("The bandwidth share of a backlogged queue - this overrides priority.") . "</td></tr>";
2002
		$form .= "</table><br/>";
2003
		$form .= gettext("The format for service curve specifications is (m1, d, m2).  m2 controls "
2004
		      .  "the bandwidth assigned to the queue.  m1 and d are optional and can be "
2005
		      .  "used to control the initial bandwidth assignment.  For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value "
2006
		      .  "given in m2.");
2007
		$form .= "</td>";
2008
		$form .= "</tr>";
2009

    
2010
		return $form;
2011
	}
2012

    
2013
	function update_altq_queue_data(&$data) { 
2014
		$this->ReadConfig($data);
2015
	}
2016

    
2017
	function wconfig() {
2018
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2019
		if (!is_array($cflink))
2020
			$cflink = array();
2021
		$cflink['name'] = $this->GetQname();
2022
		$cflink['interface'] = $this->GetInterface();
2023
		$cflink['qlimit'] = trim($this->GetQlimit());
2024
		if (empty($cflink['qlimit']))
2025
			unset($cflink['qlimit']);
2026
		$cflink['priority'] = $this->GetQpriority();
2027
		if (empty($cflink['priority']))
2028
			unset($cflink['priority']);
2029
		$cflink['description'] = $this->GetDescription();
2030
		if (empty($cflink['description']))
2031
			unset($cflink['description']);
2032
		$cflink['bandwidth'] = $this->GetBandwidth();
2033
		$cflink['bandwidthtype'] = $this->GetBwscale();
2034
		$cflink['enabled'] = $this->GetEnabled();
2035
		if (empty($cflink['enabled']))
2036
			unset($cflink['enabled']);
2037
		$cflink['default'] = $this->GetDefault();
2038
		if (empty($cflink['default']))
2039
			unset($cflink['default']);
2040
		$cflink['red'] = trim($this->GetRed());
2041
		if (empty($cflink['red']))
2042
			unset($cflink['red']);
2043
		$cflink['rio'] = $this->GetRio();
2044
		if (empty($cflink['rio']))
2045
			unset($cflink['rio']);
2046
		$cflink['ecn'] = trim($this->GetEcn());
2047
		if (empty($cflink['ecn']))
2048
			unset($cflink['ecn']);
2049
		$cflink['codel'] = trim($this->GetCodel());
2050
		if (empty($cflink['codel']))
2051
			unset($cflink['codel']);
2052
		if ($this->GetLinkshare() <> "") {
2053
			if ($this->GetL_m1() <> "") {
2054
				$cflink['linkshare1'] = $this->GetL_m1();
2055
				$cflink['linkshare2'] = $this->GetL_d();
2056
				$cflink['linkshare'] = "on";
2057
			} else {
2058
				unset($cflink['linkshare']);
2059
				unset($cflink['linkshare1']);
2060
				unset($cflink['linkshare2']);
2061
			}
2062
			if ($this->GetL_m2() <> "") {
2063
				$cflink['linkshare3'] = $this->GetL_m2();
2064
				$cflink['linkshare'] = "on";
2065
			} else {
2066
				unset($cflink['linkshare']);
2067
				unset($cflink['linkshare3']);
2068
			}
2069
		} else {
2070
			unset($cflink['linkshare']);
2071
			unset($cflink['linkshare1']);
2072
			unset($cflink['linkshare2']);
2073
			unset($cflink['linkshare3']);
2074
		}
2075
		if ($this->GetRealtime() <> "") {
2076
			if ($this->GetR_m1() <> "") {
2077
				$cflink['realtime1'] = $this->GetR_m1();
2078
				$cflink['realtime2'] = $this->GetR_d();
2079
				$cflink['realtime'] = "on";
2080
			} else {
2081
				unset($cflink['realtime']);
2082
				unset($cflink['realtime1']);
2083
				unset($cflink['realtime2']);
2084
			}
2085
			if ($this->GetR_m2() <> "") {
2086
				$cflink['realtime3'] = $this->GetR_m2();
2087
				$cflink['realtime'] = "on";
2088
			} else {
2089
				unset($cflink['realtime']);
2090
				unset($cflink['realtime3']);
2091
			}
2092
		} else {
2093
			unset($cflink['realtime']);
2094
			unset($cflink['realtime1']);
2095
			unset($cflink['realtime2']);
2096
			unset($cflink['realtime3']);
2097
		}
2098
		if ($this->GetUpperlimit() <> "") {
2099
			if ($this->GetU_m1() <> "") {
2100
				$cflink['upperlimit1'] = $this->GetU_m1();
2101
				$cflink['upperlimit2'] = $this->GetU_d();
2102
				$cflink['upperlimit'] = "on";
2103
			} else {
2104
				unset($cflink['upperlimit']);
2105
				unset($cflink['upperlimit1']);
2106
				unset($cflink['upperlimit2']);
2107
			}
2108
			if ($this->GetU_m2() <> "") {
2109
				$cflink['upperlimit3'] = $this->GetU_m2();
2110
				$cflink['upperlimit'] = "on";
2111
			} else {
2112
				unset($cflink['upperlimit']);
2113
				unset($cflink['upperlimit3']);
2114
			}
2115
		} else {
2116
			unset($cflink['upperlimit']);
2117
			unset($cflink['upperlimit1']);
2118
			unset($cflink['upperlimit2']);
2119
			unset($cflink['upperlimit3']);
2120
		}
2121
	}
2122
}
2123

    
2124
class cbq_queue extends priq_queue {
2125
	var $qborrow = "";
2126

    
2127
	function GetBorrow() {
2128
		return $this->qborrow;
2129
	}
2130
	function SetBorrow($borrow) {
2131
		$this->qborrow = $borrow;
2132
	}
2133
	function CanHaveChildren() {
2134
		return true;
2135
	}
2136

    
2137
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2138

    
2139
		if (!is_array($this->subqueues))
2140
			$this->subqueues = array();
2141
		$q =& new cbq_queue();
2142
		$q->SetInterface($this->GetInterface());
2143
		$q->SetParent($this);
2144
		$q->ReadConfig($qname);
2145
                $q->validate_input($qname, $input_errors);
2146
                if (count($input_errors)) {
2147
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
2148
                        return $q;
2149
                }
2150
                switch ($q->GetBwscale()) {
2151
                case "%":
2152
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2153
                        break;
2154
                default:
2155
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2156
                        break;
2157
                }
2158
                $q->SetAvailableBandwidth($myBw);
2159
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2160

    
2161
		$q->SetEnabled("on");
2162
		$q->SetLink($path);
2163
		$this->subqueues[$q->GetQName()] = &$q;
2164
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2165
		if (is_array($qname['queue'])) {
2166
			foreach ($qname['queue'] as $key1 => $que) {
2167
				array_push($path, $key1);
2168
				$q->add_queue($q->GetInterface(), $que, $path, $input_errors);
2169
				array_pop($path);
2170
			}
2171
		}
2172

    
2173
		return $q;
2174
	}
2175

    
2176
	function copy_queue($interface, &$cflink) {
2177

    
2178
		$cflink['interface'] = $interface;
2179
		$cflink['qlimit'] = trim($this->GetQlimit());
2180
		if (empty($clink['qlimit']))
2181
			unset($cflink['qlimit']);
2182
		$cflink['priority'] = trim($this->GetQpriority());
2183
		if (empty($cflink['priority']))
2184
			unset($cflink['priority']);
2185
		$cflink['name'] = $this->GetQname();
2186
		$cflink['description'] = trim($this->GetDescription());
2187
		if (empty($cflink['description']))
2188
			unset($cflink['description']);
2189
		$cflink['bandwidth'] = $this->GetBandwidth();
2190
		$cflink['bandwidthtype'] = $this->GetBwscale();
2191
		$cflink['enabled'] = trim($this->GetEnabled());
2192
		if (empty($cflink['enabled']))
2193
			unset($cflink['enabled']);
2194
		$cflink['default'] = trim($this->GetDefault());
2195
		if (empty($cflink['default']))
2196
			unset($cflink['default']);
2197
		$cflink['red'] = trim($this->GetRed());
2198
		if (empty($cflink['red']))
2199
			unset($cflink['red']);
2200
		$cflink['rio'] = trim($this->GetRio());
2201
		if (empty($cflink['rio']))
2202
			unset($cflink['rio']);
2203
		$cflink['ecn'] = trim($this->GetEcn());
2204
		if (empty($cflink['ecn']))
2205
			unset($cflink['ecn']);
2206
		$cflink['borrow'] = trim($this->GetBorrow());
2207
		if (empty($cflink['borrow']))
2208
			unset($cflink['borrow']);
2209
		if (is_array($this->queues)) {
2210
			$cflinkp['queue'] = array();
2211
			foreach ($this->subqueues as $q) {
2212
				$cflink['queue'][$q->GetQname()] = array();
2213
				$q->copy_queue($interface, $cflink['queue'][$q->GetQname()]);
2214
			}
2215
		}
2216
	}
2217

    
2218
	/*
2219
	 * Should search even its children
2220
	 */
2221
	function &find_queue($interface, $qname) {
2222
		if ($qname == $this->GetQname())
2223
			return $this;
2224
		foreach ($this->subqueues as $q) {
2225
			$result =& $q->find_queue("", $qname);
2226
			if ($result)
2227
				return $result;
2228
		}
2229
	}
2230

    
2231
	function &find_parentqueue($interface, $qname) {
2232
		if ($this->subqueues[$qname])
2233
			return $this;
2234
		foreach ($this->subqueues as $q) {
2235
			$result = $q->find_parentqueue("", $qname);
2236
			if ($result)
2237
				return $result;
2238
		}
2239
	}
2240

    
2241
	function delete_queue() {
2242
		unref_on_altq_queue_list($this->GetQname());
2243
		cleanup_queue_from_rules($this->GetQname());
2244
		foreach ($this->subqueues as $q) {
2245
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2246
			$q->delete_queue();
2247
		}
2248
		unset_object_by_reference($this->GetLink());
2249
	}
2250

    
2251
	function validate_input($data, &$input_errors) {
2252
		parent::validate_input($data, $input_errors);
2253

    
2254
		if ($data['priority'] > 7)
2255
				$input_errors[] = gettext("Priority must be an integer between 1 and 7.");
2256
		$reqdfields[] = "bandwidth";
2257
		$reqdfieldsn[] = gettext("Bandwidth");
2258
		$reqdfields[] = "bandwidthtype";
2259
		$reqdfieldsn[] = gettext("Bandwidthtype");
2260

    
2261
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2262

    
2263
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2264
			$input_errors[] = gettext("Bandwidth must be an integer.");
2265

    
2266

    
2267
		if ($data['bandwidth'] < 0)
2268
                       $input_errors[] = gettext("Bandwidth cannot be negative.");
2269

    
2270
		if ($data['bandwidthtype'] == "%") {
2271
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2272
				$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
2273
		}
2274

    
2275
/*
2276
		$parent =& $this->GetParent();
2277
		switch ($data['bandwidthtype']) {
2278
		case "%":
2279
			$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2280
			break;
2281
		default:
2282
			$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2283
			break;
2284
		}
2285
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2286
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2287
*/
2288
	}
2289

    
2290
	function ReadConfig(&$q) {
2291
		parent::ReadConfig($q);
2292
		if (!empty($q['borrow']))
2293
			$this->SetBorrow("on");
2294
		else
2295
			$this->SetBorrow("");
2296
	}
2297

    
2298
	function build_javascript() {
2299
		return parent::build_javascript();
2300
	}
2301

    
2302
	function build_tree() {
2303
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&amp;queue=" . $this->GetQname()."&amp;action=show"; 
2304
		$tree .= "\" ";
2305
		$tmpvalue = trim($this->GetDefault());
2306
		if (!empty($tmpvalue))
2307
			$tree .= " class=\"navlnk\"";
2308
		$tree .= " >" . $this->GetQname() . "</a>";
2309
		if (is_array($this->subqueues)) {
2310
			$tree .= "<ul>";
2311
			foreach ($this->subqueues as $q)  {
2312
				$tree .= $q->build_tree();
2313
			}	
2314
			$tree .= "</ul>";
2315
		}
2316
		$tree .= "</li>";
2317
		return $tree;
2318
	}
2319

    
2320
	/* Even this should take children into consideration */
2321
	function build_rules(&$default = false) {
2322
		$pfq_rule = "queue ". $this->qname;
2323
		if ($this->GetInterface())
2324
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2325
		if ($this->GetBandwidth() && $this->GetBwscale())
2326
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2327
		$tmpvalue = $this->GetQpriority();
2328
		if (!empty($tmpvalue))
2329
			$pfq_rule .= " priority " . $this->GetQpriority();
2330
		$tmpvalue = trim($this->GetQlimit());
2331
		if (!empty($tmpvalue))
2332
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2333
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow() || $this->GetCodel()) {
2334
			$pfq_rule .= " cbq ( ";
2335
			$tmpvalue = trim($this->GetRed());
2336
			if (!empty($tmpvalue)) {
2337
				$comma = 1;
2338
				$pfq_rule .= " red ";
2339
			}
2340
			$tmpvalue = trim($this->GetCodel());
2341
			if (!empty($tmpvalue)) {
2342
				$comma = 1;
2343
				$pfq_rule .= " codel ";
2344
			}
2345
			$tmpvalue = trim($this->GetRio());
2346
			if (!empty($tmpvalue)) {
2347
				if ($comma) 
2348
					$pfq_rule .= " ,";
2349
				$comma = 1;
2350
				$pfq_rule .= " rio ";
2351
			}
2352
			$tmpvalue = trim($this->GetEcn());
2353
			if (!empty($tmpvalue)) {
2354
				if ($comma) 
2355
					$pfq_rule .= " ,";
2356
				$comma = 1;
2357
				$pfq_rule .= " ecn ";
2358
			}
2359
			$tmpvalue = trim($this->GetDefault());
2360
			if (!empty($tmpvalue)) {
2361
				if ($comma)
2362
					$pfq_rule .= " ,";
2363
				$comma = 1;
2364
				$pfq_rule .= " default ";
2365
				$default = true;
2366
			}
2367
			$tmpvalue = trim($this->GetBorrow());
2368
			if (!empty($tmpvalue)) {
2369
				if ($comma)
2370
					$pfq_rule .= ", ";
2371
				$pfq_rule .= " borrow ";
2372
			}
2373
			$pfq_rule .= " ) ";
2374
		} 
2375
		if (count($this->subqueues)) {
2376
			$i = count($this->subqueues);
2377
			$pfq_rule .= " { ";
2378
			foreach ($this->subqueues as $qkey => $qnone) {
2379
				if ($i > 1) {
2380
					$i--;
2381
					$pfq_rule .= " {$qkey}, ";
2382
				} else
2383
					$pfq_rule .= " {$qkey} ";
2384
			}
2385
			$pfq_rule .= " } \n";
2386
			foreach ($this->subqueues as $q)
2387
				$pfq_rule .= $q->build_rules($default);
2388
		}
2389

    
2390
		$pfq_rule .= " \n";
2391
		return $pfq_rule;
2392
	}
2393

    
2394
	function build_form() {
2395
		$form = parent::build_form();
2396
		$form .= "<tr>";
2397
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
2398
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2399
		if ($this->GetBandwidth() > 0)
2400
			$form .= htmlspecialchars($this->GetBandwidth());
2401
		$form .= "\" />";
2402
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2403
		$form .= "<option value=\"Gb\"";
2404
		if ($this->GetBwscale() == "Gb")
2405
			$form .= " selected=\"selected\"";
2406
		$form .= ">" . gettext("Gbit/s") . "</option>";
2407
		$form .= "<option value=\"Mb\"";
2408
		if ($this->GetBwscale() == "Mb")
2409
			$form .= " selected=\"selected\"";
2410
		$form .= ">" . gettext("Mbit/s") . "</option>";
2411
		$form .= "<option value=\"Kb\"";
2412
		if ($this->GetBwscale() == "Kb")
2413
			$form .= " selected=\"selected\"";
2414
		$form .= ">" . gettext("Kbit/s") . "</option>";
2415
		$form .= "<option value=\"b\"";
2416
		if ($this->GetBwscale() == "b")
2417
			$form .= " selected=\"selected\"";
2418
		$form .= ">" . gettext("Bit/s") . "</option>";
2419
		$form .= "<option value=\"%\"";
2420
		if ($this->GetBwscale() == "%")
2421
			$form .= " selected=\"selected\"";
2422
		$form .= ">%</option>";
2423
		$form .= "</select> <br/>";
2424
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
2425
		$form .= "</span></td></tr>";
2426
		$form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>";
2427
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2428
		if($this->GetBorrow() == "on") 
2429
			$form .=  " checked=\"checked\" ";
2430
		$form .= " /> " . gettext("Borrow from other queues when available") . "<br/></td></tr>";
2431

    
2432
		return $form;
2433
	}
2434

    
2435
	function update_altq_queue_data(&$data) { 
2436
		$this->ReadConfig($data);
2437
	}
2438

    
2439
	function wconfig() {
2440
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2441
		if (!is_array($cflink))
2442
			$cflink = array();
2443
		$cflink['interface'] = $this->GetInterface();
2444
		$cflink['qlimit'] = trim($this->GetQlimit());
2445
		if (empty($cflink['qlimit']))
2446
			unset($cflink['qlimit']);
2447
		$cflink['priority'] = $this->GetQpriority();
2448
		if (empty($cflink['priority']))
2449
			unset($cflink['priority']);
2450
		$cflink['name'] = $this->GetQname();
2451
		$cflink['description'] = $this->GetDescription();
2452
		if (empty($cflink['description']))
2453
			unset($cflink['description']);
2454
		$cflink['bandwidth'] = $this->GetBandwidth();
2455
		$cflink['bandwidthtype'] = $this->GetBwscale();
2456
		$cflink['enabled'] = trim($this->GetEnabled());
2457
		if (empty($cflink['enabled']))
2458
			unset($cflink['enabled']);
2459
		$cflink['default'] = trim($this->GetDefault());
2460
		if (empty($cflink['default']))
2461
			unset($cflink['default']);
2462
		$cflink['red'] = trim($this->GetRed());
2463
		if (empty($cflink['red']))
2464
			unset($cflink['red']);
2465
		$cflink['rio'] = trim($this->GetRio());
2466
		if (empty($cflink['rio']))
2467
			unset($cflink['rio']);
2468
		$cflink['ecn'] = trim($this->GetEcn());
2469
		if (empty($cflink['ecn']))
2470
			unset($cflink['ecn']);
2471
		$cflink['codel'] = trim($this->GetCodel());
2472
		if (empty($cflink['codel']))
2473
			unset($cflink['codel']);
2474
		$cflink['borrow'] = trim($this->GetBorrow());
2475
		if (empty($cflink['borrow']))
2476
			unset($cflink['borrow']);
2477
	}
2478
}
2479

    
2480
class fairq_queue extends priq_queue {
2481
	var $hogs;
2482
	var $buckets;
2483

    
2484
	function GetBuckets() {
2485
		return $this->buckets;
2486
	}
2487
	function SetBuckets($buckets) {
2488
		$this->buckets = $buckets;
2489
	}
2490
	function GetHogs() {
2491
		return $this->hogs;
2492
	}
2493
	function SetHogs($hogs) {
2494
		$this->hogs = $hogs;
2495
	}
2496
	function CanHaveChildren() {
2497
		return false;
2498
	}
2499

    
2500

    
2501
	function copy_queue($interface, &$cflink) {
2502
                $cflink['interface'] = $interface;
2503
                $cflink['qlimit'] = $this->GetQlimit();
2504
                $cflink['priority'] = $this->GetQpriority();
2505
                $cflink['name'] = $this->GetQname();
2506
                $cflink['description'] = $this->GetDescription();
2507
                $cflink['bandwidth'] = $this->GetBandwidth();
2508
                $cflink['bandwidthtype'] = $this->GetBwscale();
2509
                $cflink['enabled'] = $this->GetEnabled();
2510
                $cflink['default'] = $this->GetDefault();
2511
                $cflink['red'] = $this->GetRed();
2512
                $cflink['rio'] = $this->GetRio();
2513
                $cflink['ecn'] = $this->GetEcn();
2514
                $cflink['buckets'] = $this->GetBuckets();
2515
		$cflink['hogs'] = $this->GetHogs();
2516
	}
2517

    
2518
	/*
2519
	 * Should search even its children
2520
	 */
2521
	function &find_queue($interface, $qname) {
2522
		if ($qname == $this->GetQname())
2523
			return $this;
2524
	}
2525

    
2526
	function find_parentqueue($interface, $qname) { return; }
2527

    
2528
	function delete_queue() {
2529
		unref_on_altq_queue_list($this->GetQname());
2530
		cleanup_queue_from_rules($this->GetQname());
2531
		unset_object_by_reference($this->GetLink());
2532
	}
2533

    
2534
	function validate_input($data, &$input_errors) {
2535
		parent::validate_input($data, $input_errors);
2536

    
2537
		if ($data['priority'] > 255)
2538
				$input_errors[] = gettext("Priority must be an integer between 1 and 255.");
2539
		$reqdfields[] = "bandwidth";
2540
		$reqdfieldsn[] = gettext("Bandwidth");
2541
		$reqdfields[] = "bandwidthtype";
2542
		$reqdfieldsn[] = gettext("Bandwidthtype");
2543

    
2544
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2545

    
2546
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2547
			$input_errors[] = gettext("Bandwidth must be an integer.");
2548

    
2549

    
2550
		if ($data['bandwidth'] < 0)
2551
			$input_errors[] = gettext("Bandwidth cannot be negative.");
2552

    
2553

    
2554
		if ($data['bandwidthtype'] == "%") {
2555
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2556
				$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
2557
		}
2558

    
2559
/*
2560
           	$parent =& $this->GetParent();
2561
           	switch ($data['bandwidthtype']) {
2562
                       case "%":
2563
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2564
                       default:
2565
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2566
                             break;
2567
           	}
2568
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2569
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2570
*/
2571
	}
2572

    
2573
	function ReadConfig(&$q) {
2574
		parent::ReadConfig($q);
2575
		if (!empty($q['buckets']))
2576
			$this->SetBuckets($q['buckets']);
2577
		else
2578
			$this->SetBuckets("");
2579
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2580
			$this->SetHogs($q['hogs']);
2581
		else
2582
			$this->SetHogs("");
2583
	}
2584

    
2585
	function build_javascript() {
2586
		return parent::build_javascript();
2587
	}
2588

    
2589
	function build_tree() {
2590
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2591
		$this->GetInterface()."&amp;queue=" . $this->GetQname()."&amp;action=show"; 
2592
		$tree .= "\" ";
2593
		$tmpvalue = trim($this->GetDefault());
2594
		if (!empty($tmpvalue))
2595
			$tree .= " class=\"navlnk\"";
2596
		$tree .= " >" . $this->GetQname() . "</a>";
2597
		$tree .= "</li>";
2598
		return $tree;
2599
	}
2600

    
2601
	/* Even this should take children into consideration */
2602
	function build_rules(&$default = false) {
2603
		$pfq_rule = "queue ". $this->qname;
2604
		if ($this->GetInterface())
2605
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2606
		if ($this->GetBandwidth() && $this->GetBwscale())
2607
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2608
		$tmpvalue = trim($this->GetQpriority());
2609
		if (!empty($tmpvalue))
2610
			$pfq_rule .= " priority " . $this->GetQpriority();
2611
		$tmpvalue = trim($this->GetQlimit());
2612
		if (!empty($tmpvalue))
2613
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2614
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2615
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs() || $this->GetCodel()) {
2616
			$pfq_rule .= " fairq ( ";
2617
			$tmpvalue = trim($this->GetRed());
2618
			if (!empty($tmpvalue)) {
2619
				$comma = 1;
2620
				$pfq_rule .= " red ";
2621
			}
2622
			$tmpvalue = trim($this->GetCodel());
2623
			if (!empty($tmpvalue)) {
2624
				$comma = 1;
2625
				$pfq_rule .= " codel ";
2626
			}
2627
			$tmpvalue = trim($this->GetRio());
2628
			if (!empty($tmpvalue)) {
2629
				if ($comma) 
2630
					$pfq_rule .= " ,";
2631
				$comma = 1;
2632
				$pfq_rule .= " rio ";
2633
			}
2634
			$tmpvalue = trim($this->GetEcn());
2635
			if (!empty($tmpvalue)) {
2636
				if ($comma) 
2637
					$pfq_rule .= " ,";
2638
				$comma = 1;
2639
				$pfq_rule .= " ecn ";
2640
			}
2641
			$tmpvalue = trim($this->GetDefault());
2642
			if (!empty($tmpvalue)) {
2643
				if ($comma)
2644
					$pfq_rule .= " ,";
2645
				$comma = 1;
2646
				$pfq_rule .= " default ";
2647
				$default = true;
2648
			}
2649
			$tmpvalue = trim($this->GetBuckets());
2650
			if (!empty($tmpvalue)) {
2651
				if ($comma)
2652
					$pfq_rule .= ", ";
2653
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2654
			}
2655
			$tmpvalue = trim($this->GetHogs());
2656
			if (!empty($tmpvalue)) {
2657
				if ($comma)
2658
					$pfq_rule .= ", ";
2659
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2660
			}
2661
				$pfq_rule .= " ) ";
2662
		} 
2663

    
2664
		$pfq_rule .= " \n";
2665
		return $pfq_rule;
2666
	}
2667

    
2668
	function build_form() {
2669
		$form = parent::build_form();
2670
		$form .= "<tr>";
2671
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
2672
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2673
		if ($this->GetBandwidth() > 0)
2674
			$form .= htmlspecialchars($this->GetBandwidth());
2675
		$form .= "\" />";
2676
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2677
		$form .= "<option value=\"Gb\"";
2678
		if ($this->GetBwscale() == "Gb")
2679
			$form .= " selected=\"selected\"";
2680
		$form .= ">" . gettext("Gbit/s") . "</option>";
2681
		$form .= "<option value=\"Mb\"";
2682
		if ($this->GetBwscale() == "Mb")
2683
			$form .= " selected=\"selected\"";
2684
		$form .= ">" . gettext("Mbit/s") . "</option>";
2685
		$form .= "<option value=\"Kb\"";
2686
		if ($this->GetBwscale() == "Kb")
2687
			$form .= " selected=\"selected\"";
2688
		$form .= ">" . gettext("Kbit/s") . "</option>";
2689
		$form .= "<option value=\"b\"";
2690
		if ($this->GetBwscale() == "b")
2691
			$form .= " selected=\"selected\"";
2692
		$form .= ">" . gettext("Bit/s") . "</option>";
2693
		$form .= "<option value=\"%\"";
2694
		if ($this->GetBwscale() == "%")
2695
			$form .= " selected=\"selected\"";
2696
		$form .= ">%</option>";
2697
		$form .= "</select> <br/>";
2698
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
2699
		$form .= "</span></td></tr>";
2700
		$form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>";
2701
		$form .= "<td class=\"vtable\"><table><tr><td>";
2702
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2703
		$tmpvalue = trim($this->GetBuckets());
2704
		if(!empty($tmpvalue)) 
2705
			$form .=  $this->GetBuckets();
2706
		$form .= "\" /> " . gettext("Number of buckets available.") . "<br/></td></tr>";
2707
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2708
		$tmpvalue = trim($this->GetHogs());
2709
		if(!empty($tmpvalue)) 
2710
			$form .=  $this->GetHogs();
2711
		$form .= "\" /> " . gettext("Bandwidth limit for hosts to not saturate link.") . "<br/></td></tr>";
2712
		$form .= "</table></td></tr>";
2713
		return $form;
2714
	}
2715

    
2716
	function update_altq_queue_data(&$data) { 
2717
		$this->ReadConfig($data);
2718
	}
2719

    
2720
	function wconfig() {
2721
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2722
		if (!is_array($cflink))
2723
			$cflink = array();
2724
		$cflink['interface'] = $this->GetInterface();
2725
		$cflink['qlimit'] = trim($this->GetQlimit());
2726
		if (empty($cflink['qlimit']))
2727
			unset($cflink['qlimit']);
2728
		$cflink['priority'] = trim($this->GetQpriority());
2729
		if (empty($cflink['priority']))
2730
			unset($cflink['priority']);
2731
		$cflink['name'] = $this->GetQname();
2732
		$cflink['description'] = trim($this->GetDescription());
2733
		if (empty($cflink['description']))
2734
			unset($cflink['description']);
2735
		$cflink['bandwidth'] = $this->GetBandwidth();
2736
		$cflink['bandwidthtype'] = $this->GetBwscale();
2737
		$cflink['enabled'] = $this->GetEnabled();
2738
		if (empty($cflink['enabled']))
2739
			unset($cflink['enabled']);
2740
		$cflink['default'] = trim($this->GetDefault());
2741
		if (empty($cflink['default']))
2742
			unset($cflink['default']);
2743
		$cflink['red'] = trim($this->GetRed());
2744
		if (empty($cflink['red']))
2745
			unset($cflink['red']);
2746
		$cflink['rio'] = trim($this->GetRio());
2747
		if (empty($cflink['rio']))
2748
			unset($cflink['rio']);
2749
		$cflink['ecn'] = trim($this->GetEcn());
2750
		if (empty($cflink['ecn']))
2751
			unset($cflink['ecn']);
2752
		$cflink['codel'] = trim($this->GetCodel());
2753
		if (empty($cflink['codel']))
2754
			unset($cflink['codel']);
2755
		$cflink['buckets'] = trim($this->GetBuckets());
2756
		if (empty($cflink['buckets']))
2757
			unset($cflink['buckets']);
2758
		$cflink['hogs'] = trim($this->GetHogs());
2759
		if (empty($cflink['hogs']))
2760
			unset($cflink['hogs']);
2761
	}
2762
}
2763

    
2764

    
2765
/*
2766
 * dummynet(4) wrappers.
2767
 */
2768

    
2769

    
2770
/*
2771
 * List of respective objects!
2772
 */
2773
$dummynet_pipe_list = array();
2774

    
2775
class dummynet_class {
2776
        var $qname;
2777
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2778
        var $qlimit;
2779
        var $description;
2780
	var $qenabled;
2781
	var $link;
2782
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2783
        var $plr;
2784

    
2785
        var $buckets;
2786
        /* mask parameters */
2787
        var $mask;
2788
        var $noerror;
2789
        
2790
        /* Accessor functions */
2791
        function SetLink($link) {
2792
                $this->link = $link;
2793
        }
2794
        function GetLink() {
2795
                return $this->link;
2796
        }
2797
	function GetMask() {
2798
		if (!isset($this->mask["type"]))
2799
			$this->mask["type"] = "none";
2800
		return $this->mask;
2801
	}
2802
	function SetMask($mask) {
2803
		$this->mask = $mask;
2804
	}
2805
	function &GetParent() {
2806
		return $this->qparent;
2807
	}
2808
	function SetParent(&$parent) {
2809
		$this->qparent = &$parent;
2810
	}
2811
        function GetEnabled() {
2812
                return $this->qenabled;
2813
        }
2814
        function SetEnabled($value) {
2815
                $this->qenabled = $value;
2816
        }
2817
	function CanHaveChildren() {
2818
		return false;
2819
        }
2820
	function CanBeDeleted() {
2821
                return true;
2822
        }
2823
        function GetQname() {
2824
                return $this->qname;
2825
        }
2826
        function SetQname($name) {
2827
                $this->qname = trim($name);
2828
        }
2829
        function GetQlimit() {
2830
                return $this->qlimit;
2831
        }
2832
        function SetQlimit($limit) {
2833
               	$this->qlimit = $limit;
2834
        }
2835
        function GetDescription() {
2836
                return $this->description;
2837
        }
2838
        function SetDescription($str) {
2839
                $this->description = trim($str);
2840
        }
2841
        function GetFirstime() {
2842
                return $this->firsttime;
2843
        }
2844
        function SetFirsttime($number) {
2845
                $this->firsttime = $number;
2846
        }
2847
        function GetBuckets() {
2848
                return $this->buckets;
2849
        }
2850
        function SetBuckets($buckets) {
2851
                $this->buckets = $buckets;
2852
        }
2853
	function SetNumber($number) {
2854
		$this->qnumber = $number;
2855
	}
2856
	function GetNumber() {
2857
		return $this->qnumber;
2858
	}
2859
        function GetPlr() {
2860
                return $this->plr;
2861
        }
2862
        function SetPlr($plr) {
2863
                $this->plr = $plr;
2864
        }
2865

    
2866
	function build_javascript() {
2867
		$javascript .= "<script type=\"text/javascript\">\n";
2868
		$javascript .= "//<![CDATA[\n";
2869
		$javascript .= "function enable_maskbits(enable_over) {\n";
2870
		$javascript .= "var e = document.getElementById(\"mask\");\n";
2871
		$javascript .= "if ((e.options[e.selectedIndex].text == \"none\") || enable_over) {\n";
2872
		$javascript .= "document.iform.maskbits.disabled = 1;\n";
2873
		$javascript .= "document.iform.maskbits.value = \"\";\n";
2874
		$javascript .= "document.iform.maskbitsv6.disabled = 1;\n";
2875
		$javascript .= "document.iform.maskbitsv6.value = \"\";\n";
2876
		$javascript .= "} else {\n";
2877
		$javascript .= "document.iform.maskbits.disabled = 0;\n";
2878
                $javascript .= "document.iform.maskbitsv6.disabled = 0;\n";
2879
		$javascript .= "}}\n";
2880
		$javascript .= "//]]>\n";
2881
		$javascript .= "</script>\n";
2882
		return $javascript;
2883
	}
2884

    
2885
	function validate_input($data, &$input_errors) {
2886
		$reqdfields[] = "bandwidth";
2887
		$reqdfieldsn[] = gettext("Bandwidth");
2888
		$reqdfields[] = "burst";
2889
		$reqdfieldsn[] = gettext("Burst");
2890
		$reqdfields[] = "bandwidthtype";
2891
		$reqdfieldsn[] = gettext("Bandwidthtype");
2892
		$reqdfields[] = "newname";
2893
		$reqdfieldsn[] = gettext("Name");
2894

    
2895
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2896

    
2897
		if ($data['plr'] && (!is_numeric($data['plr']) ||
2898
			($data['plr'] < 0) || ($data['plr'] > 1))) 
2899
				$input_errors[] = gettext("Plr must be a value between 0 and 1.");
2900
		if ($data['buckets'] && (!is_numeric($data['buckets']) ||
2901
			($data['buckets'] < 16) || ($data['buckets'] > 65535)))
2902
				$input_errors[] = gettext("Buckets must be an integer between 16 and 65535.");
2903
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2904
            		$input_errors[] = gettext("Queue limit must be an integer");
2905
        	if (!empty($data['newname']) && !preg_match("/^[a-zA-Z0-9_-]+$/", $data['newname']))
2906
			$input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
2907
        	if (!empty($data['name']) && !preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2908
			$input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
2909
                if (isset($data['maskbits']) && ($data['maskbits'] <> ""))
2910
			if ((!is_numeric($data['maskbits'])) || ($data['maskbits'] <= 0) || ($data['maskbits'] > 32))
2911
				$input_errors[] = gettext("IPV4 bit mask must be blank or numeric value between 1 and 32.");
2912
		if (isset($data['maskbitsv6']) && ($data['maskbitsv6'] <> ""))
2913
			if ((!is_numeric($data['maskbitsv6'])) || ($data['maskbitsv6'] <= 0) || ($data['maskbitsv6'] > 128))
2914
				$input_errors[] = gettext("IPV6 bit mask must be blank or numeric value between 1 and 128.");
2915
	}
2916
	
2917
	function build_mask_rules(&$pfq_rule) {
2918
		$mask = $this->GetMask();
2919
		if (!empty($mask['type'])) {
2920
			if ($mask['type'] <> 'none')
2921
				$pfq_rule .= " mask";
2922
			switch ($mask['type']) {
2923
			case 'srcaddress':
2924
				if (!empty($mask['bitsv6']) && ($mask['bitsv6'] <> ""))
2925
					$pfq_rule .= " src-ip6 /" . $mask['bitsv6'];
2926
				else
2927
					$pfq_rule .= " src-ip6 /128";
2928
                                if (!empty($mask['bits']) && ($mask['bits'] <> ""))
2929
                                        $pfq_rule .= sprintf(" src-ip 0x%x", gen_subnet_mask_long($mask['bits']));
2930
                                else
2931
					$pfq_rule .= " src-ip 0xffffffff";
2932
				break;
2933
			case 'dstaddress':
2934
				if (!empty($mask['bitsv6']) && ($mask['bitsv6'] <> ""))
2935
					$pfq_rule .= " dst-ip6 /" . $mask['bitsv6'];
2936
				else
2937
					$pfq_rule .= " dst-ip6 /128";
2938
                                if (!empty($mask['bits']) && ($mask['bits'] <> ""))
2939
                                        $pfq_rule .= sprintf(" dst-ip 0x%x", gen_subnet_mask_long($mask['bits']));
2940
                                else
2941
					$pfq_rule .= " dst-ip 0xffffffff";
2942
				break;
2943
			default:
2944
				break;
2945
			}
2946
		}            
2947
	}
2948
        
2949
}
2950

    
2951
class dnpipe_class extends dummynet_class {
2952
        var $delay;
2953
	var $qbandwidth = array();
2954
	var $qbandwidthtype;
2955

    
2956
		/* This is here to help on form building and building rules/lists */
2957
        var $subqueues = array();
2958

    
2959
	function CanHaveChildren() {
2960
	        return true;
2961
        }
2962
	function SetDelay($delay) {
2963
		$this->delay = $delay;
2964
	}
2965
	function GetDelay() {
2966
		return $this->delay;
2967
	}
2968
	function delete_queue() {
2969
		cleanup_dnqueue_from_rules($this->GetQname());
2970
		foreach ($this->subqueues as $q)
2971
			$q->delete_queue();
2972
		unset_dn_object_by_reference($this->GetLink());
2973
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2974
        }
2975
        function GetBandwidth() {
2976
                return $this->qbandwidth;
2977
        }
2978
        function SetBandwidth($bandwidth) {
2979
                $this->qbandwidth = $bandwidth;
2980
        }
2981
		function GetBurst() {
2982
				return $this->qburst;
2983
		}
2984
		function SetBurst($burst) {
2985
				$this->qburst = $burst;
2986
		}
2987

    
2988
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2989

    
2990
		if (!is_array($this->subqueues))
2991
			$this->subqueues = array();
2992

    
2993
		$q =& new dnqueue_class();
2994
		$q->SetLink($path);
2995
		$q->SetEnabled("on");
2996
		$q->SetPipe($this->GetQname());
2997
		$q->SetParent($this);
2998
		$q->ReadConfig($queue);
2999
		$q->validate_input($queue, $input_errors);
3000
		if (count($input_errors)) {
3001
			log_error("SHAPER: could not create queue " . $q->GetQname() . " on interface {$interface} because: " . print_r($input_errors, true));
3002
			return $q;
3003
		}
3004
		$number = dnqueue_find_nextnumber();
3005
		$q->SetNumber($number);
3006
		$this->subqueues[$q->GetQname()] = &$q;
3007
            
3008
		return $q;
3009
	}
3010

    
3011
	function &get_queue_list(&$q = null) {
3012
		$qlist = array();
3013

    
3014
		$qlist[$this->GetQname()] = $this->GetNumber();
3015
		if (is_array($this->subqueues)) {
3016
			foreach ($this->subqueues as $queue)
3017
				$queue->get_queue_list($qlist);
3018
		}
3019
		return $qlist;
3020
	}
3021

    
3022
        /*
3023
         * Should search even its children
3024
         */
3025
        function &find_queue($pipe, $qname) {
3026
                if ($qname == $this->GetQname()) 
3027
                        return $this;
3028
               	foreach ($this->subqueues as $q) {
3029
                       	$result =& $q->find_queue("", $qname);
3030
						if ($result)
3031
                       	        return $result;
3032
               	}
3033
        }
3034

    
3035
	function &find_parentqueue($pipe, $qname) {
3036
		return NULL;
3037
       	}
3038

    
3039
	function validate_input($data, &$input_errors) {
3040
		parent::validate_input($data, $input_errors);
3041

    
3042
		$schedule = 0;
3043
		$schedulenone = 0;
3044
		$entries = 0;
3045
		for ($i = 0; $i < 30; $i++) {
3046
			if (!empty($data["bwsched{$i}"])) {
3047
				if ($data["bwsched{$i}"] != "none")
3048
					$schedule++;
3049
				else
3050
					$schedulenone++;
3051
			}
3052
			if (!empty($data["bandwidth{$i}"])) {
3053
				if (!is_numeric($data["bandwidth{$i}"]))
3054
					$input_errors[] = sprintf(gettext("Bandwidth for schedule %s must be an integer."), $data["bwsched{$i}"]);
3055
				else if (($data["burst{$i}"] != "") && (!is_numeric($data["burst{$i}"])))
3056
					$input_errors[] = sprintf(gettext("Burst for schedule %s must be an integer."), $data["bwsched{$i}"]);
3057
				else
3058
					$entries++;
3059
			}
3060
		}
3061
		if ($schedule == 0 && $entries > 1)
3062
			$input_errors[] = gettext("You need to specify a schedule for every additional entry");
3063
		if ($schedulenone > 0 && $entries > 1)
3064
			$input_errors[] = gettext("If more than one bandwidth configured all schedules need to be selected");
3065
		if ($entries == 0)
3066
			$input_errors[] = gettext("At least one bw specification is necessary");
3067
		if ($data['delay'] && (!is_numeric($data['delay'])))
3068
			$input_errors[] = gettext("Delay must be an integer.");
3069
	}
3070

    
3071
	function ReadConfig(&$q) {
3072
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
3073
			$this->SetQname($q['newname']);
3074
		} else if (!empty($q['newname'])) {
3075
			$this->SetQname($q['newname']);
3076
		} else {
3077
			$this->SetQname($q['name']);
3078
		}
3079
		$this->SetNumber($q['number']);
3080

    
3081
		if (!empty($_POST)) {
3082
			$bandwidth = array();
3083
			for ($i = 0; $i < 30; $i++) {
3084
				if (isset($q["bandwidth{$i}"]) && $q["bandwidth{$i}"] <> "") { 
3085
					$bw = array();
3086
					$bw['bw'] = $q["bandwidth{$i}"];
3087
					$bw['burst'] = $q["burst{$i}"];
3088
					if (isset($q["bwtype{$i}"]) && $q["bwtype{$i}"])
3089
						$bw['bwscale'] = $q["bwtype{$i}"];
3090
					if (isset($q["bwsched{$i}"]) && $q["bwsched{$i}"])
3091
						$bw['bwsched'] = $q["bwsched{$i}"];
3092
					$bandwidth[] = $bw;
3093
				}
3094
			}
3095
			$this->SetBandwidth($bandwidth);
3096
		}
3097
		
3098
		if (is_array($q['bandwidth']) && is_array($q['bandwidth']['item'])) {
3099
			$this->SetBandwidth($q['bandwidth']['item']);
3100
			$this->SetBurst($q['burst']['item']);
3101
		}
3102
			
3103
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3104
              		$this->SetQlimit($q['qlimit']);
3105
		else
3106
              		$this->SetQlimit("");
3107
		if (isset($q['mask']) && $q['mask'] <> "")
3108
			$masktype = $q['mask'];
3109
		else
3110
			$masktype = "";
3111
		if (isset($q['maskbits']) && $q['maskbits'] <> "")
3112
			$maskbits = $q['maskbits'];
3113
		else
3114
			$maskbits = "";
3115
		if (isset($q['maskbitsv6']) && $q['maskbitsv6'] <> "")
3116
			$maskbitsv6 = $q['maskbitsv6'];
3117
		else
3118
			$maskbitsv6 = "";
3119
		$this->SetMask(array("type" => $masktype, "bits" => $maskbits, "bitsv6" => $maskbitsv6));
3120
		if (isset($q['buckets']) && $q['buckets'] <> "")
3121
              		$this->SetBuckets($q['buckets']);
3122
		else
3123
              		$this->SetBuckets("");
3124
            	if (isset($q['plr']) && $q['plr'] <> "")
3125
            		$this->SetPlr($q['plr']);
3126
		else
3127
            		$this->SetPlr("");
3128
		if (isset($q['delay']) && $q['delay'] <> "")
3129
            		$this->SetDelay($q['delay']);
3130
		else
3131
			$this->SetDelay(0);
3132
            	if (isset($q['description']) && $q['description'] <> "")
3133
			$this->SetDescription($q['description']);
3134
		else
3135
			$this->SetDescription("");
3136
		$this->SetEnabled($q['enabled']);
3137

    
3138
        }
3139

    
3140
	function build_tree() {
3141
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&amp;queue=".$this->GetQname() ."&amp;action=show\">"; 
3142
		$tree .= $this->GetQname() . "</a>";
3143
		if (is_array($this->subqueues)) {
3144
			$tree .= "<ul>";
3145
			foreach ($this->subqueues as $q)  {
3146
				$tree .= $q->build_tree();
3147
			}	
3148
			$tree .= "</ul>";
3149
		}
3150
		$tree .= "</li>";
3151

    
3152
		return $tree;
3153
	}
3154

    
3155
        function build_rules() {
3156
		global $config, $time_based_rules;
3157

    
3158
		if ($this->GetEnabled() == "")
3159
			return;
3160

    
3161
		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
3162
		$found = false;
3163
		$bandwidth = $this->GetBandwidth();
3164
		if (is_array($bandwidth)) {
3165
			foreach ($bandwidth as $bw) {
3166
				if ($bw['bwsched'] != "none") {
3167
					$time_based_rules = true;
3168
					if (is_array($config['schedules']) && is_array($config['schedules']['schedule'])) {
3169
						foreach ($config['schedules']['schedule'] as $schedule) {
3170
							if ($bw['bwsched'] == $schedule['name']) {
3171
								if (filter_get_time_based_rule_status($schedule)) {
3172
									$pfq_rule .= " bw ".trim($bw['bw']).$bw['bwscale'];
3173
									if (is_numeric($bw['burst']) && ($bw['burst'] > 0))
3174
										$pfq_rule .= " burst ".trim($bw['burst']).$bw['bwscale'];
3175
									$found = true;
3176
									break;
3177
								}
3178
							}
3179
						}
3180
					} else {
3181
						$pfq_rule .= " bw 0";
3182
						$found = true;
3183
						break;
3184
					}
3185
				} else {
3186
					$pfq_rule .= " bw ".trim($bw['bw']).$bw['bwscale'];
3187
					if (is_numeric($bw['burst']) && ($bw['burst'] > 0))
3188
						$pfq_rule .= " burst ".trim($bw['burst']).$bw['bwscale'];
3189
					$found = true;
3190
					break;
3191
				}
3192
			}
3193
			if ($found == false)
3194
				$pfq_rule .= " bw 0";
3195
		} else
3196
			$pfq_rule .= " bw 0";
3197

    
3198
		if ($this->GetQlimit())
3199
			$pfq_rule .= " queue " . $this->GetQlimit();
3200
		if ($this->GetPlr())
3201
			$pfq_rule .= " plr " . $this->GetPlr();
3202
		if ($this->GetBuckets())
3203
			$pfq_rule .= " buckets " . $this->GetBuckets();
3204
		if ($this->GetDelay())
3205
			$pfq_rule .= " delay " . $this->GetDelay();
3206
		$this->build_mask_rules($pfq_rule);
3207

    
3208
		$pfq_rule .= "\n";
3209

    
3210
		if (!empty($this->subqueues) && count($this->subqueues) > 0) {
3211
			foreach ($this->subqueues as $q)
3212
			$pfq_rule .= $q->build_rules();
3213
		}
3214
		$pfq_rule .= " \n";
3215

    
3216
		return $pfq_rule;
3217
        }
3218

    
3219
	function update_dn_data(&$data) { 
3220
		$this->ReadConfig($data);
3221
	}
3222

    
3223
	function build_javascript() {
3224
		global $g, $config;
3225

    
3226
		$javasr = parent::build_javascript();
3227
		
3228
		//build list of schedules
3229
		$schedules = "<option value='none'>none</option>";
3230
		if (is_array($config['schedules']) && is_array($config['schedules']['schedule'])) {
3231
			foreach ($config['schedules']['schedule'] as $schedule) {
3232
				if ($schedule['name'] <> "")
3233
					$schedules .= "<option value='{$schedule['name']}'>{$schedule['name']}</option>";
3234
			}
3235
		}
3236
		$bwopt = "";
3237
		foreach (array("Kb" => "Kbit/s", "Mb" => "Mbit/s", "Gb" => "Gbit/s", "b" => "Bit/s") as $bwidx => $bw)
3238
			$bwopt .= "<option value='{$bwidx}'>{$bw}</option>";
3239

    
3240
		$javasr .= <<<EOD
3241
<script type='text/javascript'>
3242
//<![CDATA[
3243
var addBwRowTo = (function() {
3244
	return (function (tableId) {
3245
	var d, tbody, tr, td;
3246
	d = document;
3247
	tbody = d.getElementById(tableId).getElementsByTagName("tbody").item(0);
3248
	tr = d.createElement("tr");
3249
	td = d.createElement("td");
3250
	td.innerHTML="<input type='hidden' value='" + totalrows +"' name='bandwidth_row-" + totalrows + "' /><input size='10' type='text' class='formfld unknown' name='bandwidth" + totalrows + "' id='bandwidth" + totalrows + "' />";
3251
	tr.appendChild(td);
3252
	td = d.createElement("td");
3253
	td.innerHTML="<input type='hidden' value='" + totalrows +"' name='burst_row-" + totalrows + "' /><input size='10' type='text' class='formfld unknown' name='burst" + totalrows + "' id='burst" + totalrows + "' />";
3254
	tr.appendChild(td);
3255
	td = d.createElement("td");
3256
	td.innerHTML="<input type='hidden' value='" + totalrows +"' name='bwtype_row-" + totalrows + "' /><select class='formselect' name='bwtype" + totalrows + "'>{$bwopt}</select>";
3257
	tr.appendChild(td);
3258
	td = d.createElement("td");
3259
	td.innerHTML="<input type='hidden' value='" + totalrows +"' name='bwsched_row-" + totalrows + "' /><select class='formselect' name='bwsched" + totalrows + "'>{$schedules}</select>";
3260
	tr.appendChild(td);
3261
	td = d.createElement("td");
3262
	td.rowSpan = "1";
3263
	td.innerHTML = '<a onclick="removeBwRow(this); return false;" href="#"><img border="0" src="/themes/{$g['theme']}/images/icons/icon_x.gif" alt="remove" /></a>';
3264
	tr.appendChild(td);
3265
	tbody.appendChild(tr);
3266
	totalrows++;
3267
	});
3268
})();
3269

    
3270
function removeBwRow(el) {
3271
	var cel;
3272
	while (el && el.nodeName.toLowerCase() != "tr")
3273
	    el = el.parentNode;
3274
		if (el && el.parentNode) {
3275
			cel = el.getElementsByTagName("td").item(0);
3276
			el.parentNode.removeChild(el);
3277
		}
3278
}
3279
//]]>
3280
</script>
3281

    
3282
EOD;
3283

    
3284
	       return $javasr;
3285
	}
3286

    
3287
        function build_form() { 
3288
		global $g, $config;
3289

    
3290
		//build list of schedules
3291
		$schedules = array();
3292
		$schedules[] = "none";//leave none to leave rule enabled all the time
3293
		if (is_array($config['schedules']) && is_array($config['schedules']['schedule'])) {
3294
			foreach ($config['schedules']['schedule'] as $schedule) {
3295
				if ($schedule['name'] <> "")
3296
					$schedules[] = $schedule['name'];
3297
			}
3298
		}
3299

    
3300
		$form = "<tr><td valign=\"middle\" class=\"vncellreq\"><br/>";
3301
                $form .= gettext("Enable");
3302
                $form .= "</td><td class=\"vncellreq\">";
3303
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
3304
                if ($this->GetEnabled() == "on")
3305
                        $form .=  " checked=\"checked\"";
3306
                $form .= " /><span class=\"vexpl\"> " . gettext("Enable limiter and its children") . "</span>";
3307
                $form .= "</td></tr>";
3308
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\"><br/><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
3309
		$form .= "<td class=\"vncellreq\">";
3310
		$form .= "<input type=\"text\" id=\"newname\" name=\"newname\" value=\"";
3311
		$form .= $this->GetQname()."\" />";
3312
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"";
3313
		$form .= $this->GetQname()."\" />";
3314
		if ($this->GetNumber() > 0) {
3315
			$form .= "<input type=\"hidden\" id=\"number\" name=\"number\" value=\"";
3316
			$form .= $this->GetNumber()."\" />";
3317
		}
3318
		$form .= "</td></tr>";
3319
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Bandwidth");
3320
		$bandwidth = $this->GetBandwidth();
3321
		$form .= "</td><td class=\"vncellreq\">";
3322
		$form .= "<table id='maintable'>";
3323
		$form .= "<tbody><tr>";
3324
		$form .= "<td width='35%'><div id='onecolumn'>Bandwidth</div></td>";
3325
		$form .= "<td width='35%'><div id='fifthcolumn'>Burst</div></td>";
3326
		$form .= "<td width='20%'><div id='twocolumn'>Bw type</div></td>";
3327
		$form .= "<td width='35%' ><div id='thirdcolumn'>Schedule</div></td>";
3328
		$form .= "<td width='5%'><div id='fourthcolumn'></div></td>";
3329
		$form .= "</tr>";
3330
		if (is_array($bandwidth)) {
3331
			foreach ($bandwidth as $bwidx => $bw) {
3332
				$form .= "\n<tr><td width='40%'>";
3333
				$form .= "<input class='formfld unknown' size='10' type=\"text\" id=\"bandwidth{$bwidx}\" name=\"bandwidth{$bwidx}\" value=\"{$bw['bw']}\" />";
3334
				$form .= "</td><td width='20%'>";
3335
				$form .= "<input class='formfld unknown' size='10' type=\"text\" id=\"burst{$bwidx}\" name=\"burst{$bwidx}\" value=\"{$bw['burst']}\" />";
3336
				$form .= "</td><td width='20%'>";
3337
				$form .= "<select id=\"bwtype{$bwidx}\" name=\"bwtype{$bwidx}\" class=\"formselect\">";
3338
				foreach (array("Kb" => "Kbit/s", "Mb" => "Mbit/s", "Gb" => "Gbit/s", "b" => "Bit/s") as $bwsidx => $bwscale) {
3339
					$form .= "<option value=\"{$bwsidx}\"";
3340
					if ($bw['bwscale'] == $bwsidx)
3341
						$form .= " selected=\"selected\"";
3342
					$form .= ">{$bwscale}</option>";
3343
				}
3344
				$form .= "</select>";
3345
				$form .= "</td><td width='35%' >";
3346
				$form .= "<select id=\"bwsched{$bwidx}\" name=\"bwsched{$bwidx}\" class=\"formselect\">";
3347
				foreach ($schedules as $schd) {
3348
					$selected = "";
3349
					if ($bw['bwsched'] == $schd)
3350
						$selected = "selected=\"selected\"";
3351
					$form .= "<option value='{$schd}' {$selected}>{$schd}</option>";
3352
				}
3353
				$form .= "</select>";
3354
				$form .= "</td><td width='5%' >";
3355
				$form .= "<a onclick=\"removeBwRow(this); return false;\" href='#'><img border='0' src='/themes/{$g['theme']}/images/icons/icon_x.gif' alt='remove' /></a>";
3356
				$form .= "</td></tr>";
3357
			}
3358
		}
3359
		$form .= "</tbody></table>";
3360
		$form .= "<a onclick=\"javascript:addBwRowTo('maintable'); return false;\" href='#'>";
3361
		$form .= "<img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='add' title='" . gettext("add another schedule") . "' /></a>";
3362
		$form .= "<br/><span class=\"vexpl\">" . gettext("Bandwidth is a rate (e.g. Mbit/s), burst is a total amount of data that will be transferred at full speed after an idle period.") . "</span><br />";
3363
		$form .= "</td></tr>";
3364
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Mask") . "</td>";
3365
		$form .= "<td class=\"vncellreq\">";
3366
		$form .= "<select name=\"mask\" id=\"mask\" class=\"formselect\" onchange=\"enable_maskbits();\" >";
3367
		$form .= "<option value=\"none\"";
3368
		$mask = $this->GetMask();
3369
		if ($mask['type'] == "none")
3370
			$form .= " selected=\"selected\"";
3371
		$form .= ">none</option>";
3372
		$form .= "<option value=\"srcaddress\"";
3373
		if ($mask['type'] == "srcaddress")
3374
			$form .= " selected=\"selected\"";
3375
		$form .= ">" . gettext("Source addresses") . "</option>";
3376
		$form .= "<option value=\"dstaddress\"";
3377
		if ($mask['type'] == "dstaddress")
3378
			$form .= " selected=\"selected\"";
3379
		$form .= ">" . gettext("Destination addresses") . "</option>";
3380
		$form .= "</select>";
3381
		$form .= "&nbsp;<br/>";
3382
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' slots is chosen, \n"
3383
		      .  "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n"
3384
		      .  "be created for each source/destination IP address encountered, \n"
3385
		      .  "respectively. This makes it possible to easily specify bandwidth \n"
3386
		      .  "limits per host.") . "</span><br />";
3387
		$form .= "255.255.255.255/&nbsp;<input type=\"text\" class=\"formfld unknown\" size=\"2\" id=\"maskbits\" name=\"maskbits\" value=\"";
3388
		if ($mask['type'] <> "none")
3389
		$form .= $mask['bits'];
3390
		$form .= "\"";
3391
		if ($mask['type'] == "none")
3392
			$form .= " disabled";
3393
		$form .= " />";
3394
		$form .= "&nbsp; IPV4 mask bits (1-32)<br/>";
3395
		$form .= "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/&nbsp;<input type=\"text\" class=\"formfld unknown\" size=\"2\" id=\"maskbitsv6\" name=\"maskbitsv6\" value=\"";
3396
		if ($mask['type'] <> "none")
3397
		$form .= $mask['bitsv6'];
3398
		$form .= "\"";
3399
		if ($mask['type'] == "none")
3400
			$form .= " disabled";
3401
		$form .= " />";
3402
		$form .= "&nbsp; IPV6 mask bits (1-128)<br/>";
3403
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' slots is chosen, \n"
3404
		      .  "leaving the mask bits blank will create one pipe per host. Otherwise specify \n"
3405
		      .  "the number of 'one' bits in the subnet mask used to group multiple hosts \n"
3406
		      .  "per pipe.") . "</span>";
3407
		$form .= "</td></tr>";
3408
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Description") . "</td>";
3409
		$form .= "<td class=\"vncellreq\">";
3410
		$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"40\" id=\"description\" name=\"description\" value=\"";
3411
		$form .= $this->GetDescription();
3412
		$form .= "\" />";
3413
		$form .= "<br/> <span class=\"vexpl\">";
3414
		$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3415
		$form .= "</td></tr>";
3416
      		$form .= "<tr id=\"sprtable4\">";
3417
		$form .= "<td></td>";
3418
                $form .= "<td><div id=\"showadvancedboxspr\">";
3419
                $form .= "<p><input type=\"button\" onclick=\"show_source_port_range()\"";
3420
		$form .= " value=\"" . gettext("Show advanced options") . "\" />";
3421
                $form .= "</p></div></td></tr>";
3422
                $form .= "<tr style=\"display:none\" id=\"sprtable\">";
3423

    
3424
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Delay") . "</td>";
3425
		$form .= "<td valign=\"middle\" class=\"vncellreq\">";
3426
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3427
		$form .= $this->GetDelay() . "\" />";
3428
		$form .= "&nbsp;ms<br/> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3429
			  .  "should specify 0 here (or leave the field empty)") . "</span><br/>";
3430
		$form .= "</td></tr>";
3431
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\">";
3432
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Packet loss rate") . "</td>";
3433
		$form .= "<td valign=\"middle\" class=\"vncellreq\">";
3434
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3435
		$form .= $this->GetPlr() . "\" />";
3436
		$form .= "&nbsp;<br/> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3437
			  .  "should specify 0 here (or leave the field empty). "
3438
		      .  "A value of 0.001 means one packet in 1000 gets dropped") . "</span>";
3439
		$form .= "</td></tr>";
3440
		$form .= "<tr style=\"display:none\" id=\"sprtable2\">";
3441
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Queue Size") . "</td>";
3442
		$form .= "<td class=\"vncellreq\">";
3443
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3444
		$form .= $this->GetQlimit() . "\" />";
3445
		$form .= "&nbsp;slots<br/>";
3446
		$form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3447
		      .  "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, "
3448
	              .  "then they are delayed by value specified in the Delay field, and then they "
3449
		      .  "are delivered to their destination.") . "</span>";
3450
		$form .= "</td></tr>";
3451
		$form .= "<tr style=\"display:none\" id=\"sprtable5\">";
3452
                $form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bucket Size") . "</td>";
3453
                $form .= "<td class=\"vncellreq\">";
3454
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3455
                $form .= $this->GetBuckets() . "\" />";
3456
                $form .= "&nbsp;slots<br/>";
3457
                $form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3458
                      .  "should leave the field empty. It increases the hash size set.");
3459
                $form .= "</span></td></tr>";
3460

    
3461
		return $form;
3462

    
3463
		}
3464

    
3465
	function wconfig() {
3466
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3467
            	if (!is_array($cflink))
3468
            		$cflink = array();
3469
		$cflink['name'] = $this->GetQname();
3470
		$cflink['number'] = $this->GetNumber();
3471
            	$cflink['qlimit'] = $this->GetQlimit();
3472
            	$cflink['plr'] = $this->GetPlr();
3473
            	$cflink['description'] = $this->GetDescription();
3474
               
3475
		$bandwidth = $this->GetBandwidth();
3476
		if (is_array($bandwidth)) {
3477
			$cflink['bandwidth'] = array();
3478
			$cflink['bandwidth']['item'] = array();
3479
			foreach ($bandwidth as $bwidx => $bw)
3480
				$cflink['bandwidth']['item'][] = $bw;
3481
		}
3482

    
3483
		$cflink['enabled'] = $this->GetEnabled();
3484
		$cflink['buckets'] = $this->GetBuckets();
3485
		$mask = $this->GetMask();
3486
		$cflink['mask'] = $mask['type'];
3487
		$cflink['maskbits'] = $mask['bits'];
3488
                $cflink['maskbitsv6'] = $mask['bitsv6'];
3489
		$cflink['delay'] = $this->GetDelay();
3490
	}
3491

    
3492
}
3493

    
3494
class dnqueue_class extends dummynet_class {
3495
        var $pipeparent;
3496
        var $weight;
3497

    
3498
        function GetWeight() {
3499
                return $this->weight;
3500
        }
3501
        function SetWeight($weight) {
3502
                $this->weight = $weight;
3503
        }
3504
	function GetPipe() {
3505
		return $this->pipeparent;
3506
	}
3507
	function SetPipe($pipe) {
3508
		$this->pipeparent = $pipe;
3509
	}
3510

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

    
3514
	function delete_queue() {
3515
		cleanup_dnqueue_from_rules($this->GetQname());
3516
		unset_dn_object_by_reference($this->GetLink());
3517
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3518
        }
3519

    
3520
	function validate_input($data, &$input_errors) {
3521
		parent::validate_input($data, $input_errors);
3522

    
3523
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3524
			($data['weight'] < 1 && $data['weight'] > 100))) 
3525
				$input_errors[] = gettext("Weight must be an integer between 1 and 100.");
3526
	}
3527

    
3528
        /*
3529
         * Should search even its children
3530
         */
3531
        function &find_queue($pipe, $qname) {
3532
                if ($qname == $this->GetQname()) 
3533
                	return $this;
3534
		else
3535
			return NULL;
3536
        }
3537

    
3538
	function &find_parentqueue($pipe, $qname) {
3539
		return $this->qparent;
3540
        }
3541

    
3542
        function &get_queue_list(&$qlist) {
3543
		if ($this->GetEnabled() == "")
3544
			return;
3545
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3546
        }		
3547

    
3548
	function ReadConfig(&$q) {
3549
		if (!empty($q['name']) && !empty($q['newname']) && $q['name'] != $q['newname']) {
3550
			$this->SetQname($q['newname']);
3551
		} else if (!empty($q['newname'])) {
3552
			$this->SetQname($q['newname']);
3553
		} else {
3554
			$this->SetQname($q['name']);
3555
		}
3556
		$this->SetNumber($q['number']);
3557
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3558
       		       	$this->SetQlimit($q['qlimit']);
3559
		else
3560
       		       	$this->SetQlimit("");
3561
		if (isset($q['mask']) && $q['mask'] <> "")
3562
			$masktype = $q['mask'];
3563
		else
3564
			$masktype = "";
3565
		if (isset($q['maskbits']) && $q['maskbits'] <> "")
3566
			$maskbits = $q['maskbits'];
3567
		else
3568
			$maskbits = "";
3569
		if (isset($q['maskbitsv6']) && $q['maskbitsv6'] <> "")
3570
			$maskbitsv6 = $q['maskbitsv6'];
3571
		else
3572
			$maskbitsv6 = "";
3573
		$this->SetMask(array("type" => $masktype, "bits" => $maskbits, "bitsv6" => $maskbitsv6));
3574
       		if (isset($q['weight']) && $q['weight'] <> "")
3575
            		$this->SetWeight($q['weight']);
3576
		else
3577
            		$this->SetWeight("");
3578
            	if (isset($q['description']) && $q['description'] <> "")
3579
			$this->SetDescription($q['description']);
3580
		else
3581
			$this->SetDescription("");
3582
		$this->SetEnabled($q['enabled']);
3583
        }
3584

    
3585
	function build_tree() {
3586
		$parent =& $this->GetParent();
3587
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&amp;queue=" . $this->GetQname() ."&amp;action=show\">"; 
3588
		$tree .= $this->GetQname() . "</a>";
3589
		$tree .= "</li>";
3590

    
3591
		return $tree;
3592
	}
3593

    
3594
        function build_rules() {
3595
		if ($this->GetEnabled() == "")
3596
			return; 
3597

    
3598
		$parent =& $this->GetParent();
3599
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3600
		if ($this->GetQlimit())
3601
                    	$pfq_rule .= " queue " . $this->GetQlimit();
3602
		if ($this->GetWeight())
3603
			$pfq_rule .= " weight " . $this->GetWeight();
3604
		if ($this->GetBuckets())
3605
			$pfq_rule .= " buckets " . $this->GetBuckets();
3606
		$this->build_mask_rules($pfq_rule);
3607
		$pfq_rule .= "\n";
3608

    
3609
		return $pfq_rule;
3610
	}
3611

    
3612
        function build_javascript() {
3613
		return parent::build_javascript();
3614
	}
3615

    
3616

    
3617
        function build_form() { 
3618
		$form = "<tr><td valign=\"middle\" class=\"vncellreq\"><br/>";
3619
                $form .= gettext("Enable/Disable");
3620
                $form .= "</td><td class=\"vncellreq\">";
3621
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
3622
                if ($this->GetEnabled() == "on")
3623
                        $form .=  " checked=\"checked\"";
3624
                $form .= " /><span class=\"vexpl\"> " . gettext("Enable/Disable queue") . "</span>";
3625
                $form .= "</td></tr>";
3626
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\"><br/><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
3627
		$form .= "<td class=\"vncellreq\">";
3628
		$form .= "<input type=\"text\" id=\"newname\" name=\"newname\" value=\"";
3629
		$form .= $this->GetQname()."\" />";
3630
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"";
3631
		$form .= $this->GetQname()."\" />";
3632
		if ($this->GetNumber() > 0) {
3633
			$form .= "<input type=\"hidden\" id=\"number\" name=\"number\" value=\"";
3634
			$form .= $this->GetNumber()."\" />";
3635
		}
3636
		$form .= "</td></tr>";
3637
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Mask") . "</td>";
3638
		$form .= "<td class=\"vncellreq\">";
3639
		$form .= "<select name=\"mask\" id=\"mask\" class=\"formselect\" onchange=\"enable_maskbits();\" >";
3640
		$form .= "<option value=\"none\"";
3641
		$mask = $this->GetMask();
3642
		if ($mask['type'] == "none")
3643
			$form .= " selected=\"selected\"";
3644
		$form .= ">" . gettext("none") . "</option>";
3645
		$form .= "<option value=\"srcaddress\"";
3646
		if ($mask['type'] == "srcaddress")
3647
			$form .= " selected=\"selected\"";
3648
		$form .= ">" . gettext("Source addresses") . "</option>";
3649
		$form .= "<option value=\"dstaddress\"";
3650
		if ($mask['type'] == "dstaddress")
3651
			$form .= " selected=\"selected\"";
3652
		$form .= ">" . gettext("Destination addresses") . "</option>";
3653
		$form .= "</select>";
3654
		$form .= "&nbsp;slots<br/>";
3655
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' slots is chosen, \n"
3656
		      .  "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n"
3657
		      .  "be created for each source/destination IP address encountered, \n"
3658
		      .  "respectively. This makes it possible to easily specify bandwidth \n"
3659
		      .  "limits per host.") . "</span><br/>";
3660
		$form .= "255.255.255.255/&nbsp;<input type=\"text\" class=\"formfld unknown\" size=\"2\" id=\"maskbits\" name=\"maskbits\" value=\"";
3661
		if ($mask['type'] <> "none")
3662
		$form .= $mask['bits'];
3663
		$form .= "\"";
3664
		if ($mask['type'] == "none")
3665
			$form .= " disabled";
3666
		$form .= " />";
3667
		$form .= "&nbsp; IPV4 mask bits (1-32)<br/>";
3668
		$form .= "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/&nbsp;<input type=\"text\" class=\"formfld unknown\" size=\"2\" id=\"maskbitsv6\" name=\"maskbitsv6\" value=\"";
3669
		if ($mask['type'] <> "none")
3670
		$form .= $mask['bitsv6'];
3671
		$form .= "\"";
3672
		if ($mask['type'] == "none")
3673
			$form .= " disabled";
3674
		$form .= " />";
3675
		$form .= "&nbsp; IPV6 mask bits (1-128)<br/>";
3676
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' slots is chosen, \n"
3677
		      .  "leaving the mask bits blank will create one pipe per host. Otherwise specify \n"
3678
		      .  "the number of 'one' bits in the subnet mask used to group multiple hosts \n"
3679
		      .  "per queue.") . "</span>";
3680
		$form .= "</td></tr>";
3681
		$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Description") . "</td>";
3682
		$form .= "<td class=\"vncellreq\">";
3683
		$form .= "<input type=\"text\" id=\"description\" class=\"formfld unknown\" size=\"40\" name=\"description\" value=\"";
3684
		$form .= $this->GetDescription();
3685
		$form .= "\" />";
3686
		$form .= "<br/> <span class=\"vexpl\">";
3687
		$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3688
		$form .= "</td></tr>";
3689
		$form .= "<tr id=\"sprtable4\">";
3690
		$form .= "<td></td>";
3691
                $form .= "<td><div id=\"showadvancedboxspr\">";
3692
                $form .= "<p><input type=\"button\" onclick=\"show_source_port_range()\"";
3693
		$form .= " value=\"" . gettext("Show advanced options") . "\" />";
3694
                $form .= "</p></div></td></tr>";
3695
		$form .= "<tr style=\"display:none\" id=\"sprtable\">";
3696
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Weight") . "</td>";
3697
		$form .= "<td valign=\"middle\" class=\"vncellreq\">";
3698
		$form .= "<input name=\"weight\" type=\"text\" id=\"weight\" size=\"5\" value=\"";
3699
		$form .= $this->GetWeight() . "\" />";
3700
		$form .= "&nbsp;<br/> <span class=\"vexpl\">" . gettext("Hint: For queues under the same parent "
3701
		      .  "this specifies the share that a queue gets(values range from 1 to 100, you can leave it blank otherwise)") . "</span>";
3702
		$form .= "</td></tr>";
3703
		$form .= "<tr style=\"display:none\" id=\"sprtable1\">";
3704
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Packet loss rate") . "</td>";
3705
		$form .= "<td valign=\"middle\" class=\"vncellreq\">";
3706
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3707
		$form .= $this->GetPlr() . "\" />";
3708
		$form .= "&nbsp;<br/> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3709
			  .  "should specify 0 here (or leave the field empty). "
3710
			  .  "A value of 0.001 means one packet in 1000 gets dropped") . "</span>";
3711
		$form .= "</td></tr>";
3712
		$form .= "<tr style=\"display:none\" id=\"sprtable2\">";
3713
		$form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Queue Size") . "</td>";
3714
		$form .= "<td class=\"vncellreq\">";
3715
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3716
		$form .= $this->GetQlimit() . "\" />";
3717
		$form .= "&nbsp;slots<br/>";
3718
		$form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3719
			  .  "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, "
3720
			  .  "then they are delayed by value specified in the Delay field, and then they "
3721
			  .  "are delivered to their destination.") . "</span>";
3722
		$form .= "</td></tr>";
3723
		$form .= "<tr style=\"display:none\" id=\"sprtable5\">";
3724
                $form .= "<td valign=\"middle\" class=\"vncellreq\">" . gettext("Bucket Size") . "</td>";
3725
                $form .= "<td class=\"vncellreq\">";
3726
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3727
                $form .= $this->GetBuckets() . "\" />";
3728
                $form .= "&nbsp;" . gettext("slots") . "<br/>";
3729
                $form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3730
                      .  "should leave the field empty. It increases the hash size set.");
3731
                $form .= "</span></td></tr>";
3732

    
3733
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3734
		$form .= " value=\"" . $this->GetPipe() . "\" />";
3735

    
3736
		return $form;
3737

    
3738
	}
3739

    
3740
        function update_dn_data(&$data) { 
3741
		$this->ReadConfig($data);
3742
	}
3743

    
3744
	function wconfig() {
3745
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3746
            	if (!is_array($cflink))
3747
            		$cflink = array();
3748
		$cflink['name'] = $this->GetQname();
3749
		$cflink['number'] = $this->GetNumber();
3750
            	$cflink['qlimit'] = $this->GetQlimit();
3751
            	$cflink['description'] = $this->GetDescription();
3752
		$cflink['weight'] = $this->GetWeight();
3753
		$cflink['enabled'] = $this->GetEnabled();
3754
		$cflink['buckets'] = $this->GetBuckets();
3755
		$mask = $this->GetMask();
3756
		$cflink['mask'] = $mask['type'];
3757
		$cflink['maskbits'] = $mask['bits'];
3758
                $cflink['maskbitsv6'] = $mask['bitsv6'];
3759
	}
3760
}
3761

    
3762
// List of layer7 objects
3763
$layer7_rules_list = array();
3764

    
3765
class layer7 {
3766
    
3767
    var $rname; //alias
3768
    var $rdescription; //alias description
3769
    var $rport; //divert port
3770
    var $renabled; //rule enabled
3771
    var $rsets = array(); //array of l7 associations
3772
    
3773
    // Auxiliary functions
3774
    
3775
    function GetRName() {
3776
        return $this->rname;
3777
    }
3778
    function SetRName($rname) {
3779
        $this->rname = $rname;
3780
    }
3781
    function GetRDescription() {
3782
        return $this->rdescription;
3783
    }
3784
    function SetRDescription($rdescription) {
3785
        $this->rdescription = $rdescription;
3786
    }
3787
    function GetRPort() {
3788
        return $this->rport;
3789
    }
3790
    function SetRPort($rport) {
3791
        $this->rport = $rport;
3792
    }
3793
    function GetREnabled() {
3794
        return $this->renabled;
3795
    }
3796
    function SetREnabled($value) {
3797
        $this->renabled = $value;
3798
    }
3799
    function GetRl7() {
3800
        return $this->rsets;
3801
    }
3802
    function SetRl7($rsets) {
3803
        $this->rsets = $rsets;
3804
    }
3805
    
3806
    //Add a tuple (rule,sctructure,element) to the $rsets
3807
    
3808
    function add_rule($l7set) {
3809
       	$this->rsets[] = $l7set;
3810
    }
3811
    
3812
    // Build the layer7 rules
3813
    function build_l7_rules() {
3814
        if($this->GetREnabled() == "") {
3815
            return;
3816
        }
3817
        //$l7rules = "#" . $this->rdescription . "\n";
3818
        foreach ($this->rsets as $rl7) {
3819
            $l7rules .= $rl7->build_rules();
3820
        }
3821
        return $l7rules;
3822
    }
3823
    
3824
    // Read the config from array
3825
    function ReadConfig(&$qname, &$q) {
3826
        $this->SetRName($qname);
3827
        $this->SetREnabled($q['enabled']);
3828
        $this->SetRPort($q['divert_port']);
3829
        if(isset($q['description']) && $q['description'] <> "")
3830
            $this->SetRDescription($q['description']);
3831
        $rsets = $q['l7rules'];
3832
        //Put individual rules in the array
3833
	if(is_array($rsets)) {
3834
	    $this->rsets = array(); // XXX: ugly hack
3835
	    foreach($rsets as $l7r) {
3836
	        $l7obj = new l7rule();
3837
	        $l7obj->SetRProtocol($l7r['protocol']);
3838
	        $l7obj->SetRStructure($l7r['structure']);
3839
	        $l7obj->SetRBehaviour($l7r['behaviour']);
3840
	        $this->add_rule($l7obj);
3841
	    }
3842
	}
3843
    }
3844
    
3845
    //Generate a random port for the divert socket
3846
    function gen_divert_port() {
3847
        $dports = get_divert_ports(); //array of used ports
3848
	$divert_port = 1; // Initialize
3849
	while (($divert_port % 2) != 0 || in_array($divert_port, $dports)) {
3850
		$divert_port = rand(40000, 60000);
3851
	}
3852
        return $divert_port;
3853
    }
3854
    
3855
    //Helps building the left tree
3856
    function build_tree() {
3857
        $tree = " <li><a href=\"firewall_shaper_layer7.php?container=" . $this->GetRName() ."&amp;action=show\">"; 
3858
        $tree .= $this->GetRName() . "</a>";
3859
	$tree .= "</li>";
3860

    
3861
	return $tree;
3862
    }
3863
    
3864
    function build_form() {
3865
        $form = "<tr><td valign=\"middle\" class=\"vncellreq\"><br/>";
3866
	$form .= gettext("Enable/Disable");
3867
	$form .= "</td><td class=\"vncellreq\">";
3868
	$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\" ";
3869
	if ($this->GetREnabled() == "on") {
3870
       	    $form .=  "checked=\"checked\"";
3871
	}
3872
	$form .= " /><span class=\"vexpl\"> " . gettext("Enable/Disable layer7 Container") . "</span>";
3873
	$form .= "</td></tr>";
3874
        $form .= "<tr><td valign=\"middle\" class=\"vncellreq\"><br/><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
3875
	$form .= "<td class=\"vncellreq\">";
3876
	$form .= "<input type=\"text\" id=\"container\" name=\"container\" value=\"";
3877
	$form .= $this->GetRName()."\" />";
3878
	$form .= "</td></tr>";
3879
	$form .= "<tr><td valign=\"middle\" class=\"vncellreq\">" . gettext("Description") . "</td>";
3880
	$form .= "<td class=\"vncellreq\">";
3881
	$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"40\" id=\"description\" name=\"description\" value=\"";
3882
	$form .= $this->GetRDescription();
3883
	$form .= "\" />";
3884
	$form .= "<br/> <span class=\"vexpl\">";
3885
	$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3886
	$form .= "</td></tr>";
3887

    
3888
	return $form;
3889
    }
3890
    
3891
    //Write the setting to the $config array
3892
    function wconfig() {
3893
	global $config;
3894

    
3895
	if(!is_array($config['l7shaper']['container'])) {
3896
		$config['l7shaper']['container'] = array();
3897
	}
3898
        //
3899
        $cflink =& get_l7c_reference_to_me_in_config($this->GetRName());
3900
	// Test if this rule does exists already
3901
	if(!$cflink) {
3902
		$cflink =& $config['l7shaper']['container'][];
3903
	}
3904
	$cflink['name'] = $this->GetRName();
3905
        $cflink['enabled'] = $this->GetREnabled();
3906
        $cflink['description'] = $this->GetRDescription();
3907
        $cflink['divert_port'] = $this->GetRPort();
3908
        
3909
	//Destroy previously existent rules
3910
	if(is_array($cflink['rules'])) {
3911
		unset($cflink['l7rules']);
3912
	}
3913

    
3914
        $cflink['l7rules'] = array();
3915

    
3916
        $i = 0;
3917
        foreach($this->rsets as $rulel7) {
3918
            $cflink['l7rules'][$i]['protocol'] = $rulel7->GetRProtocol();
3919
            $cflink['l7rules'][$i]['structure'] = $rulel7->GetRStructure();
3920
            $cflink['l7rules'][$i]['behaviour'] = $rulel7->GetRBehaviour();
3921
            $i++;
3922
        }
3923
    }
3924
    
3925
    //This function is necessary to help producing the overload options for keep state
3926
    function get_unique_structures() {
3927
        
3928
        $unique_structures = array("action" => false, "dummynet" => false, "altq" => false);
3929
        foreach($this->rsets as $l7rule) {
3930
		if($l7rule->GetRStructure() == "action")
3931
			$unique_structures['action'] = true;
3932
		else if($l7rule->GetRStructure() == "limiter")
3933
			$unique_structures['dummynet'] = true;
3934
		else
3935
			$unique_structures['altq'] = true;
3936
        }
3937
	//Delete non used structures so we don't have to check this in filter.inc
3938
	foreach($unique_structures as $key => $value)
3939
		if(!$value)
3940
			unset($unique_structures[$key]);
3941
        return $unique_structures;
3942
    }
3943
    
3944
    function validate_input($data, &$input_errors) {
3945
	$reqdfields[] = "container";
3946
	$reqdfieldsn[] = gettext("Name");
3947

    
3948
	shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
3949
        
3950
        if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['container']))
3951
            $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
3952
    }
3953
    
3954
    function delete_l7c() {
3955
	mwexec("/bin/pkill -f 'ipfw-classifyd .* -p ". $this->GetRPort() . "'", true);
3956
	unset_l7_object_by_reference($this->GetRName());
3957
	cleanup_l7_from_rules($this->GetRName());
3958
    }
3959
}
3960

    
3961
class l7rule {
3962
    
3963
    var $rprotocol; //protocol
3964
    var $rstructure; //action, limiter, queue
3965
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3966
    
3967
    //Auxiliary Functions
3968
    
3969
    function GetRProtocol() {
3970
        return $this->rprotocol;
3971
    }
3972
    function SetRProtocol($rprotocol) {
3973
        $this->rprotocol = $rprotocol;
3974
    }
3975
    function GetRStructure() {
3976
        return $this->rstructure;
3977
    }
3978
    function SetRStructure($rstructure) {
3979
        $this->rstructure = $rstructure;
3980
    }
3981
    function GetRBehaviour() {
3982
        return $this->rbehaviour;
3983
    }
3984
    function SetRBehaviour($rbehaviour) {
3985
        $this->rbehaviour = $rbehaviour;
3986
    }
3987
    
3988
    //XXX Do we need to test any particularity for AltQ queues?
3989
    function build_rules() {
3990
	global $dummynet_pipe_list;
3991
	switch ($this->GetRStructure()) {
3992
		case "limiter":
3993
			read_dummynet_config();
3994
			$dn_list =& get_unique_dnqueue_list();
3995
			$found = false;
3996
			if(is_array($dn_list)) {
3997
				foreach($dn_list as $key => $value) {
3998
					if($key == $this->GetRBehaviour()) {
3999
						if($value[0] == "?")
4000
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
4001
						else
4002
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
4003
						$found = true;
4004
					}
4005
					if($found)
4006
						break;
4007
				}
4008
			}
4009
			break;
4010
		default: //This is for action and for altq
4011
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
4012
			break;
4013
	}
4014
        return $l7rule;
4015
    }
4016
}
4017

    
4018
/*
4019
 * This function allows to return an array with all the used divert socket ports
4020
 */
4021
function get_divert_ports() {
4022
    global $layer7_rules_list;
4023
    $dports = array();
4024
    
4025
    foreach($layer7_rules_list as $l7r)
4026
        $dports[] = $l7r->GetRPort();
4027
    
4028
    return $dports;
4029
}
4030

    
4031
function &get_l7c_reference_to_me_in_config(&$name) {
4032
	global $config;
4033

    
4034
	$ptr = NULL;
4035

    
4036
	if(is_array($config['l7shaper']['container'])) {
4037
		foreach($config['l7shaper']['container'] as $key => $value) {
4038
			if($value['name'] == $name)
4039
				$ptr =& $config['l7shaper']['container'][$key];
4040
		}
4041
	}	
4042
	return $ptr;
4043
// $ptr can be null. has to be checked later
4044
}
4045

    
4046
function unset_l7_object_by_reference(&$name) {
4047
	global $config;
4048
        
4049
	if(is_array($config['l7shaper']['container'])) {
4050
		foreach($config['l7shaper']['container'] as $key => $value) {
4051
			if($value['name'] == $name) {
4052
				unset($config['l7shaper']['container'][$key]['l7rules']);
4053
				unset($config['l7shaper']['container'][$key]);
4054
				break;
4055
			}
4056
		}
4057
	}
4058
}
4059

    
4060
function read_layer7_config() {
4061
    global $layer7_rules_list, $config;
4062
    
4063
    $l7cs = &$config['l7shaper']['container'];
4064
    
4065
    $layer7_rules_list = array();
4066
    
4067
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
4068
	return;
4069
    
4070
    foreach ($l7cs as $conf) {
4071
	if (empty($conf['name']))
4072
		continue; /* XXX: grrrrrr at php */ 
4073
        $root =& new layer7();
4074
        $root->ReadConfig($conf['name'],$conf);
4075
        $layer7_rules_list[$root->GetRName()] = &$root;
4076
    }
4077
}
4078

    
4079
function generate_layer7_files() {
4080
    global $layer7_rules_list, $g;
4081
    
4082
    read_layer7_config();
4083
    
4084
    if (!empty($layer7_rules_list)) {
4085
	if (!is_module_loaded("ipdivert.ko"))
4086
		mwexec("/sbin/kldload ipdivert.ko");
4087

    
4088
	mwexec("rm -f {$g['tmp_path']}/*.l7");
4089
    }
4090
    
4091
    foreach($layer7_rules_list as $l7rules) {
4092
        if($l7rules->GetREnabled()) {
4093
            $filename = $l7rules->GetRName() . ".l7";
4094
            $path = "{$g['tmp_path']}/" . $filename;
4095
        
4096
            $rules = $l7rules->build_l7_rules();
4097
        
4098
            $fp = fopen($path,'w');
4099
            fwrite($fp,$rules);
4100
            fclose($fp);
4101
        }
4102
    }
4103
}
4104

    
4105
function layer7_start_l7daemon() {
4106
    global $layer7_rules_list, $g;
4107

    
4108
    /*
4109
     * XXX: ermal - Needed ?!
4110
     * read_layer7_config();
4111
     */
4112

    
4113
    foreach($layer7_rules_list as $l7rules) {
4114
        if($l7rules->GetREnabled()) {
4115
            $filename = $l7rules->GetRName() . ".l7";
4116
            $path = "{$g['tmp_path']}/" . $filename;
4117

    
4118
	    unset($l7pid);
4119
	    /* Only reread the configuration rather than restart to avoid losing information. */
4120
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
4121
	    if (count($l7pid) > 0) {
4122
		log_error(sprintf(gettext("Sending HUP signal to %s"), $l7pid[0]));
4123
		mwexec("/bin/kill -HUP {$l7pid[0]}");
4124
	    } else {
4125
		// XXX: Hardcoded number of packets to garbage collect and queue length..
4126
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 8 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
4127
		mwexec_bg($ipfw_classifyd_init);
4128
	    }
4129
        }
4130
    }
4131
}
4132

    
4133
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
4134
function generate_protocols_array() {
4135
	$protocols = return_dir_as_array("/usr/local/share/protocols");
4136
	$protocols_new = array();
4137
	if(is_array($protocols)) {
4138
		foreach($protocols as $key => $proto) {
4139
			if (strstr($proto, ".pat"))
4140
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
4141
		}
4142
		sort($protocols_new);
4143
	}		
4144
	return $protocols_new;
4145
}
4146

    
4147
function get_l7_unique_list() {
4148
	global $layer7_rules_list;
4149

    
4150
	$l7list = array();
4151
	if(is_array($layer7_rules_list)) 
4152
		foreach($layer7_rules_list as $l7c)
4153
			if($l7c->GetREnabled())
4154
				$l7list[] = $l7c->GetRName();
4155

    
4156
	return $l7list;
4157
}
4158

    
4159
// Disable a removed l7 container from the filter
4160
function cleanup_l7_from_rules(&$name) {
4161
	global $config;
4162

    
4163
	if(is_array($config['filter']['rule']))
4164
		foreach ($config['filter']['rule'] as $key => $rule) {
4165
			if ($rule['l7container'] == $name)
4166
				unset($config['filter']['rule'][$key]['l7container']);
4167
		}
4168
}
4169

    
4170
function get_dummynet_name_list() {
4171

    
4172
	$dn_name_list =& get_unique_dnqueue_list();
4173
	$dn_name = array();
4174
	if(is_array($dn_name_list))
4175
		foreach($dn_name_list as $key => $value)
4176
			$dn_name[] = $key;
4177

    
4178
	return $dn_name;
4179

    
4180
}
4181

    
4182
function get_altq_name_list() {
4183
	$altq_name_list =& get_unique_queue_list();
4184
	$altq_name = array();
4185
	if(is_array($altq_name_list))
4186
		foreach($altq_name_list as $key => $aqobj)
4187
			$altq_name[] = $key;
4188

    
4189
	return $altq_name;
4190
}
4191

    
4192
/*
4193
 * XXX: TODO Make a class shaper to hide all these function
4194
 * from the global namespace.
4195
 */
4196

    
4197
/* 
4198
 * This is a layer violation but for now there is no way 
4199
 * i can find to properly do this with PHP.
4200
 */
4201
function altq_get_default_queue($interface) {
4202
	global $altq_list_queues;
4203

    
4204
	$altq_tmp = $altq_list_queues[$interface];
4205
	if ($altq_tmp)
4206
		return $altq_tmp->GetDefaultQueuePresent(); 
4207
	else
4208
		return false;
4209
}
4210

    
4211
function altq_check_default_queues() {
4212
	global $altq_list_queues;
4213

    
4214
	$count = 0;
4215
	if (is_array($altq_list_queues)) {
4216
		foreach($altq_list_queues as $altq) {
4217
			if ($altq->GetDefaultQueuePresent())
4218
				$count++;
4219
		}
4220
	}
4221
	else  $count++;;
4222

    
4223
	return 0;
4224
}
4225

    
4226
function &get_unique_queue_list() {
4227
	global $altq_list_queues;
4228

    
4229
	$qlist = array();
4230
	if (is_array($altq_list_queues)) {
4231
		foreach ($altq_list_queues as $altq) {
4232
			if ($altq->GetEnabled() == "")
4233
				continue;
4234
			$tmplist =& $altq->get_queue_list();
4235
			foreach ($tmplist as $qname => $link) {
4236
				if ($link->GetEnabled() <> "")
4237
					$qlist[$qname] = $link;	
4238
			}
4239
		}
4240
	}
4241
	return $qlist;
4242
}
4243

    
4244
function &get_unique_dnqueue_list() {
4245
	global $dummynet_pipe_list;
4246

    
4247
	$qlist = array();
4248
	if (is_array($dummynet_pipe_list)) {
4249
		foreach ($dummynet_pipe_list as $dn) {
4250
			if ($dn->GetEnabled() == "")
4251
				continue;
4252
			$tmplist =& $dn->get_queue_list();
4253
			foreach ($tmplist as $qname => $link) {
4254
				$qlist[$qname] = $link;	
4255
			}
4256
		}
4257
	}
4258
	return $qlist;
4259
}
4260

    
4261
function ref_on_altq_queue_list($parent, $qname) {
4262
	if (isset($GLOBALS['queue_list'][$qname]))
4263
		$GLOBALS['queue_list'][$qname]++;
4264
	else
4265
		$GLOBALS['queue_list'][$qname] = 1;
4266

    
4267
	unref_on_altq_queue_list($parent);
4268
}
4269

    
4270
function unref_on_altq_queue_list($qname) {
4271
	$GLOBALS['queue_list'][$qname]--;
4272
	if ($GLOBALS['queue_list'][$qname] <= 1)
4273
		unset($GLOBALS['queue_list'][$qname]);	
4274
}
4275

    
4276
function read_altq_config() {
4277
	global $altq_list_queues, $config;
4278
	$path = array();
4279

    
4280
	if (!is_array($config['shaper']))
4281
		$config['shaper'] = array();
4282
	if (!is_array($config['shaper']['queue']))
4283
		$config['shaper']['queue'] = array();
4284
	$a_int = &$config['shaper']['queue'];
4285

    
4286
	$altq_list_queues = array();
4287

    
4288
	if (!is_array($config['shaper']['queue']))
4289
		return;
4290

    
4291
	foreach ($a_int as $key => $conf) {
4292
		$int = $conf['interface'];
4293
		$root =& new altq_root_queue();
4294
		$root->SetInterface($int);
4295
		$altq_list_queues[$root->GetInterface()] = &$root;
4296
		$root->ReadConfig($conf);
4297
		array_push($path, $key);
4298
		$root->SetLink($path);
4299
		if (is_array($conf['queue'])) {
4300
			foreach ($conf['queue'] as $key1 => $q) {
4301
				array_push($path, $key1);
4302
				/* 
4303
				 * XXX: we completely ignore errors here but anyway we must have 
4304
				 *	checked them before so no harm should be come from this.
4305
				 */
4306
				$root->add_queue($root->GetInterface(), $q, $path, $input_errors);
4307
				array_pop($path);
4308
			} 	
4309
		}
4310
		array_pop($path);
4311
	}
4312
}
4313

    
4314
function read_dummynet_config() {
4315
	global $dummynet_pipe_list, $config;
4316
	$path = array();
4317

    
4318
	if (!is_array($config['dnshaper']))
4319
		$config['dnshaper'] = array();
4320
	if (!is_array($config['dnshaper']['queue']))
4321
		$config['dnshaper']['queue'] = array();
4322
	$a_int = &$config['dnshaper']['queue'];
4323

    
4324
	$dummynet_pipe_list = array();
4325

    
4326
	if (!is_array($config['dnshaper']['queue'])
4327
		|| !count($config['dnshaper']['queue']))
4328
		return;
4329

    
4330
	foreach ($a_int as $key => $conf) {
4331
		if (empty($conf['name']))
4332
			continue; /* XXX: grrrrrr at php */ 
4333
		$root =& new dnpipe_class();
4334
		$root->ReadConfig($conf);
4335
		$dummynet_pipe_list[$root->GetQname()] = &$root;
4336
		array_push($path, $key);
4337
		$root->SetLink($path);
4338
		if (is_array($conf['queue'])) {
4339
			foreach ($conf['queue'] as $key1 => $q) {
4340
				array_push($path, $key1);
4341
				/* 
4342
				 * XXX: we completely ignore errors here but anyway we must have 
4343
				 *	checked them before so no harm should be come from this.
4344
				 */	
4345
				$root->add_queue($root->GetQname(), $q, $path, $input_errors);
4346
				array_pop($path);
4347
			} 	
4348
		}
4349
		array_pop($path);
4350
	}
4351
}
4352

    
4353
function get_interface_list_to_show() {
4354
	global $altq_list_queues, $config;
4355
	global $shaperIFlist;
4356

    
4357
	$tree = "";
4358
	foreach ($shaperIFlist as $shif => $shDescr) {
4359
		if ($altq_list_queues[$shif]) {
4360
			continue;
4361
		} else  {
4362
			if (!is_altq_capable(get_real_interface($shif)))
4363
				continue;
4364
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&amp;action=add\">".$shDescr."</a></li>";
4365
		}
4366
	}
4367

    
4368
	return $tree;
4369
}
4370

    
4371
function filter_generate_altq_queues() {
4372
	global $altq_list_queues;
4373

    
4374
	read_altq_config();
4375

    
4376
	$altq_rules = "";
4377
	foreach ($altq_list_queues as $altq) 
4378
		$altq_rules .= $altq->build_rules();
4379

    
4380
	return $altq_rules;
4381
}
4382

    
4383
function dnqueue_find_nextnumber() {
4384
	global $dummynet_pipe_list;
4385

    
4386
	$dnused = array();
4387
	if (is_array($dummynet_pipe_list)) {
4388
		foreach ($dummynet_pipe_list as $dn) {
4389
			$tmplist =& $dn->get_queue_list();
4390
			foreach ($tmplist as $qname => $link) {
4391
				if ($link[0] == "?")
4392
					$dnused[$qname] = substr($link, 1);
4393
			}
4394
		}
4395
	}
4396

    
4397
	sort($dnused, SORT_NUMERIC);
4398
	$dnnumber = 0;
4399
	$found = false;
4400
	foreach ($dnused as $dnnum) {
4401
		if (($dnnum - $dnnumber) > 1) {
4402
			$dnnumber = $dnnum + 1;
4403
			$found = true;
4404
			break;
4405
		} else
4406
			$dnnumber = $dnnum;
4407
	}
4408

    
4409
	if ($found == false)
4410
		$dnnumber++;
4411

    
4412
	unset($dnused, $dnnum, $found);
4413
	return $dnnumber;
4414
}
4415

    
4416
function dnpipe_find_nextnumber() {
4417
	global $dummynet_pipe_list;
4418

    
4419
	$dnused = array();
4420
	foreach ($dummynet_pipe_list as $dn)
4421
		$dnused[] = $dn->GetNumber();
4422

    
4423
	sort($dnused, SORT_NUMERIC);
4424
	$dnnumber = 0;
4425
	$found = false;
4426
	foreach ($dnused as $dnnum) {
4427
		if (($dnnum - $dnnumber) > 1) {
4428
			$dnnumber = $dnnum + 1;
4429
			$found = true;
4430
			break;
4431
		} else
4432
			$dnnumber = $dnnum;
4433
	}
4434

    
4435
	if ($found == false)
4436
		$dnnumber++;
4437

    
4438
	unset($dnused, $dnnum, $found);
4439
	return $dnnumber;
4440
}
4441

    
4442
function filter_generate_dummynet_rules() {
4443
	global $g, $dummynet_pipe_list;
4444

    
4445
	read_dummynet_config();
4446

    
4447
	if (!empty($dummynet_pipe_list)) {
4448
		if (!is_module_loaded("dummynet.ko")) {
4449
			mwexec("/sbin/kldload dummynet");
4450
			mwexec("/sbin/sysctl net.inet.ip.dummynet.io_fast=1 net.inet.ip.dummynet.hash_size=256");
4451
		}
4452
	}
4453

    
4454
	$dn_rules = "";
4455
	foreach ($dummynet_pipe_list as $dn) 
4456
		$dn_rules .= $dn->build_rules();
4457

    
4458
	if (!empty($dn_rules)) {
4459
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
4460
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
4461
	}
4462
}
4463

    
4464
function build_iface_without_this_queue($iface, $qname) {
4465
	global $g, $altq_list_queues;
4466
	global $shaperIFlist;
4467

    
4468
	$altq =& $altq_list_queues[$iface];
4469
	if ($altq)
4470
		$scheduler = ": " . $altq->GetScheduler();
4471
	$form = "<tr><td width=\"20%\" >";
4472
	$form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&amp;queue=" . $iface."&amp;action=show\">". $shaperIFlist[$iface] . $scheduler."</a>";
4473
	$form .= "</td></tr>";
4474
	$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
4475
	$form .= "<a href=\"firewall_shaper_queues.php?interface=";
4476
	$form .= $iface . "&amp;queue=". $qname . "&amp;action=add\">";
4477
	$form .= "<img src=\"";
4478
	$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
4479
	$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\" alt=\"clone\" />";
4480
	$form .= gettext(" Clone shaper/queue on this interface") . "</a></td></tr>";
4481

    
4482
	return $form;
4483

    
4484
}
4485

    
4486

    
4487
$default_shaper_msg =  "<tr><td align=\"center\" width=\"80%\">";
4488
$default_shaper_msg .= "<span class=\"vexpl\"><strong><b>" . sprintf(gettext("Welcome to the %s Traffic Shaper."), $g['product_name']) . "</b><br />";
4489
$default_shaper_msg .= gettext("The tree on the left helps you navigate through the queues <br />"
4490
                    .  "buttons at the bottom represent queue actions and are activated accordingly.");
4491
$default_shaper_msg .= "</strong></span>";
4492
$default_shaper_msg .= "</td></tr>";
4493

    
4494
$dn_default_shaper_msg =  "<tr><td align=\"center\" width=\"80%\">";
4495
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><b>" . sprintf(gettext("Welcome to the %s Traffic Shaper."), $g['product_name']) . "</b><br />";
4496
$dn_default_shaper_msg .= gettext("The tree on the left helps you navigate through the queues <br />"
4497
                       .  "buttons at the bottom represent queue actions and are activated accordingly.");
4498
$dn_default_shaper_msg .= "</strong></span>";
4499
$dn_default_shaper_msg .= "</td></tr>";
4500

    
4501
?>
(50-50/66)