Project

General

Profile

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

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

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

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

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

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

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

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

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

    
47
	return $ptr;
48
}
49

    
50
function unset_object_by_reference(&$mypath) 
51
{
52
	global $config;
53

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

    
61
function &get_dn_reference_to_me_in_config(&$mypath) 
62
{
63
	global $config;
64

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

    
70
	return $ptr;
71
}
72

    
73
function unset_dn_object_by_reference(&$mypath) 
74
{
75
	global $config;
76

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

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

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

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

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

    
163
function get_interface_bandwidth($object) 
164
{
165
	global $altq_list_queues;
166

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

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

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

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

    
198
function cleanup_queue_from_rules($queue) 
199
{
200
	global $config;
201

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

    
210
function cleanup_dnqueue_from_rules($queue) 
211
{
212
	global $config;
213

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

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

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

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

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

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

    
380
	function &get_queue_list($q = null) {
381
		$qlist = array();
382

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

    
391
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
392

    
393
		if (!is_array($this->queues))
394
			$this->queues = array();
395

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

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

    
446
		return $q;
447
	}
448

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

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

    
475
	function build_tree() {
476
		global $shaperIFlist;
477

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

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

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

    
549
	function build_javascript() {
550
		$javascript = "<script type=\"text/javascript\">";
551
		$javascript .= "function mySuspend() {";
552
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);";
553
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';";
554
		$javascript .= "else if (document.all)";
555
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';";
556
		$javascript .= "}";
557

    
558
		$javascript .= "function myResume() {";
559
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)";
560
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';";
561
		$javascript .= "else if (document.all)";
562
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';";
563
		$javascript .= "}";
564
		$javascript .= "</script>";
565

    
566
		return $javascript;
567
	}
568
	
569
	function build_shortform() {
570
		global $g;
571

    
572
		$altq =& $this;
573
		if ($altq)
574
			$scheduler = ": " . $altq->GetScheduler();
575
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
576
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=". $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
577
		$form .= "</td></tr>";
578
		$form .= "<tr>";
579
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
580
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
581
		$form .= "</td><td width=\"50%\"></td></tr>";
582
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
583
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
584
		$form .= $this->GetInterface() . "&queue=";
585
		$form .= $this->GetQname() . "&action=delete\">";
586
		$form .= "<img src=\"";
587
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
588
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Disable shaper on interface\">";
589
		$form .= "<span>Disable shaper on interface</span></a></td></tr>";
590

    
591
		return $form;
592

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

    
680

    
681
		return $form;
682
	}
683

    
684
	function update_altq_queue_data(&$data) { 
685
		$this->ReadConfig($data);
686
	}
687
	
688
	/*
689
	 * Should call on each of it queues and subqueues
690
	 * the same function much like build_rules();
691
	 */
692
	function wconfig() { 
693
		$cflink = &get_reference_to_me_in_config($this->GetLink());
694
		if (!is_array($cflink))
695
			$cflink = array();
696
		$cflink['interface'] = $this->GetInterface();	
697
		$cflink['name'] = $this->GetQname();
698
		$cflink['scheduler'] = $this->GetScheduler();
699
		$cflink['bandwidth'] = $this->GetBandwidth();
700
		$cflink['bandwidthtype'] = $this->GetBwscale();
701
		$cflink['qlimit'] = trim($this->GetQlimit());
702
		if (empty($cflink['qlimit']))
703
			unset($cflink['qlimit']);
704
		$cflink['tbrconfig'] = trim($this->GetTbrConfig());
705
		if (empty($cflink['tbrconfig']))
706
			unset($cflink['tbrconfig']);
707
		$cflink['enabled'] = $this->GetEnabled();
708
		if (empty($cflink['enabled']))
709
			unset($cflink['enabled']);
710
	}
711

    
712
}
713

    
714
class priq_queue {
715
	var $qname;
716
	var $qinterface; 
717
	var $qlimit;
718
	var $qpriority;
719
	var $description;
720
	var $isparent;
721
	var $qbandwidth;
722
	var $qbandwidthtype;
723
	var $qdefault = "";
724
	var $qrio = "";
725
	var $qred = "";
726
	var $qecn = "";
727
	var $qack;
728
	var $qenabled = "";
729
	var $qparent;
730
	var $link;
731
	var $available_bw; /* in b/s */
732

    
733
	/* This is here to help with form building and building rules/lists */
734
		var $subqueues = array();
735

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

    
847
	function build_javascript() {
848
		$javascript = "<script type=\"text/javascript\">";
849
		$javascript .= "function mySuspend() { \n";
850
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);\n";
851
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
852
		$javascript .= "else if (document.all)\n";
853
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
854
		$javascript .= "}\n";
855

    
856
		$javascript .= "function myResume() {\n";
857
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
858
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
859
		$javascript .= "else if (document.all)\n";
860
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
861
		$javascript .= "}\n";
862
		$javascript .= "</script>";
863
		
864
		return $javascript;
865
	}
866
	
867
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
868

    
869
	/* 
870
	 * Currently this will not be called unless we decide to clone a whole 
871
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
872
	 */
873
	 function copy_queue($interface, &$cflink) {
874

    
875
 		$cflink['name'] = $this->GetQname();
876
                $cflink['interface'] = $interface;
877
                $cflink['qlimit'] = $this->GetQlimit();
878
                $cflink['priority'] = $this->GetQpriority();
879
                $cflink['description'] = $this->GetDescription();
880
                $cflink['enabled'] = $this->GetEnabled();
881
                $cflink['default'] = $this->GetDefault();
882
                $cflink['red'] = $this->GetRed();
883
                $cflink['rio'] = $this->GetRio();
884
                $cflink['ecn'] = $this->GetEcn();
885

    
886
                if (is_array($this->subqueues)) {
887
                        $cflinkp['queue'] = array();
888
                        foreach ($this->subqueues as $q) {
889
				 $cflink['queue'][$q->GetQname()] = array();
890
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
891
			}
892
                }
893

    
894
	 }
895

    
896
	function clean_queue($sched) {
897
		clean_child_queues($sched, $this->GetLink());
898
		if (is_array($this->subqueues)) {
899
			foreach ($this->subqueues as $q)
900
				$q->clean_queue($sched);
901
		}
902
	}
903

    
904
        function &get_queue_list(&$qlist) {
905
		$qlist[$this->GetQname()] = & $this;
906
		if (is_array($this->subqueues)) {
907
			foreach ($this->subqueues as $queue)
908
				$queue->get_queue_list($qlist);
909
		}
910
	}
911

    
912
	function delete_queue() {
913
		unref_on_altq_queue_list($this->GetQname());
914
		if ($this->GetDefault())
915
				altq_set_default_queue($this->GetInterface(), "false");
916
		cleanup_queue_from_rules($this->GetQname());
917
		unset_object_by_reference($this->GetLink());
918
	}
919
	
920
	function delete_all() {
921
                if (count($this->subqueues)) {
922
                        foreach ($this->subqueues as $q) {
923
                                $q->delete_all();
924
                                unset_object_by_reference($q->GetLink());
925
                                unset($q);
926
                        }
927
                        unset($this->subqueues);
928
                }
929
        }
930

    
931
	 function &find_queue($interface, $qname) { 
932
		if ($qname == $this->GetQname())
933
			return $this; 
934
	}
935
	
936
	function find_parentqueue($interface, $qname) { return; }
937
		
938
	function validate_input($data, &$input_errors) {
939
	
940
		$reqdfields[] = "name";
941
		$reqdfieldsn[] = gettext("Name");
942
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
943

    
944
		if ($data['priority'] && (!is_numeric($data['priority'])
945
						|| ($data['priority'] < 1) || ($data['priority'] > 15))) {
946
					$input_errors[] = gettext("The priority must be an integer between 1 and 15.");
947
		}
948
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
949
				$input_errors[] = gettext("Queue limit must be an integer");
950
		if ($data['qlimit'] < 0)
951
				$input_errors[] = gettext("Queue limit must be positive");
952
		if (!preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
953
			 $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
954
		
955
	}
956

    
957
	function ReadConfig(&$q) {
958
		if (isset($q['name']))
959
				$this->SetQname($q['name']);
960
		if (isset($q['interface']))
961
				$this->SetInterface($q['interface']);
962
		$this->SetBandwidth($q['bandwidth']);
963
		if ($q['bandwidthtype'] <> "")
964
			$this->SetBwscale($q['bandwidthtype']);
965
		if (!empty($q['qlimit']))
966
			$this->SetQlimit($q['qlimit']);
967
		else
968
			$this->SetQlimit(""); // Default
969
		if (!empty($q['priority']))
970
			$this->SetQPriority($q['priority']);
971
		else
972
			$this->SetQpriority("");
973
		if (!empty($q['description']))
974
			$this->SetDescription($q['description']);
975
		else
976
			$this->SetDescription("");
977
		if (!empty($q['red']))
978
			$this->SetRed($q['red']);
979
		else
980
			$this->SetRed();
981
		if (!empty($q['rio']))
982
			$this->SetRio($q['rio']);
983
		else
984
			$this->SetRio();
985
		if (!empty($q['ecn']))
986
			$this->SetEcn($q['ecn']);
987
		else
988
			$this->SetEcn();
989
		if (!empty($q['default']))
990
			$this->SetDefault($q['default']);
991
		else
992
			$this->SetDefault();
993
		if (!empty($q['enabled']))
994
			$this->SetEnabled($q['enabled']);
995
		else
996
			$this->SetEnabled("");
997

    
998
	}
999

    
1000
	function build_tree() {
1001
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
1002
		$tree .= "\" ";
1003
		$tmpvalue = $this->GetDefault();
1004
		if (!empty($tmpvalue))
1005
			$tree .= " class=\"navlnk\"";
1006
		$tree .= " >" . $this->GetQname() . "</a>";
1007
		/* 
1008
		 * Not needed here!
1009
		 * if (is_array($queues) {
1010
		 *	  $tree .= "<ul>";
1011
		 *	  foreach ($q as $queues) 
1012
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1013
		 *	  endforeach	
1014
		 *	  $tree .= "</ul>";
1015
		 * }
1016
		 */
1017

    
1018
		$tree .= "</li>"; 
1019

    
1020
		return $tree;
1021
	}
1022
		
1023
	/* Should return something like:
1024
	 * queue $qname on $qinterface bandwidth ....
1025
	 */
1026
	function build_rules() {
1027
		$pfq_rule = " queue ". $this->qname;
1028
		if ($this->GetInterface())
1029
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1030
		$tmpvalue = $this->GetQpriority();
1031
		if (!empty($tmpvalue))
1032
			$pfq_rule .= " priority ".$this->GetQpriority();
1033
		$tmpvalue = $this->GetQlimit();
1034
		if (!empty($tmpvalue))
1035
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1036
		if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
1037
			$pfq_rule .= " priq ( ";
1038
			$tmpvalue = $this->GetRed();
1039
			if (!empty($tmpvalue)) {
1040
				$comma = 1;
1041
				$pfq_rule .= " red ";
1042
			}
1043
			$tmpvalue = $this->GetRio();
1044
			if (!empty($tmpvalue)) {
1045
				if ($comma) 
1046
					$pfq_rule .= " ,";
1047
				$comma = 1;
1048
				$pfq_rule .= " rio ";
1049
			}
1050
			$tmpvalue = $this->GetEcn();
1051
			if (!empty($tmpvalue)) {
1052
				if ($comma) 
1053
					$pfq_rule .= " ,";
1054
				$comma = 1;
1055
				$pfq_rule .= " ecn ";
1056
			}
1057
			$tmpvalue = $this->GetDefault();
1058
			if (!empty($tmpvalue)) {
1059
				if ($comma)
1060
					$pfq_rule .= " ,";
1061
				$pfq_rule .= " default ";
1062
			}
1063
			$pfq_rule .= " ) ";
1064
		}
1065

    
1066
		$pfq_rule .= " \n";
1067

    
1068
		return $pfq_rule;
1069
	}
1070

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

    
1144
		return $form;
1145
	}
1146

    
1147
	function build_shortform() {
1148
		/* XXX: Hacks in site. Mostly layer violations!  */
1149
		global $g, $altq_list_queues;
1150

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

    
1183
	}
1184

    
1185
		function update_altq_queue_data(&$q) { 
1186
		$this->ReadConfig($q);
1187
	}
1188

    
1189
	function wconfig() {
1190
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1191
		if (!is_array($cflink))
1192
			$cflink = array();
1193
		$cflink['name'] = $this->GetQname();
1194
		$cflink['interface'] = $this->GetInterface();
1195
		$cflink['qlimit'] = trim($this->GetQlimit());
1196
		if (empty($cflink['qlimit']))
1197
			unset($cflink['qlimit']);
1198
		$cflink['priority'] = trim($this->GetQpriority());
1199
		if (empty($cflink['priority']))
1200
			unset($cflink['priority']);
1201
		$cflink['description'] = trim($this->GetDescription());
1202
		if (empty($cflink['description']))
1203
			unset($cflink['description']);
1204
		$cflink['enabled'] = trim($this->GetEnabled());
1205
		if (empty($cflink['enabled']))
1206
			unset($cflink['enabled']);
1207
		$cflink['default'] = trim($this->GetDefault());
1208
		if (empty($cflink['default']))
1209
			unset($cflink['default']);
1210
		$cflink['red'] = trim($this->GetRed());
1211
		if (empty($cflink['red']))
1212
			unset($cflink['red']);
1213
		$cflink['rio'] = trim($this->GetRio());
1214
		if (empty($cflink['rio']))
1215
			unset($cflink['rio']);
1216
		$cflink['ecn'] = trim($this->GetEcn());
1217
		if (empty($cflink['ecn']))
1218
			unset($cflink['ecn']);
1219
	}
1220
}
1221

    
1222
class hfsc_queue extends priq_queue {
1223
	/* realtime */
1224
	var $realtime;
1225
	var $r_m1;
1226
	var $r_d;
1227
	var $r_m2;
1228
	/* linkshare */
1229
	var $linkshare;
1230
	var $l_m1;
1231
	var $l_d;
1232
	var $l_m2;
1233
	/* upperlimit */
1234
	var $upperlimit;
1235
	var $u_m1;
1236
	var $u_d;
1237
	var $u_m2;
1238

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

    
1327
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1328

    
1329
		if (!is_array($this->subqueues))
1330
			$this->subqueues = array();
1331
		$q =& new hfsc_queue();
1332
		$q->SetInterface($this->GetInterface());
1333
		$q->SetParent(&$this);
1334
		$q->ReadConfig($qname);
1335
		$q->validate_input($qname, $input_errors);
1336
		if (count($input_errors)) {
1337
			return $q;
1338
		}
1339

    
1340
		$q->SetEnabled("on");
1341
		$q->SetLink($path);
1342
		switch ($q->GetBwscale()) {
1343
		case "%":
1344
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1345
			break;
1346
		default:
1347
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1348
			break;
1349
		}
1350
		$q->SetAvailableBandwidth($myBw);
1351
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1352

    
1353
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1354
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1355
		if (is_array($qname['queue'])) {
1356
			foreach ($qname['queue'] as $key1 => $que) {
1357
				array_push($path, $key1);
1358
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1359
				array_pop($path);
1360
			}
1361
		}
1362
	
1363
		return $q;
1364
	}
1365

    
1366
        function copy_queue($interface, &$cflink) {
1367

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

    
1451
		if (is_array($this->subqueues)) {
1452
			$cflinkp['queue'] = array();
1453
			foreach ($this->subqueues as $q) {
1454
				$cflink['queue'][$q->GetQname()] = array();
1455
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1456
			}
1457
		}
1458
	}
1459

    
1460
	function delete_queue() { 
1461
		unref_on_altq_queue_list($this->GetQname());
1462
		$tmpvalue = $this->GetDefault();
1463
		if (!empty($tmpvalue)) 
1464
			altq_set_default_queue($this->GetInterface(), "false");
1465
		cleanup_queue_from_rules($this->GetQname());
1466
		$parent =& $this->GetParent();
1467
		foreach ($this->subqueues as $q)  {
1468
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1469
			$q->delete_queue();
1470
		}
1471
		unset_object_by_reference($this->GetLink());
1472
	}
1473

    
1474
	/*
1475
	 * Should search even its children
1476
	 */
1477
	function &find_queue($interface, $qname) {
1478
		if ($qname == $this->GetQname()) 
1479
			return $this;
1480

    
1481
		foreach ($this->subqueues as $q) {
1482
			$result =& $q->find_queue("", $qname);
1483
			if ($result)
1484
				return $result;
1485
		}
1486
	}
1487

    
1488
	function &find_parentqueue($interface, $qname) {
1489
		if ($this->subqueues[$qname]) 
1490
			return $this;
1491
		foreach ($this->subqueues as $q) {
1492
			$result = $q->find_parentqueue("", $qname);
1493
			if ($result)
1494
				return $result;
1495
		}
1496
	}
1497
	
1498
	function validate_input($data, &$input_errors) {
1499
		parent::validate_input($data, $input_errors);
1500
		
1501
		$reqdfields[] = "bandwidth";
1502
		$reqdfieldsn[] = gettext("Bandwidth");
1503
		$reqdfields[] = "bandwidthtype";
1504
		$reqdfieldsn[] = gettext("Bandwidthtype");
1505

    
1506
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1507
		
1508
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1509
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1510
				$input_errors[] = gettext("Bandwidth must be an integer.");
1511

    
1512
			if ($data['bandwidth'] < 0)
1513
				$input_errors[] = gettext("Bandwidth cannot be negative.");
1514

    
1515
			if ($data['bandwidthtype'] == "%") {
1516
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1517
					$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
1518
			}
1519
		/*
1520
			$parent =& $this->GetParent();
1521
			switch ($data['bandwidthtype']) {
1522
			case "%":
1523
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1524
			default:
1525
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1526
				break;
1527
			}
1528
			if ($parent->GetAvailableBandwidth() < $myBw)
1529
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1530
		*/
1531
		}
1532

    
1533
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1534
			$input_errors[] = gettext("upperlimit service curve defined but missing (d) value");
1535
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1536
			$input_errors[] = gettext("upperlimit service curve defined but missing initial bandwidth (m1) value");
1537
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1538
			$input_errors[] = gettext("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1539
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1540
			$input_errors[] = gettext("upperlimit d value needs to be numeric");
1541
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1542
			$input_errors[] = gettext("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1543

    
1544
		/*
1545
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1546
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1547
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1548
			if (floatval($bw_1) < floatval($bw_2)) 
1549
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1550

    
1551
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1552
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1553
		}
1554
		*/
1555
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1556
			$input_errors[] = gettext("linkshare service curve defined but missing (d) value");
1557
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1558
			$input_errors[] = gettext("linkshare service curve defined but missing initial bandwidth (m1) value");
1559
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1560
			$input_errors[] = gettext("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1561
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1562
			$input_errors[] = gettext("linkshare d value needs to be numeric");
1563
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1564
			$input_errors[] = gettext("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1565
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1566
			$input_errors[] = gettext("realtime service curve defined but missing (d) value");
1567
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1568
			$input_errors[] = gettext("realtime service curve defined but missing initial bandwidth (m1) value");
1569

    
1570
		/*
1571
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1572
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1573
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1574
                	if (floatval($bw_1) < floatval($bw_2))
1575
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1576

    
1577
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1578
                        	$input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1579
		}
1580
		*/
1581

    
1582
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1583
			$input_errors[] = gettext("realtime m1 value needs to be Kb, Mb, Gb, or %");
1584
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1585
			$input_errors[] = gettext("realtime d value needs to be numeric");
1586
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1587
			$input_errors[] = gettext("realtime m2 value needs to be Kb, Mb, Gb, or %");
1588

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

    
1596
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1597
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1598
		}
1599
		*/
1600

    
1601
	}
1602

    
1603
	function ReadConfig(&$cflink) {
1604
		if (!empty($cflink['linkshare'])) {
1605
			if (!empty($cflink['linkshare1'])) {
1606
				$this->SetL_m1($cflink['linkshare1']);
1607
                                $this->SetL_d($cflink['linkshare2']);
1608
				$this->SetLinkshare();
1609
			} else {
1610
				$this->SetL_m1("");
1611
                                $this->SetL_d("");
1612
				$this->DisableLinkshare();
1613
			}
1614
			if (!empty($cflink['linkshare3'])) {
1615
                                $this->SetL_m2($cflink['linkshare3']);
1616
				$this->SetLinkshare();
1617
			}
1618
		} else
1619
			$this->DisableLinkshare();
1620
		if (!empty($cflink['realtime'])) {
1621
                        if (!empty($cflink['realtime1'])) {
1622
                                $this->SetR_m1($cflink['realtime1']);
1623
                                $this->SetR_d($cflink['realtime2']);
1624
				$this->SetRealtime();
1625
			} else {
1626
                                $this->SetR_m1("");
1627
                                $this->SetR_d("");
1628
				$this->DisableRealtime();
1629
			}
1630
                        if (!empty($cflink['realtime3'])) {
1631
                                $this->SetR_m2($cflink['realtime3']);
1632
				$this->SetRealtime();
1633
			}
1634
		} else
1635
			$this->DisableRealtime(); 
1636
		if (!empty($cflink['upperlimit'])) {
1637
                        if (!empty($cflink['upperlimit1'])) {
1638
                                $this->SetU_m1($cflink['upperlimit1']);
1639
                                $this->SetU_d($cflink['upperlimit2']);
1640
				$this->SetUpperlimit();
1641
			} else {
1642
                                $this->SetU_m1("");
1643
                                $this->SetU_d("");
1644
				$this->DisableUpperlimit();
1645
			}
1646
                        if (!empty($cflink['upperlimit3'])) {
1647
                                $this->SetU_m2($cflink['upperlimit3']);
1648
				$this->SetUpperlimit();
1649
			}
1650
		} else
1651
			$this->DisableUpperlimit();
1652
		parent::ReadConfig($cflink);
1653
	}
1654

    
1655
	function build_tree() {
1656
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1657
		$tree .= "\" ";
1658
		$tmpvalue = $this->GetDefault();
1659
		if (!empty($tmpvalue))
1660
			$tree .= " class=\"navlnk\"";
1661
		$tree .= " >" . $this->GetQname() . "</a>";
1662
		if (is_array($this->subqueues)) {
1663
			$tree .= "<ul>";
1664
			foreach ($this->subqueues as $q)  {
1665
				$tree .= $q->build_tree();
1666
			}	
1667
			$tree .= "</ul>";
1668
		}
1669
		$tree .= "</li>";
1670
		return $tree;
1671
	}
1672

    
1673
	/* Even this should take children into consideration */
1674
	function build_rules() {
1675

    
1676
		$pfq_rule = " queue ". $this->qname;
1677
		if ($this->GetInterface())
1678
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1679
		if ($this->GetBandwidth() && $this->GetBwscale())
1680
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1681
				
1682
		$tmpvalue = $this->GetQlimit();
1683
		if (!empty($tmpvalue))
1684
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1685
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1686
			$pfq_rule .= " hfsc ( ";
1687
			$tmpvalue = $this->GetRed();
1688
			if (!empty($tmpvalue)) {
1689
				$comma = 1;
1690
				$pfq_rule .= " red ";
1691
			}
1692
			
1693
			$tmpvalue = $this->GetRio();
1694
			if (!empty($tmpvalue)) {
1695
				if ($comma) 
1696
					$pfq_rule .= " ,";
1697
				$comma = 1;
1698
				$pfq_rule .= " rio ";
1699
			}
1700
			$tmpvalue = $this->GetEcn();
1701
			if (!empty($tmpvalue)) {
1702
				if ($comma) 
1703
					$pfq_rule .= " ,";
1704
				$comma = 1;
1705
				$pfq_rule .= " ecn ";
1706
			}
1707
			$tmpvalue = $this->GetDefault();
1708
			if (!empty($tmpvalue)) {
1709
				if ($comma)
1710
					$pfq_rule .= " ,";
1711
				$comma = 1;
1712
				$pfq_rule .= " default ";
1713
			}
1714

    
1715
			if ($this->GetRealtime() <> "")  {
1716
				if ($comma) 
1717
					$pfq_rule .= " , ";
1718
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1719
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1720
				else  if ($this->GetR_m2() <> "")
1721
					$pfq_rule .= " realtime " . $this->GetR_m2();
1722
				$comma = 1;
1723
			}
1724
			if ($this->GetLinkshare() <> "") {
1725
				if ($comma)
1726
					$pfq_rule .= " ,";
1727
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1728
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1729
				else if ($this->GetL_m2() <> "")
1730
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1731
				$comma = 1;
1732
			}
1733
			if ($this->GetUpperlimit() <> "") {
1734
				if ($comma)
1735
					$pfq_rule .= " ,";
1736
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1737
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1738
				else if ($this->GetU_m2() <> "")
1739
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1740
			}
1741
			$pfq_rule .= " ) ";
1742
		}
1743
		if (count($this->subqueues)) {
1744
			$i = count($this->subqueues);
1745
			$pfq_rule .= " { ";
1746
			foreach ($this->subqueues as $qkey => $qnone) {
1747
				if ($i > 1) {
1748
					$i--;
1749
					$pfq_rule .= " {$qkey}, ";
1750
				} else
1751
					$pfq_rule .= " {$qkey} ";
1752
			}
1753
			$pfq_rule .= " } \n";
1754
			foreach ($this->subqueues as $q)
1755
				$pfq_rule .= $q->build_rules();
1756
		}
1757

    
1758
		 $pfq_rule .= " \n";
1759
			
1760
		return $pfq_rule;
1761
	}
1762

    
1763
	function build_javascript() {
1764
		$javascript = parent::build_javascript();
1765
		$javascript .= "<script type=\"text/javascript\">";
1766
		$javascript .= "function enable_realtime(enable_over) { \n";
1767
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1768
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1769
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1770
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1771
		$javascript .= " } else { \n";
1772
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1773
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1774
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1775
		$javascript .= " } \n";
1776
		$javascript .= " } \n";
1777
		$javascript .= "function enable_linkshare(enable_over) { \n";
1778
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1779
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1780
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1781
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1782
		$javascript .= " } else { \n";
1783
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1784
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1785
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1786
		$javascript .= " } \n";
1787
		$javascript .= " } \n";
1788
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1789
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1790
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1791
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1792
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1793
		$javascript .= " } else { \n";
1794
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1795
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1796
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1797
		$javascript .= " } \n";
1798
			
1799
		$javascript .= "} \n";
1800
		$javascript .= "</script>";
1801

    
1802
		return $javascript;
1803
	}
1804

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

    
1906
		return $form;
1907
	}
1908

    
1909
	function update_altq_queue_data(&$data) { 
1910
		$this->ReadConfig($data);
1911
	}
1912

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

    
2017
class cbq_queue extends priq_queue {
2018
	var $qborrow = "";
2019

    
2020
	function GetBorrow() {
2021
		return $this->qborrow;
2022
	}
2023
	function SetBorrow($borrow) {
2024
		$this->qborrow = $borrow;
2025
	}
2026
	function CanHaveChildren() {
2027
		return true;
2028
	}
2029

    
2030
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2031

    
2032
		if (!is_array($this->subqueues))
2033
			$this->subqueues = array();
2034
		$q =& new cbq_queue();
2035
		$q->SetInterface($this->GetInterface());
2036
		$q->SetParent(&$this);
2037
		$q->ReadConfig($qname);
2038
                $q->validate_input($qname, $input_errors);
2039
                if (count($input_errors)) {
2040
                        return $q;
2041
                }
2042
                switch ($q->GetBwscale()) {
2043
                case "%":
2044
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2045
                        break;
2046
                default:
2047
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2048
                        break;
2049
                }
2050
                $q->SetAvailableBandwidth($myBw);
2051
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2052

    
2053
		$q->SetEnabled("on");
2054
		$q->SetLink($path);
2055
		$this->subqueues[$q->GetQName()] = &$q;
2056
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2057
		if (is_array($qname['queue'])) {
2058
			foreach ($qname['queue'] as $key1 => $que) {
2059
				array_push($path, $key1);
2060
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2061
				array_pop($path);
2062
			}
2063
		}
2064

    
2065
		return $q;
2066
	}
2067

    
2068
	function copy_queue($interface, &$cflink) {
2069

    
2070
		$cflink['interface'] = $interface;
2071
		$cflink['qlimit'] = trim($this->GetQlimit());
2072
		if (empty($clink['qlimit']))
2073
			unset($cflink['qlimit']);
2074
		$cflink['priority'] = trim($this->GetQpriority());
2075
		if (empty($cflink['priority']))
2076
			unset($cflink['priority']);
2077
		$cflink['name'] = $this->GetQname();
2078
		$cflink['description'] = trim($this->GetDescription());
2079
		if (empty($cflink['description']))
2080
			unset($cflink['description']);
2081
		$cflink['bandwidth'] = $this->GetBandwidth();
2082
		$cflink['bandwidthtype'] = $this->GetBwscale();
2083
		$cflink['enabled'] = trim($this->GetEnabled());
2084
		if (empty($cflink['enabled']))
2085
			unset($cflink['enabled']);
2086
		$cflink['default'] = trim($this->GetDefault());
2087
		if (empty($cflink['default']))
2088
			unset($cflink['default']);
2089
		$cflink['red'] = trim($this->GetRed());
2090
		if (empty($cflink['red']))
2091
			unset($cflink['red']);
2092
		$cflink['rio'] = trim($this->GetRio());
2093
		if (empty($cflink['rio']))
2094
			unset($cflink['rio']);
2095
		$cflink['ecn'] = trim($this->GetEcn());
2096
		if (empty($cflink['ecn']))
2097
			unset($cflink['ecn']);
2098
		$cflink['borrow'] = trim($this->GetBorrow());
2099
		if (empty($cflink['borrow']))
2100
			unset($cflink['borrow']);
2101
		if (is_array($this->queues)) {
2102
			$cflinkp['queue'] = array();
2103
			foreach ($this->subqueues as $q) {
2104
				$cflink['queue'][$q->GetQname()] = array();
2105
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
2106
			}
2107
		}
2108
	}
2109
	
2110
	/*
2111
	 * Should search even its children
2112
	 */
2113
	function &find_queue($interface, $qname) {
2114
		if ($qname == $this->GetQname())
2115
			return $this;
2116
		foreach ($this->subqueues as $q) {
2117
			$result =& $q->find_queue("", $qname);
2118
			if ($result)
2119
				return $result;
2120
		}
2121
	}
2122

    
2123
	function &find_parentqueue($interface, $qname) {
2124
		if ($this->subqueues[$qname])
2125
			return $this;
2126
		foreach ($this->subqueues as $q) {
2127
			$result = $q->find_parentqueue("", $qname);
2128
			if ($result)
2129
				return $result;
2130
		}
2131
	}
2132

    
2133
	function delete_queue() {
2134
		unref_on_altq_queue_list($this->GetQname());
2135
		if ($this->GetDefault())
2136
			altq_set_default_queue($this->GetInterface(), "false");
2137
		cleanup_queue_from_rules($this->GetQname());
2138
		foreach ($this->subqueues as $q) {
2139
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2140
			$q->delete_queue();
2141
		}
2142
		unset_object_by_reference($this->GetLink());
2143
	}
2144
	
2145
	function validate_input($data, &$input_errors) {
2146
		parent::validate_input($data, $input_errors);
2147
		
2148
		if ($data['priority'] > 7)
2149
				$input_errors[] = gettext("Priority must be an integer between 1 and 7.");
2150
		$reqdfields[] = "bandwidth";
2151
		$reqdfieldsn[] = gettext("Bandwidth");
2152
		$reqdfields[] = "bandwidthtype";
2153
		$reqdfieldsn[] = gettext("Bandwidthtype");
2154

    
2155
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2156
		
2157
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2158
			$input_errors[] = gettext("Bandwidth must be an integer.");
2159

    
2160

    
2161
		if ($data['bandwidth'] < 0)
2162
                       $input_errors[] = gettext("Bandwidth cannot be negative.");
2163

    
2164
		if ($data['bandwidthtype'] == "%") {
2165
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2166
				$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
2167
		}
2168

    
2169
/*
2170
           $parent =& $this->GetParent();
2171
           switch ($data['bandwidthtype']) {
2172
                       case "%":
2173
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2174
                       default:
2175
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2176
                             break;
2177
           }
2178
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2179
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2180
*/
2181
	}
2182

    
2183
	function ReadConfig(&$q) {
2184
		parent::ReadConfig($q);
2185
		if (!empty($q['borrow']))
2186
			$this->SetBorrow("on");
2187
		else
2188
			$this->SetBorrow("");
2189
	}
2190
		
2191
	function build_javascript() {
2192
		return parent::build_javascript();
2193
	}
2194

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

    
2277
		$pfq_rule .= " \n";
2278
		return $pfq_rule;
2279
	}
2280

    
2281
	function build_form() {
2282
		$form = parent::build_form();
2283
		$form .= "<tr>";
2284
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
2285
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2286
		if ($this->GetBandwidth() > 0)
2287
			$form .= htmlspecialchars($this->GetBandwidth());
2288
		$form .= "\">";
2289
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2290
		$form .= "<option value=\"Gb\"";
2291
		if ($this->GetBwscale() == "Gb")
2292
			$form .= " selected=\"yes\"";
2293
		$form .= ">Gbit/s</option>";
2294
		$form .= "<option value=\"Mb\"";
2295
		if ($this->GetBwscale() == "Mb")
2296
			$form .= " selected=\"yes\"";
2297
		$form .= ">Mbit/s</option>";
2298
		$form .= "<option value=\"Kb\"";
2299
		if ($this->GetBwscale() == "Kb")
2300
			$form .= " selected=\"yes\"";
2301
		$form .= ">Kbit/s</option>";
2302
		$form .= "<option value=\"\"";
2303
		if ($this->GetBwscale() == "b")
2304
			$form .= " selected=\"yes\"";
2305
		$form .= ">Bit/s</option>";
2306
		$form .= "<option value=\"%\"";
2307
		if ($this->GetBwscale() == "%")
2308
			$form .= " selected=\"yes\"";
2309
		$form .= ">%</option>";
2310
		$form .= "</select> <br>";
2311
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
2312
		$form .= "</span></td></tr>";
2313
		$form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>";
2314
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2315
		if($this->GetBorrow() == "on") 
2316
			$form .=  " CHECKED ";
2317
		$form .= "> " . gettext("Borrow from other queues when available") . "<br></td></tr>";
2318

    
2319
		return $form;
2320
	}
2321

    
2322
	function update_altq_queue_data(&$data) { 
2323
		$this->ReadConfig($data);
2324
	}
2325

    
2326
	function wconfig() {
2327
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2328
		if (!is_array($cflink))
2329
			$cflink = array();
2330
		$cflink['interface'] = $this->GetInterface();
2331
		$cflink['qlimit'] = trim($this->GetQlimit());
2332
		if (empty($cflink['qlimit']))
2333
			unset($cflink['qlimit']);
2334
		$cflink['priority'] = $this->GetQpriority();
2335
		if (empty($cflink['priority']))
2336
			unset($cflink['priority']);
2337
		$cflink['name'] = $this->GetQname();
2338
		$cflink['description'] = $this->GetDescription();
2339
		if (empty($cflink['description']))
2340
			unset($cflink['description']);
2341
		$cflink['bandwidth'] = $this->GetBandwidth();
2342
		$cflink['bandwidthtype'] = $this->GetBwscale();
2343
		$cflink['enabled'] = trim($this->GetEnabled());
2344
		if (empty($cflink['enabled']))
2345
			unset($cflink['enabled']);
2346
		$cflink['default'] = trim($this->GetDefault());
2347
		if (empty($cflink['default']))
2348
			unset($cflink['default']);
2349
		$cflink['red'] = trim($this->GetRed());
2350
		if (empty($cflink['red']))
2351
			unset($cflink['red']);
2352
		$cflink['rio'] = trim($this->GetRio());
2353
		if (empty($cflink['rio']))
2354
			unset($cflink['rio']);
2355
		$cflink['ecn'] = trim($this->GetEcn());
2356
		if (empty($cflink['ecn']))
2357
			unset($cflink['ecn']);
2358
		$cflink['borrow'] = trim($this->GetBorrow());
2359
		if (empty($cflink['borrow']))
2360
			unset($cflink['borrow']);
2361
	}
2362
}
2363

    
2364
class fairq_queue extends priq_queue {
2365
	var $hogs;
2366
	var $buckets;
2367

    
2368
	function GetBuckets() {
2369
		return $this->buckets;
2370
	}
2371
	function SetBuckets($buckets) {
2372
		$this->buckets = $buckets;
2373
	}
2374
	function GetHogs() {
2375
		return $this->hogs;
2376
	}
2377
	function SetHogs($hogs) {
2378
		$this->hogs = $hogs;
2379
	}
2380
	function CanHaveChildren() {
2381
		return false;
2382
	}
2383

    
2384

    
2385
	function copy_queue($interface, &$cflink) {
2386
                $cflink['interface'] = $interface;
2387
                $cflink['qlimit'] = $this->GetQlimit();
2388
                $cflink['priority'] = $this->GetQpriority();
2389
                $cflink['name'] = $this->GetQname();
2390
                $cflink['description'] = $this->GetDescription();
2391
                $cflink['bandwidth'] = $this->GetBandwidth();
2392
                $cflink['bandwidthtype'] = $this->GetBwscale();
2393
                $cflink['enabled'] = $this->GetEnabled();
2394
                $cflink['default'] = $this->GetDefault();
2395
                $cflink['red'] = $this->GetRed();
2396
                $cflink['rio'] = $this->GetRio();
2397
                $cflink['ecn'] = $this->GetEcn();
2398
                $cflink['buckets'] = $this->GetBuckets();
2399
		$cflink['hogs'] = $this->GetHogs();
2400
	}
2401
	
2402
	/*
2403
	 * Should search even its children
2404
	 */
2405
	function &find_queue($interface, $qname) {
2406
		if ($qname == $this->GetQname())
2407
			return $this;
2408
	}
2409

    
2410
	function find_parentqueue($interface, $qname) { return; }
2411

    
2412
	function delete_queue() {
2413
		unref_on_altq_queue_list($this->GetQname());
2414
		if ($this->GetDefault())
2415
			altq_set_default_queue($this->GetInterface(), "false");
2416
		cleanup_queue_from_rules($this->GetQname());
2417
		unset_object_by_reference($this->GetLink());
2418
	}
2419
	
2420
	function validate_input($data, &$input_errors) {
2421
		parent::validate_input($data, $input_errors);
2422
		
2423
		if ($data['priority'] > 255)
2424
				$input_errors[] = gettext("Priority must be an integer between 1 and 255.");
2425
		$reqdfields[] = "bandwidth";
2426
		$reqdfieldsn[] = gettext("Bandwidth");
2427
		$reqdfields[] = "bandwidthtype";
2428
		$reqdfieldsn[] = gettext("Bandwidthtype");
2429

    
2430
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2431
		
2432
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2433
			$input_errors[] = gettext("Bandwidth must be an integer.");
2434

    
2435

    
2436
		if ($data['bandwidth'] < 0)
2437
			$input_errors[] = gettext("Bandwidth cannot be negative.");
2438

    
2439

    
2440
		if ($data['bandwidthtype'] == "%") {
2441
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2442
				$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
2443
		}
2444

    
2445
/*
2446
           	$parent =& $this->GetParent();
2447
           	switch ($data['bandwidthtype']) {
2448
                       case "%":
2449
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2450
                       default:
2451
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2452
                             break;
2453
           	}
2454
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2455
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2456
*/
2457
	}
2458
	
2459
	function ReadConfig(&$q) {
2460
		parent::ReadConfig($q);
2461
		if (!empty($q['buckets']))
2462
			$this->SetBuckets($q['buckets']);
2463
		else
2464
			$this->SetBuckets("");
2465
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2466
			$this->SetHogs($q['hogs']);
2467
		else
2468
			$this->SetHogs("");
2469
	}
2470
		
2471
	function build_javascript() {
2472
		return parent::build_javascript();
2473
	}
2474

    
2475
	function build_tree() {
2476
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2477
		$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2478
		$tree .= "\" ";
2479
		$tmpvalue = trim($this->GetDefault());
2480
		if (!empty($tmpvalue))
2481
			$tree .= " class=\"navlnk\"";
2482
		$tree .= " >" . $this->GetQname() . "</a>";
2483
		$tree .= "</li>";
2484
		return $tree;
2485
	}
2486
		
2487
	/* Even this should take children into consideration */
2488
	function build_rules() {
2489
		$pfq_rule = "queue ". $this->qname;
2490
		if ($this->GetInterface())
2491
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2492
		if ($this->GetBandwidth() && $this->GetBwscale())
2493
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2494
		$tmpvalue = trim($this->GetQpriority());
2495
		if (!empty($tmpvalue))
2496
			$pfq_rule .= " priority " . $this->GetQpriority();
2497
		$tmpvalue = trim($this->GetQlimit());
2498
		if (!empty($tmpvalue))
2499
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2500
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2501
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2502
			$pfq_rule .= " fairq ( ";
2503
			$tmpvalue = trim($this->GetRed());
2504
			if (!empty($tmpvalue)) {
2505
				$comma = 1;
2506
				$pfq_rule .= " red ";
2507
			}
2508
			$tmpvalue = trim($this->GetRio());
2509
			if (!empty($tmpvalue)) {
2510
				if ($comma) 
2511
					$pfq_rule .= " ,";
2512
				$comma = 1;
2513
				$pfq_rule .= " rio ";
2514
			}
2515
			$tmpvalue = trim($this->GetEcn());
2516
			if (!empty($tmpvalue)) {
2517
				if ($comma) 
2518
					$pfq_rule .= " ,";
2519
				$comma = 1;
2520
				$pfq_rule .= " ecn ";
2521
			}
2522
			$tmpvalue = trim($this->GetDefault());
2523
			if (!empty($tmpvalue)) {
2524
				if ($comma)
2525
					$pfq_rule .= " ,";
2526
				$comma = 1;
2527
				$pfq_rule .= " default ";
2528
			}
2529
			$tmpvalue = trim($this->GetBuckets());
2530
			if (!empty($tmpvalue)) {
2531
				if ($comma)
2532
					$pfq_rule .= ", ";
2533
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2534
			}
2535
			$tmpvalue = trim($this->GetHogs());
2536
			if (!empty($tmpvalue)) {
2537
				if ($comma)
2538
					$pfq_rule .= ", ";
2539
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2540
			}
2541
				$pfq_rule .= " ) ";
2542
		} 
2543

    
2544
		$pfq_rule .= " \n";
2545
		return $pfq_rule;
2546
	}
2547

    
2548
	function build_form() {
2549
		$form = parent::build_form();
2550
		$form .= "<tr>";
2551
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
2552
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2553
		if ($this->GetBandwidth() > 0)
2554
			$form .= htmlspecialchars($this->GetBandwidth());
2555
		$form .= "\">";
2556
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2557
		$form .= "<option value=\"Gb\"";
2558
		if ($this->GetBwscale() == "Gb")
2559
			$form .= " selected=\"yes\"";
2560
		$form .= ">Gbit/s</option>";
2561
		$form .= "<option value=\"Mb\"";
2562
		if ($this->GetBwscale() == "Mb")
2563
			$form .= " selected=\"yes\"";
2564
		$form .= ">Mbit/s</option>";
2565
		$form .= "<option value=\"Kb\"";
2566
		if ($this->GetBwscale() == "Kb")
2567
			$form .= " selected=\"yes\"";
2568
		$form .= ">Kbit/s</option>";
2569
		$form .= "<option value=\"\"";
2570
		if ($this->GetBwscale() == "b")
2571
			$form .= " selected=\"yes\"";
2572
		$form .= ">Bit/s</option>";
2573
		$form .= "<option value=\"%\"";
2574
		if ($this->GetBwscale() == "%")
2575
			$form .= " selected=\"yes\"";
2576
		$form .= ">%</option>";
2577
		$form .= "</select> <br>";
2578
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
2579
		$form .= "</span></td></tr>";
2580
		$form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>";
2581
		$form .= "<td class=\"vtable\"><table><tr><td>";
2582
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2583
		$tmpvalue = trim($this->GetBuckets());
2584
		if(!empty($tmpvalue)) 
2585
			$form .=  $this->GetBuckets();
2586
		$form .= "\"> " . gettext("Number of buckets available.") . "<br></td></tr>";
2587
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2588
		$tmpvalue = trim($this->GetHogs());
2589
		if(!empty($tmpvalue)) 
2590
			$form .=  $this->GetHogs();
2591
		$form .= "\"> " . gettext("Bandwidth limit for hosts to not saturate link.") . "<br></td></tr>";
2592
		$form .= "</table></td></tr>";
2593
		return $form;
2594
	}
2595

    
2596
	function update_altq_queue_data(&$data) { 
2597
		$this->ReadConfig($data);
2598
	}
2599

    
2600
	function wconfig() {
2601
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2602
		if (!is_array($cflink))
2603
			$cflink = array();
2604
		$cflink['interface'] = $this->GetInterface();
2605
		$cflink['qlimit'] = trim($this->GetQlimit());
2606
		if (empty($cflink['qlimit']))
2607
			unset($cflink['qlimit']);
2608
		$cflink['priority'] = trim($this->GetQpriority());
2609
		if (empty($cflink['priority']))
2610
			unset($cflink['priority']);
2611
		$cflink['name'] = $this->GetQname();
2612
		$cflink['description'] = trim($this->GetDescription());
2613
		if (empty($cflink['description']))
2614
			unset($cflink['description']);
2615
		$cflink['bandwidth'] = $this->GetBandwidth();
2616
		$cflink['bandwidthtype'] = $this->GetBwscale();
2617
		$cflink['enabled'] = $this->GetEnabled();
2618
		if (empty($cflink['enabled']))
2619
			unset($cflink['enabled']);
2620
		$cflink['default'] = trim($this->GetDefault());
2621
		if (empty($cflink['default']))
2622
			unset($cflink['default']);
2623
		$cflink['red'] = trim($this->GetRed());
2624
		if (empty($cflink['red']))
2625
			unset($cflink['red']);
2626
		$cflink['rio'] = trim($this->GetRio());
2627
		if (empty($cflink['rio']))
2628
			unset($cflink['rio']);
2629
		$cflink['ecn'] = trim($this->GetEcn());
2630
		if (empty($cflink['ecn']))
2631
			unset($cflink['ecn']);
2632
		$cflink['buckets'] = trim($this->GetBuckets());
2633
		if (empty($cflink['buckets']))
2634
			unset($cflink['buckets']);
2635
		$cflink['hogs'] = trim($this->GetHogs());
2636
		if (empty($cflink['hogs']))
2637
			unset($cflink['hogs']);
2638
	}
2639
}
2640

    
2641

    
2642
/*
2643
 * dummynet(4) wrappers.
2644
 */
2645

    
2646

    
2647
/*
2648
 * List of respective objects!
2649
 */
2650
$dummynet_pipe_list = array();
2651

    
2652
class dummynet_class {
2653
        var $qname;
2654
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2655
        var $qlimit;
2656
        var $description;
2657
	var $qenabled;
2658
	var $link;
2659
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2660
        var $plr;
2661

    
2662
        var $buckets;
2663
        /* mask parameters */
2664
        var $mask;
2665
        var $noerror;
2666

    
2667
        /* Accessor functions */
2668
        function SetLink($link) {
2669
                $this->link = $link;
2670
        }
2671
        function GetLink() {
2672
                return $this->link;
2673
        }
2674
	function Getmask() {
2675
		return $this->mask;
2676
	}
2677
	function SetMask($mask) {
2678
		$this->mask = $mask;
2679
	}
2680
	function &GetParent() {
2681
		return $this->qparent;
2682
	}
2683
	function SetParent(&$parent) {
2684
		$this->qparent = &$parent;
2685
	}
2686
        function GetEnabled() {
2687
                return $this->qenabled;
2688
        }
2689
        function SetEnabled($value) {
2690
                $this->qenabled = $value;
2691
        }
2692
	function CanHaveChildren() {
2693
		return false;
2694
        }
2695
	function CanBeDeleted() {
2696
                return true;
2697
        }
2698
        function GetQname() {
2699
                return $this->qname;
2700
        }
2701
        function SetQname($name) {
2702
                $this->qname = trim($name);
2703
        }
2704
        function GetQlimit() {
2705
                return $this->qlimit;
2706
        }
2707
        function SetQlimit($limit) {
2708
               	$this->qlimit = $limit;
2709
        }
2710
        function GetDescription() {
2711
                return $this->description;
2712
        }
2713
        function SetDescription($str) {
2714
                $this->description = trim($str);
2715
        }
2716
        function GetFirstime() {
2717
                return $this->firsttime;
2718
        }
2719
        function SetFirsttime($number) {
2720
                $this->firsttime = $number;
2721
        }
2722
        function GetBuckets() {
2723
                return $this->buckets;
2724
        }
2725
        function SetBuckets($buckets) {
2726
                $this->buckets = $buckets;
2727
        }
2728
	function SetNumber($number) {
2729
		$this->qnumber = $number;
2730
	}
2731
	function GetNumber() {
2732
		return $this->qnumber;
2733
	}
2734
        function GetPlr() {
2735
                return $this->plr;
2736
        }
2737
        function SetPlr($plr) {
2738
                $this->plr = $plr;
2739
        }
2740

    
2741
	function build_javascript() { return; } /* Do not remove */
2742

    
2743
	function validate_input($data, &$input_errors) {
2744
		$reqdfields[] = "bandwidth";
2745
		$reqdfieldsn[] = gettext("Bandwidth");
2746
		$reqdfields[] = "bandwidthtype";
2747
		$reqdfieldsn[] = gettext("Bandwidthtype");
2748
		$reqdfields[] = "name";
2749
		$reqdfieldsn[] = gettext("Name");
2750
	
2751
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2752

    
2753
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2754
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2755
				$input_errors[] = gettext("Plr must be an integer between 1 and 100.");
2756
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2757
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2758
				$input_errors[] = gettext("Buckets must be an integer between 16 and 65535.");
2759
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2760
			$input_errors[] = gettext("Queue limit must be an integer");
2761
		if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2762
			$input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
2763
	}
2764
}
2765

    
2766
class dnpipe_class extends dummynet_class {
2767
        var $delay;
2768
	var $qbandwidth;
2769
	var $qbandwidthtype;
2770

    
2771
		/* This is here to help on form building and building rules/lists */
2772
        var $subqueues = array();
2773

    
2774
	function CanHaveChildren() {
2775
	        return true;
2776
        }
2777
	function SetDelay($delay) {
2778
		$this->delay = $delay;
2779
	}
2780
	function GetDelay() {
2781
		return $this->delay;
2782
	}
2783
	function GetBwscale() {
2784
                return $this->qbandwidthtype;
2785
        }
2786
        function SetBwscale($scale) {
2787
               	$this->qbandwidthtype = $scale;
2788
        }		
2789
	function delete_queue() {
2790
		cleanup_dnqueue_from_rules($this->GetQname());
2791
		foreach ($this->subqueues as $q)
2792
			$q->delete_queue();
2793
		unset_dn_object_by_reference($this->GetLink());
2794
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2795
        }
2796
        function GetBandwidth() {
2797
                return $this->qbandwidth;
2798
        }
2799
        function SetBandwidth($bandwidth) {
2800
                $this->qbandwidth = $bandwidth;
2801
        }
2802

    
2803
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2804

    
2805
		if (!is_array($this->subqueues))
2806
			$this->subqueues = array();
2807
			
2808
		$q =& new dnqueue_class();
2809
		$q->SetLink($path);
2810
		$q->SetEnabled("on");
2811
		$q->SetPipe($this->GetQname());
2812
		$q->SetParent(&$this);
2813
		$q->ReadConfig($queue);
2814
		$q->validate_input($queue, $input_errors);
2815
		if (count($input_errors))
2816
			return $q;
2817
		$this->subqueues[$q->GetQname()] = &$q;
2818
            
2819
		return $q;
2820
	}
2821

    
2822
	function &get_queue_list($q = null) {
2823
		$qlist = array();
2824

    
2825
		$qlist[$this->GetQname()] = $this->GetNumber();
2826
		if (is_array($this->subqueues)) {
2827
			foreach ($this->subqueues as $queue)
2828
				$queue->get_queue_list(&$qlist);
2829
		}
2830
		return $qlist;
2831
	}
2832
		
2833
        /*
2834
         * Should search even its children
2835
         */
2836
        function &find_queue($pipe, $qname) {
2837
                if ($qname == $this->GetQname()) 
2838
                        return $this;
2839
               	foreach ($this->subqueues as $q) {
2840
                       	$result =& $q->find_queue("", $qname);
2841
						if ($result)
2842
                       	        return $result;
2843
               	}
2844
        }
2845

    
2846
	function &find_parentqueue($pipe, $qname) {
2847
		return NULL;
2848
       	}
2849

    
2850
	function validate_input($data, &$input_errors) {
2851
		parent::validate_input($data, $input_errors);
2852

    
2853
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2854
			$input_errors[] = gettext("Bandwidth must be an integer.");
2855
		if ($data['delay'] && (!is_numeric($data['delay'])))
2856
			$input_errors[] = gettext("Delay must be an integer.");
2857
	}
2858

    
2859
	function ReadConfig(&$q) {
2860
           	$this->SetQname($q['name']);
2861
		$this->SetNumber($q['number']);
2862
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2863
			$this->SetBandwidth($q['bandwidth']);
2864
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2865
				$this->SetBwscale($q['bandwidthtype']);
2866
		}
2867
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2868
              		$this->SetQlimit($q['qlimit']);
2869
		if (isset($q['mask']) && $q['mask'] <> "")
2870
              		$this->SetMask($q['mask']);
2871
		if (isset($q['buckets']) && $q['buckets'] <> "")
2872
              		$this->SetBuckets($q['buckets']);
2873
            	if (isset($q['plr']) && $q['plr'] <> "")
2874
            		$this->SetPlr($q['plr']);
2875
		if (isset($q['delay']) && $q['delay'] <> "")
2876
            		$this->SetDelay($q['delay']);
2877
            	if (isset($q['description']) && $q['description'] <> "")
2878
			$this->SetDescription($q['description']);
2879
		$this->SetEnabled($q['enabled']);
2880

    
2881
        }
2882

    
2883
	function build_tree() {
2884
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2885
		$tree .= $this->GetQname() . "</a>";
2886
		if (is_array($this->subqueues)) {
2887
			$tree .= "<ul>";
2888
			foreach ($this->subqueues as $q)  {
2889
				$tree .= $q->build_tree();
2890
			}	
2891
			$tree .= "</ul>";
2892
		}
2893
		$tree .= "</li>";
2894
		
2895
		return $tree;
2896
	}
2897

    
2898
        function build_rules() {
2899
		if ($this->GetEnabled() == "")
2900
			return;
2901

    
2902
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2903
		if ($this->GetBandwidth() && $this->GetBwscale())
2904
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2905
		if ($this->GetQlimit())
2906
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2907
		if ($this->GetPlr())
2908
			$pfq_rule .= " plr " . $this->GetPlr();
2909
		if ($this->GetBuckets())
2910
			$pfq_rule .= " buckets " . $this->GetBuckets();
2911
		if ($this->GetDelay())
2912
			$pfq_rule .= " delay " . $this->GetDelay();
2913

    
2914
		$mask = $this->GetMask();
2915
		if (!empty($mask)) {
2916
			/* XXX TODO extend this to support more complicated masks */
2917
			switch ($mask) {
2918
			case 'srcaddress':
2919
				$pfq_rule .= " mask src-ip 0xffffffff ";
2920
				break;
2921
			case 'dstaddress':
2922
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2923
				break;
2924
			default:
2925
				break;
2926
			}
2927
			$pfq_rule .= "\n";
2928

    
2929
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2930
       			        foreach ($this->subqueues as $q)
2931
				$pfq_rule .= $q->build_rules();
2932
               		}
2933
    		}            
2934
		$pfq_rule .= " \n";
2935

    
2936
		return $pfq_rule;
2937
        }
2938

    
2939
	function update_dn_data(&$data) { 
2940
		$this->ReadConfig($data);
2941
	}
2942

    
2943
        function build_form() { 
2944
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
2945
                $form .= gettext("Enable/Disable");
2946
                $form .= "</td><td class=\"vncellreq\">";
2947
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
2948
                if ($this->GetEnabled() == "on")
2949
                        $form .=  " CHECKED";
2950
                $form .= " ><span class=\"vexpl\"> " . gettext("Enable/Disable limiter and its children") . "</span>";
2951
                $form .= "</td></tr>";
2952
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
2953
		$form .= "<td class=\"vncellreq\">";
2954
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
2955
		$form .= $this->GetQname()."\">";
2956
		$form .= "</td></tr>";
2957
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth");
2958
		$form .= "</td><td class=\"vncellreq\">";
2959
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
2960
		$form .= $this->GetBandwidth() . "\">"; 
2961
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
2962
		$form .= "<option value=\"Kb\"";
2963
		if ($this->GetBwscale() == "Kb")
2964
			$form .= " selected=\"yes\"";
2965
		$form .= ">Kbit/s</option>";
2966
		$form .= "<option value=\"Mb\"";
2967
		if ($this->GetBwscale() == "Mb")
2968
			$form .= " selected=\"yes\"";
2969
		$form .= ">Mbit/s</option>";
2970
		$form .= "<option value=\"Gb\"";
2971
		if ($this->GetBwscale() == "Gb")
2972
			$form .= " selected=\"yes\"";
2973
		$form .= ">Gbit/s</option>";		
2974
		$form .= "<option value=\"\"";
2975
		if ($this->GetBwscale() == "b")
2976
			$form .= " selected=\"yes\"";
2977
		$form .= ">" . gettext("Bit/s") . "</option>";
2978
		$form .= "</select>";
2979
		$form .= "</td></tr>";
2980
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Mask") . "</td>";
2981
		$form .= "<td class=\"vncellreq\">";
2982
		$form .= "<select name=\"mask\" class=\"formselect\">";
2983
		$form .= "<option value=\"none\"";
2984
		if ($this->GetMask() == "none")
2985
			$form .= " selected=\"yes\"";
2986
		$form .= ">none</option>";
2987
		$form .= "<option value=\"srcaddress\"";
2988
		if ($this->GetMask() == "srcaddress")
2989
			$form .= " selected=\"yes\"";
2990
		$form .= ">" . gettext("Source addresses") . "</option>";
2991
		$form .= "<option value=\"dstaddress\"";
2992
		if ($this->GetMask() == "dstaddress")
2993
			$form .= " selected=\"yes\"";
2994
		$form .= ">" . gettext("Destination addresses") . "</option>";
2995
		$form .= "</select>";
2996
		$form .= "&nbsp;<br>";
2997
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' is chosen, \n"
2998
		      .  "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n"
2999
		      .  "be created for each source/destination IP address encountered, \n"
3000
		      .  "respectively. This makes it possible to easily specify bandwidth \n"
3001
		      .  "limits per host.") . "</span>";
3002
		$form .= "</td></tr>";
3003
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Description") . "</td>";
3004
		$form .= "<td class=\"vncellreq\">";
3005
		$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3006
		$form .= $this->GetDescription();
3007
		$form .= "\">";
3008
		$form .= "<br> <span class=\"vexpl\">";
3009
		$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3010
		$form .= "</td></tr>";
3011
      		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3012
		$form .= "<td></td>";
3013
                $form .= "<td><div id=\"showadvancedboxspr\">";
3014
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3015
		$form .= " value=\"" . gettext("Show advanced options") . "\"></input></a>";
3016
                $form .= "</div></td></tr>";
3017
                $form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3018

    
3019
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3020
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3021
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3022
		$form .= $this->GetDelay() . "\">";
3023
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3024
			  .  "should specify 0 here (or leave the field empty)") . "</span>";
3025
		$form .= "</td></tr><br/>";
3026
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3027
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3028
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3029
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3030
		$form .= $this->GetPlr() . "\">";
3031
		$form .= "&nbsp;<br> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3032
			  .  "should specify 0 here (or leave the field empty). "
3033
		      .  "A value of 0.001 means one packet in 1000 gets dropped") . "</span>";
3034
		$form .= "</td></tr>";
3035
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3036
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Queue Size") . "</td>";
3037
		$form .= "<td class=\"vncellreq\">";
3038
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3039
		$form .= $this->GetQlimit() . "\">";
3040
		$form .= "&nbsp;slots<br>";
3041
		$form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3042
		      .  "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, "
3043
	              .  "then they are delayed by value specified in the Delay field, and then they "
3044
		      .  "are delivered to their destination.") . "</span>";
3045
		$form .= "</td></tr>";
3046
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3047
                $form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bucket Size") . "</td>";
3048
                $form .= "<td class=\"vncellreq\">";
3049
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3050
                $form .= $this->GetBuckets() . "\">";
3051
                $form .= "&nbsp;slots<br>";
3052
                $form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3053
                      .  "should leave the field empty. It increases the hash size set.");
3054
                $form .= "</td></tr>";
3055

    
3056
		return $form;
3057
			
3058
		}
3059

    
3060
	function wconfig() {
3061
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3062
            	if (!is_array($cflink))
3063
            		$cflink = array();
3064
		$cflink['name'] = $this->GetQname();
3065
		$cflink['number'] = $this->GetNumber();
3066
            	$cflink['qlimit'] = $this->GetQlimit();
3067
            	$cflink['plr'] = $this->GetPlr();
3068
            	$cflink['description'] = $this->GetDescription();
3069
		$cflink['bandwidth'] = $this->GetBandwidth();
3070
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3071
		$cflink['enabled'] = $this->GetEnabled();
3072
		$cflink['buckets'] = $this->GetBuckets();
3073
		$cflink['mask'] = $this->GetMask();
3074
		$cflink['delay'] = $this->GetDelay();
3075
	}
3076

    
3077
}
3078

    
3079
class dnqueue_class extends dummynet_class {
3080
        var $pipeparent;
3081
        var $weight;
3082

    
3083
        function GetWeight() {
3084
                return $this->weight;
3085
        }
3086
        function SetWeight($weight) {
3087
                $this->weight = $weight;
3088
        }
3089
	function GetPipe() {
3090
		return $this->pipeparent;
3091
	}
3092
	function SetPipe($pipe) {
3093
		$this->pipeparent = $pipe;
3094
	}
3095

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

    
3099
	function delete_queue() {
3100
		cleanup_dnqueue_from_rules($this->GetQname());
3101
		unset_dn_object_by_reference($this->GetLink());
3102
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3103
        }
3104

    
3105
	function validate_input($data, &$input_errors) {
3106
		parent::validate_input($data, $input_errors);
3107

    
3108
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3109
			($data['weight'] < 1 && $data['weight'] > 100))) 
3110
				$input_errors[] = gettext("Weight must be an integer between 1 and 100.");
3111
	}
3112

    
3113
        /*
3114
         * Should search even its children
3115
         */
3116
        function &find_queue($pipe, $qname) {
3117
                if ($qname == $this->GetQname()) 
3118
                	return $this;
3119
		else
3120
			return NULL;
3121
        }
3122

    
3123
	function &find_parentqueue($pipe, $qname) {
3124
		return $this->qparent;
3125
        }
3126

    
3127
        function &get_queue_list(&$qlist) {
3128
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3129
        }		
3130

    
3131
	function ReadConfig(&$q) {
3132
          	$this->SetQname($q['name']);
3133
		$this->SetNumber($q['number']);
3134
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3135
       		       	$this->SetQlimit($q['qlimit']);
3136
		if (isset($q['mask']) && $q['mask'] <> "")
3137
              		$this->SetMask($q['mask']);
3138
       		if (isset($q['weight']) && $q['weight'] <> "")
3139
            		$this->SetWeight($q['weight']);
3140
            	if (isset($q['description']) && $q['description'] <> "")
3141
			$this->SetDescription($q['description']);
3142
		$this->SetEnabled($q['enabled']);
3143
        }
3144

    
3145
	function build_tree() {
3146
		$parent =& $this->GetParent();
3147
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3148
		$tree .= $this->GetQname() . "</a>";
3149
		$tree .= "</li>";
3150
		
3151
		return $tree;
3152
	}
3153

    
3154
        function build_rules() {
3155
		if ($this->GetEnabled() == "")
3156
			return; 
3157

    
3158
		$parent =& $this->GetParent();
3159
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3160
		if ($this->GetQlimit())
3161
                    	$pfq_rule .= " queue " . $this->GetQimit();
3162
		if ($this->GetWeight())
3163
			$pfq_rule .= " weight " . $this->GetWeight();
3164
		if ($this->GetBuckets())
3165
			$pfq_rule .= " buckets " . $this->GetBuckets();
3166
		$mask = $this->GetMask();
3167
		if (!empty($mask)) {
3168
			/* XXX TODO extend this to support more complicated masks */
3169
			switch ($mask) {
3170
			case 'srcaddress':
3171
				$pfq_rule .= " mask src-ip 0xffffffff ";
3172
				break;
3173
			case 'dstaddress':
3174
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3175
				break;
3176
			default:
3177
				break;
3178
			}
3179
			$pfq_rule .= "\n";
3180
		}
3181

    
3182
		return $pfq_rule;
3183
	}
3184

    
3185
        function build_form() { 
3186
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
3187
                $form .= gettext("Enable/Disable");
3188
                $form .= "</td><td class=\"vncellreq\">";
3189
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
3190
                if ($this->GetEnabled() == "on")
3191
                        $form .=  " CHECKED";
3192
                $form .= " ><span class=\"vexpl\"> " . gettext("Enable/Disable queue and its children") . "</span>";
3193
                $form .= "</td></tr>";
3194
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
3195
		$form .= "<td class=\"vncellreq\">";
3196
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
3197
		$form .= $this->GetQname()."\">";
3198
		$form .= "</td></tr>";
3199
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Mask") . "</td>";
3200
		$form .= "<td class=\"vncellreq\">";
3201
		$form .= "<select name=\"mask\" class=\"formselect\">";
3202
		$form .= "<option value=\"none\"";
3203
		if ($this->GetMask() == "none")
3204
			$form .= " selected=\"yes\"";
3205
		$form .= ">" . gettext("none") . "</option>";
3206
		$form .= "<option value=\"srcaddress\"";
3207
		if ($this->GetMask() == "srcaddress")
3208
			$form .= " selected=\"yes\"";
3209
		$form .= ">" . gettext("Source addresses") . "</option>";
3210
		$form .= "<option value=\"dstaddress\"";
3211
		if ($this->GetMask() == "dstaddress")
3212
			$form .= " selected=\"yes\"";
3213
		$form .= ">" . gettext("Destination addresses") . "</option>";
3214
		$form .= "</select>";
3215
		$form .= "&nbsp;slots<br>";
3216
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' is chosen, \n"
3217
		      .  "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n"
3218
		      .  "be created for each source/destination IP address encountered, \n"
3219
		      .  "respectively. This makes it possible to easily specify bandwidth \n"
3220
		      .  "limits per host.") . "</span>";
3221
		$form .= "</td></tr>";
3222
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
3223
		$form .= "<td class=\"vncellreq\">";
3224
		$form .= "<input type=\"text\" id=\"description\" class=\"formfld unknown\" size=\"50%\" name=\"description\" value=\"";
3225
		$form .= $this->GetDescription();
3226
		$form .= "\">";
3227
		$form .= "<br> <span class=\"vexpl\">";
3228
		$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3229
		$form .= "</td></tr>";
3230
		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3231
		$form .= "<td></td>";
3232
                $form .= "<td><div id=\"showadvancedboxspr\">";
3233
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3234
		$form .= " value=\"" . gettext("Show advanced options") . "\"></input></a>";
3235
                $form .= "</div></td></tr>";
3236
		$form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3237
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Weight") . "</td>";
3238
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3239
		$form .= "<input name=\"weight\" type=\"text\" id=\"weight\" size=\"5\" value=\"";
3240
		$form .= $this->GetWeight() . "\">";
3241
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">" . gettext("Hint: For queues under the same parent "
3242
		      .  "this specifies the share that a queue gets(values range from 1 to 100, you can leave it blank otherwise)") . "</span>";
3243
		$form .= "</td></tr>";
3244
		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3245
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Packet loss rate") . "</td>";
3246
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3247
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3248
		$form .= $this->GetPlr() . "\">";
3249
		$form .= "&nbsp;<br> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3250
			  .  "should specify 0 here (or leave the field empty). "
3251
			  .  "A value of 0.001 means one packet in 1000 gets dropped") . "</span>";
3252
		$form .= "</td></tr>";
3253
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3254
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Queue Size") . "</td>";
3255
		$form .= "<td class=\"vncellreq\">";
3256
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3257
		$form .= $this->GetQlimit() . "\">";
3258
		$form .= "&nbsp;slots<br>";
3259
		$form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3260
			  .  "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, "
3261
			  .  "then they are delayed by value specified in the Delay field, and then they "
3262
			  .  "are delivered to their destination.") . "</span>";
3263
		$form .= "</td></tr>";
3264
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3265
                $form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bucket Size") . "</td>";
3266
                $form .= "<td class=\"vncellreq\">";
3267
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3268
                $form .= $this->GetBuckets() . "\">";
3269
                $form .= "&nbsp;" . gettext("slots") . "<br>";
3270
                $form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3271
                      .  "should leave the field empty. It increases the hash size set.");
3272
                $form .= "</td></tr>";
3273

    
3274
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3275
		$form .= " value=\"" . $this->GetPipe() . "\">";
3276

    
3277
		return $form;
3278
			
3279
	}
3280

    
3281
        function update_dn_data(&$data) { 
3282
		$this->ReadConfig($data);
3283
	}
3284

    
3285
	function wconfig() {
3286
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3287
            	if (!is_array($cflink))
3288
            		$cflink = array();
3289
		$cflink['name'] = $this->GetQname();
3290
		$cflink['number'] = $this->GetNumber();
3291
            	$cflink['qlimit'] = $this->GetQlimit();
3292
            	$cflink['description'] = $this->GetDescription();
3293
		$cflink['weight'] = $this->GetWeight();
3294
		$cflink['enabled'] = $this->GetEnabled();
3295
		$cflink['buckets'] = $this->GetBuckets();
3296
		$cflink['mask'] = $this->GetMask();
3297
	}
3298
}
3299

    
3300
// List of layer7 objects
3301
$layer7_rules_list = array();
3302

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

    
3499
class l7rule {
3500
    
3501
    var $rprotocol; //protocol
3502
    var $rstructure; //action, limiter, queue
3503
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3504
    
3505
    //Auxiliary Functions
3506
    
3507
    function GetRProtocol() {
3508
        return $this->rprotocol;
3509
    }
3510
    function SetRProtocol($rprotocol) {
3511
        $this->rprotocol = $rprotocol;
3512
    }
3513
    function GetRStructure() {
3514
        return $this->rstructure;
3515
    }
3516
    function SetRStructure($rstructure) {
3517
        $this->rstructure = $rstructure;
3518
    }
3519
    function GetRBehaviour() {
3520
        return $this->rbehaviour;
3521
    }
3522
    function SetRBehaviour($rbehaviour) {
3523
        $this->rbehaviour = $rbehaviour;
3524
    }
3525
    
3526
    //XXX Do we need to test any particularity for AltQ queues?
3527
    function build_rules() {
3528
	global $dummynet_pipe_list;
3529
	switch ($this->GetRStructure()) {
3530
		case "limiter":
3531
			read_dummynet_config();
3532
			$dn_list =& get_unique_dnqueue_list();
3533
			$found = false;
3534
			if(is_array($dn_list)) {
3535
				foreach($dn_list as $key => $value) {
3536
					if($key == $this->GetRBehaviour()) {
3537
						if($value[0] == "?")
3538
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3539
						else
3540
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3541
						$found = true;
3542
					}
3543
					if($found)
3544
						break;
3545
				}
3546
			}
3547
			break;
3548
		default: //This is for action and for altq
3549
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3550
			break;
3551
	}
3552
        return $l7rule;
3553
    }
3554
}
3555

    
3556
/*
3557
 * This function allows to return an array with all the used divert socket ports
3558
 */
3559
function get_divert_ports() {
3560
    global $layer7_rules_list;
3561
    $dports = array();
3562
    
3563
    foreach($layer7_rules_list as $l7r)
3564
        $dports[] = $l7r->GetRPort();
3565
    
3566
    return $dports;
3567
}
3568

    
3569
function &get_l7c_reference_to_me_in_config(&$name) {
3570
	global $config;
3571
	
3572
	$ptr = NULL;
3573
	
3574
	if(is_array($config['l7shaper']['container'])) {
3575
		foreach($config['l7shaper']['container'] as $key => $value) {
3576
			if($value['name'] == $name)
3577
				$ptr =& $config['l7shaper']['container'][$key];
3578
		}
3579
	}	
3580
	return $ptr;
3581
// $ptr can be null. has to be checked later
3582
}
3583

    
3584
function unset_l7_object_by_reference(&$name) {
3585
	global $config;
3586
        
3587
	if(is_array($config['l7shaper']['container'])) {
3588
		foreach($config['l7shaper']['container'] as $key => $value) {
3589
			if($value['name'] == $name) {
3590
				unset($config['l7shaper']['container'][$key]['l7rules']);
3591
				unset($config['l7shaper']['container'][$key]);
3592
				break;
3593
			}
3594
		}
3595
	}
3596
}
3597

    
3598
function read_layer7_config() {
3599
    global $layer7_rules_list, $config;
3600
    
3601
    $l7cs = &$config['l7shaper']['container'];
3602
    
3603
    $layer7_rules_list = array();
3604
    
3605
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3606
	return;
3607
    
3608
    foreach ($l7cs as $conf) {
3609
	if (empty($conf['name']))
3610
		continue; /* XXX: grrrrrr at php */ 
3611
        $root =& new layer7();
3612
        $root->ReadConfig($conf['name'],$conf);
3613
        $layer7_rules_list[$root->GetRName()] = &$root;
3614
    }
3615
}
3616

    
3617
function generate_layer7_files() {
3618
    global $layer7_rules_list, $g;
3619
    
3620
    read_layer7_config();
3621
    
3622
    if (!empty($layer7_rules_list)) {
3623
	if (!is_module_loaded("ipdivert.ko"))
3624
		mwexec("/sbin/kldload ipdivert.ko");
3625

    
3626
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3627
    }
3628
    
3629
    foreach($layer7_rules_list as $l7rules) {
3630
        if($l7rules->GetREnabled()) {
3631
            $filename = $l7rules->GetRName() . ".l7";
3632
            $path = "{$g['tmp_path']}/" . $filename;
3633
        
3634
            $rules = $l7rules->build_l7_rules();
3635
        
3636
            $fp = fopen($path,'w');
3637
            fwrite($fp,$rules);
3638
            fclose($fp);
3639
        }
3640
    }
3641
}
3642

    
3643
function layer7_start_l7daemon() {
3644
    global $layer7_rules_list, $g;
3645

    
3646
    /*
3647
     * XXX: ermal - Needed ?!
3648
     * read_layer7_config();
3649
     */
3650

    
3651
    foreach($layer7_rules_list as $l7rules) {
3652
        if($l7rules->GetREnabled()) {
3653
            $filename = $l7rules->GetRName() . ".l7";
3654
            $path = "{$g['tmp_path']}/" . $filename;
3655

    
3656
	    unset($l7pid);
3657
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3658
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3659
	    if (count($l7pid) > 0) {
3660
		log_error("Sending HUP signal to {$l7pid[0]}");
3661
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3662
	    } else {
3663
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3664
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3665
		mwexec_bg($ipfw_classifyd_init);
3666
	    }
3667
        }
3668
    }
3669
}
3670

    
3671
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3672
function generate_protocols_array() {
3673
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3674
	$protocols_new = array();
3675
	if(is_array($protocols)) {
3676
		foreach($protocols as $key => $proto) {
3677
			if (strstr($proto, ".pat"))
3678
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3679
		}
3680
		sort($protocols_new);
3681
	}		
3682
	return $protocols_new;
3683
}
3684

    
3685
function get_l7_unique_list() {
3686
	global $layer7_rules_list;
3687
	
3688
	$l7list = array();
3689
	if(is_array($layer7_rules_list)) 
3690
		foreach($layer7_rules_list as $l7c)
3691
			if($l7c->GetREnabled())
3692
				$l7list[] = $l7c->GetRName();
3693
	
3694
	return $l7list;
3695
}
3696

    
3697
// Disable a removed l7 container from the filter
3698
function cleanup_l7_from_rules(&$name) {
3699
	global $config;
3700

    
3701
	if(is_array($config['filter']['rule']))
3702
		foreach ($config['filter']['rule'] as $key => $rule) {
3703
			if ($rule['l7container'] == $name)
3704
				unset($config['filter']['rule'][$key]['l7container']);
3705
		}
3706
}
3707

    
3708
function get_dummynet_name_list() {
3709
	
3710
	$dn_name_list =& get_unique_dnqueue_list();
3711
	$dn_name = array();
3712
	if(is_array($dn_name_list))
3713
		foreach($dn_name_list as $key => $value)
3714
			$dn_name[] = $key;
3715
	
3716
	return $dn_name;
3717
	
3718
}
3719

    
3720
function get_altq_name_list() {
3721
	$altq_name_list =& get_unique_queue_list();
3722
	$altq_name = array();
3723
	if(is_array($altq_name_list))
3724
		foreach($altq_name_list as $key => $aqobj)
3725
			$altq_name[] = $key;
3726
		
3727
	return $altq_name;
3728
}
3729

    
3730
/*
3731
 * XXX: TODO Make a class shaper to hide all these function
3732
 * from the global namespace.
3733
 */
3734

    
3735
/* 
3736
 * This is a layer violation but for now there is no way 
3737
 * i can find to properly do this with PHP.
3738
 */
3739
function altq_set_default_queue($interface, $value) {
3740
	global $altq_list_queues;
3741
		
3742
	$altq_tmp =& $altq_list_queues[$interface];
3743
	if ($altq_tmp) {
3744
		if ($value) {
3745
			$altq_tmp->SetDefaultQueuePresent("true");
3746
		}
3747
		else {
3748
			$altq_tmp->SetDefaultQueuePresent("false");
3749
		}
3750
	}
3751
}
3752

    
3753
function altq_get_default_queue($interface) {
3754
	global $altq_list_queues;
3755

    
3756
	$altq_tmp = $altq_list_queues[$interface];
3757
	if ($altq_tmp)  
3758
		return $altq_tmp->GetDefaultQueuePresent(); 
3759
}
3760

    
3761
function altq_check_default_queues() {
3762
	global $altq_list_queues;
3763

    
3764
	$count = 0;
3765
	if (is_array($altq_list_queues)) {
3766
		foreach($altq_list_queues as $altq) {
3767
			if ($altq->GetDefaultQueuePresent())
3768
				$count++;
3769
		}
3770
	}
3771
	else  $count++;;
3772
	
3773
	return 0;
3774
}
3775

    
3776
function &get_unique_queue_list() {
3777
	global $altq_list_queues;
3778
	
3779
	$qlist = array();
3780
	if (is_array($altq_list_queues)) {
3781
		foreach ($altq_list_queues as $altq) {
3782
			$tmplist =& $altq->get_queue_list();
3783
			foreach ($tmplist as $qname => $link)
3784
				$qlist[$qname] = $link;	
3785
		}
3786
	}
3787
	return $qlist;
3788
}
3789

    
3790
function &get_unique_dnqueue_list() {
3791
	global $dummynet_pipe_list;
3792
	
3793
	$qlist = array();
3794
	if (is_array($dummynet_pipe_list)) {
3795
		foreach ($dummynet_pipe_list as $dn) {
3796
			$tmplist =& $dn->get_queue_list();
3797
			foreach ($tmplist as $qname => $link)
3798
				$qlist[$qname] = $link;	
3799
		}
3800
	}
3801
	return $qlist;
3802
}
3803

    
3804
function ref_on_altq_queue_list($parent, $qname) {
3805
	if (isset($GLOBALS['queue_list'][$qname]))
3806
		$GLOBALS['queue_list'][$qname]++;
3807
	else
3808
		$GLOBALS['queue_list'][$qname] = 1;
3809

    
3810
	unref_on_altq_queue_list($parent);
3811
}
3812

    
3813
function unref_on_altq_queue_list($qname) {
3814
	$GLOBALS['queue_list'][$qname]--;
3815
	if ($GLOBALS['queue_list'][$qname] <= 1)
3816
		unset($GLOBALS['queue_list'][$qname]);	
3817
}
3818

    
3819
function read_altq_config() {
3820
	global $altq_list_queues, $config;
3821
	$path = array();
3822
	
3823
	if (!is_array($config['shaper']))
3824
		$config['shaper'] = array();
3825
	if (!is_array($config['shaper']['queue']))
3826
		$config['shaper']['queue'] = array();
3827
	$a_int = &$config['shaper']['queue'];
3828

    
3829
	$altq_list_queues = array();
3830
	
3831
	if (!is_array($config['shaper']['queue']))
3832
		return;
3833

    
3834
	foreach ($a_int as $key => $conf) {
3835
				$int = $conf['interface'];
3836
				$root =& new altq_root_queue();
3837
				$root->SetInterface($int);
3838
				$altq_list_queues[$root->GetInterface()] = &$root;
3839
				$root->ReadConfig($conf);
3840
		array_push($path, $key);
3841
		$root->SetLink($path);
3842
		if (is_array($conf['queue'])) {
3843
			foreach ($conf['queue'] as $key1 => $q) {
3844
				array_push($path, $key1);
3845
				/* 
3846
				 * XXX: we compeletely ignore errors here but anyway we must have 
3847
				 *	checked them before so no harm should be come from this.
3848
				 */
3849
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3850
				array_pop($path);
3851
			} 	
3852
				}
3853
		array_pop($path);
3854
	}
3855
}
3856

    
3857
function read_dummynet_config() {
3858
	global $dummynet_pipe_list, $config;
3859
	$path = array();
3860
	$dnqueuenumber = 1;
3861
	$dnpipenumber = 1;
3862

    
3863
	if (!is_array($config['dnshaper']))
3864
		$config['dnshaper'] = array();
3865
	if (!is_array($config['dnshaper']['queue']))
3866
		$config['dnshaper']['queue'] = array();
3867
	$a_int = &$config['dnshaper']['queue'];
3868

    
3869
	$dummynet_pipe_list = array();
3870
	
3871
	if (!is_array($config['dnshaper']['queue'])
3872
		|| !count($config['dnshaper']['queue']))
3873
		return;
3874

    
3875
	foreach ($a_int as $key => $conf) {
3876
		if (empty($conf['name']))
3877
			continue; /* XXX: grrrrrr at php */ 
3878
		$root =& new dnpipe_class();
3879
		$root->ReadConfig($conf);
3880
		$root->SetNumber($dnpipenumber);	
3881
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3882
		array_push($path, $key);
3883
		$root->SetLink($path);
3884
		if (is_array($conf['queue'])) {
3885
			foreach ($conf['queue'] as $key1 => $q) {
3886
				array_push($path, $key1);
3887
				/* XXX: We cheat a little here till a better way is found. */
3888
				$q['number'] = $dnqueuenumber;
3889
				/* 
3890
				 * XXX: we compeletely ignore errors here but anyway we must have 
3891
				 *	checked them before so no harm should be come from this.
3892
				 */	
3893
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3894
				array_pop($path);
3895

    
3896
				$dnqueuenumber++;
3897
			} 	
3898
		}
3899
		array_pop($path);
3900
			
3901
		$dnpipenumber++;
3902
	}
3903
}
3904

    
3905
function get_interface_list_to_show() {
3906
	global $altq_list_queues, $config;
3907
	global $shaperIFlist;
3908

    
3909
	$tree = "";
3910
	foreach ($shaperIFlist as $shif => $shDescr) {
3911
		if ($altq_list_queues[$shif]) {
3912
			continue;
3913
		} else  {
3914
			if (!is_altq_capable(get_real_interface($shif)))
3915
				continue;
3916
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3917
		}
3918
	}
3919
	
3920
	return $tree;
3921
}
3922

    
3923
function filter_generate_altq_queues() {
3924
	global $altq_list_queues;
3925
	
3926
	read_altq_config();
3927

    
3928
	$altq_rules = "";
3929
	foreach ($altq_list_queues as $altq) 
3930
		$altq_rules .= $altq->build_rules();
3931

    
3932
	return $altq_rules;
3933
}
3934

    
3935
function filter_generate_dummynet_rules() {
3936
	global $g, $dummynet_pipe_list;
3937
	
3938
	read_dummynet_config();
3939
	
3940
	if (!empty($dummynet_pipe_list)) {
3941
		if (!is_module_loaded("dummynet.ko"))
3942
			mwexec("/sbin/kldload dummynet");
3943
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
3944
		//mwexec("pfctl -F dummynet");
3945
	}
3946

    
3947
	$dn_rules = "";
3948
	foreach ($dummynet_pipe_list as $dn) 
3949
		$dn_rules .= $dn->build_rules();
3950

    
3951
	if (!empty($dn_rules)) {
3952
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
3953
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
3954
	}
3955
	//return $dn_rules;
3956
}
3957

    
3958
function build_iface_without_this_queue($iface, $qname) {
3959
	global $g, $altq_list_queues;
3960

    
3961
	$altq =& $altq_list_queues[$iface];
3962
				if ($altq)
3963
						$scheduler = ": " . $altq->GetScheduler();
3964
	$form = "<tr><td width=\"20%\" >";
3965
	$form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
3966
	$form .= "</td></tr>";
3967
	$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
3968
	$form .= "<a href=\"firewall_shaper_queues.php?interface=";
3969
	$form .= $iface . "&queue=". $qname . "&action=add\">";
3970
	$form .= "<img src=\"";
3971
	$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
3972
	$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("Clone shaper/queue on this interface") . "\">";
3973
	$form .= gettext(" Clone shaper/queue on this interface") . "</a></td></tr>";
3974

    
3975
	return $form;
3976

    
3977
}
3978

    
3979

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

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

    
3994

    
3995

    
3996
?>
(38-38/53)