Project

General

Profile

Download (123 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[] = "The field '" . $pn . "' contains invalid characters.";
188
                }
189
        }
190

    
191
        for ($i = 0; $i < count($reqdfields); $i++) {
192
                if ($postdata[$reqdfields[$i]] == "") {
193
                        $input_errors[] = "The field '" . $reqdfieldsn[$i] . "' is required.";
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[] = "Bandwidth";
313
		$reqdfields[] = "bandwidthtype";
314
		$reqdfieldsn[] = "Bandwidthtype";
315
		
316
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
317
		
318
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
319
			$input_errors[] = "Bandwidth must be an integer.";
320
                if ($data['bandwidth'] < 0)
321
			$input_errors[] = "Bandwidth cannot be negative.";
322
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
323
			$input_errors[] = "Qlimit must be an integer.";
324
	 	if ($data['qlimit'] < 0)
325
			$input_errors[] = "Qlimit must be an positive.";
326
                if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig'])))
327
			$input_errors[] = "Tbrsize must be an integer.";
328
                if ($data['tbrconfig'] < 0)
329
			$input_errors[] = "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
		if ($conf['bandwidth'] <> "") {
337
			$this->SetBandwidth($conf['bandwidth']);
338
			if ($conf['bandwidthtype'] <> "")
339
				$this->SetBwscale($conf['bandwidthtype']);
340
		}
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
		if (isset($conf['name']))
353
			$this->SetQname($conf['name']);		
354
		if (!empty($conf['enabled']))
355
			$this->SetEnabled($conf['enabled']);
356
		else
357
			$this->SetEnabled("");
358
	}
359

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

    
378
	function &get_queue_list($q = null) {
379
		$qlist = array();
380

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

    
389
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
390

    
391
		if (!is_array($this->queues))
392
			$this->queues = array();
393

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

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

    
444
		return $q;
445
	}
446

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

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

    
473
	function build_tree() {
474
		global $shaperIFlist;
475

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

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

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

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

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

    
563
		return $javascript;
564
	}
565
	
566
	function build_shortform() {
567
		global $g;
568

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

    
588
		return $form;
589

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

    
669

    
670
		return $form;
671
	}
672

    
673
	function update_altq_queue_data(&$data) { 
674
		$this->ReadConfig($data);
675
	}
676
	
677
	/*
678
	 * Should call on each of it queues and subqueues
679
	 * the same function much like build_rules();
680
	 */
681
	function wconfig() { 
682
		$cflink = &get_reference_to_me_in_config($this->GetLink());
683
		if (!is_array($cflink))
684
			$cflink = array();
685
		$cflink['interface'] = $this->GetInterface();	
686
		$cflink['name'] = $this->GetQname();
687
		$cflink['scheduler'] = $this->GetScheduler();
688
		$cflink['bandwidth'] = $this->GetBandwidth();
689
		$cflink['bandwidthtype'] = $this->GetBwscale();
690
		$cflink['qlimit'] = trim($this->GetQlimit());
691
		if (empty($cflink['qlimit']))
692
			unset($cflink['qlimit']);
693
		$cflink['tbrconfig'] = trim($this->GetTbrConfig());
694
		if (empty($cflink['tbrconfig']))
695
			unset($cflink['tbrconfig']);
696
		$cflink['enabled'] = $this->GetEnabled();
697
		if (empty($cflink['enabled']))
698
			unset($cflink['enabled']);
699
	}
700

    
701
}
702

    
703
class priq_queue {
704
	var $qname;
705
	var $qinterface; 
706
	var $qlimit;
707
	var $qpriority;
708
	var $description;
709
	var $isparent;
710
	var $qbandwidth;
711
	var $qbandwidthtype;
712
	var $qdefault = "";
713
	var $qrio = "";
714
	var $qred = "";
715
	var $qecn = "";
716
	var $qack;
717
	var $qenabled = "";
718
	var $qparent;
719
	var $link;
720
	var $available_bw; /* in b/s */
721

    
722
	/* This is here to help with form building and building rules/lists */
723
		var $subqueues = array();
724

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

    
836
	function build_javascript() {
837
		$javascript = "<script type=\"text/javascript\">";
838
		$javascript .= "function mySuspend() { \n";
839
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);\n";
840
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
841
		$javascript .= "else if (document.all)\n";
842
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
843
		$javascript .= "}\n";
844

    
845
		$javascript .= "function myResume() {\n";
846
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
847
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
848
		$javascript .= "else if (document.all)\n";
849
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
850
		$javascript .= "}\n";
851
		$javascript .= "</script>";
852
		
853
		return $javascript;
854
	}
855
	
856
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
857

    
858
	/* 
859
	 * Currently this will not be called unless we decide to clone a whole 
860
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
861
	 */
862
	 function copy_queue($interface, &$cflink) {
863

    
864
 		$cflink['name'] = $this->GetQname();
865
                $cflink['interface'] = $interface;
866
                $cflink['qlimit'] = $this->GetQlimit();
867
                $cflink['priority'] = $this->GetQpriority();
868
                $cflink['description'] = $this->GetDescription();
869
                $cflink['enabled'] = $this->GetEnabled();
870
                $cflink['default'] = $this->GetDefault();
871
                $cflink['red'] = $this->GetRed();
872
                $cflink['rio'] = $this->GetRio();
873
                $cflink['ecn'] = $this->GetEcn();
874

    
875
                if (is_array($this->subqueues)) {
876
                        $cflinkp['queue'] = array();
877
                        foreach ($this->subqueues as $q) {
878
				 $cflink['queue'][$q->GetQname()] = array();
879
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
880
			}
881
                }
882

    
883
	 }
884

    
885
	function clean_queue($sched) {
886
		clean_child_queues($sched, $this->GetLink());
887
		if (is_array($this->subqueues)) {
888
			foreach ($this->subqueues as $q)
889
				$q->clean_queue($sched);
890
		}
891
	}
892

    
893
        function &get_queue_list(&$qlist) {
894
		$qlist[$this->GetQname()] = & $this;
895
		if (is_array($this->subqueues)) {
896
			foreach ($this->subqueues as $queue)
897
				$queue->get_queue_list($qlist);
898
		}
899
	}
900

    
901
	function delete_queue() {
902
		unref_on_altq_queue_list($this->GetQname());
903
		if ($this->GetDefault())
904
				altq_set_default_queue($this->GetInterface(), "false");
905
		cleanup_queue_from_rules($this->GetQname());
906
		unset_object_by_reference($this->GetLink());
907
	}
908
	
909
	function delete_all() {
910
                if (count($this->subqueues)) {
911
                        foreach ($this->subqueues as $q) {
912
                                $q->delete_all();
913
                                unset_object_by_reference($q->GetLink());
914
                                unset($q);
915
                        }
916
                        unset($this->subqueues);
917
                }
918
        }
919

    
920
	 function &find_queue($interface, $qname) { 
921
		if ($qname == $this->GetQname())
922
			return $this; 
923
	}
924
	
925
	function find_parentqueue($interface, $qname) { return; }
926
		
927
	function validate_input($data, &$input_errors) {
928
	
929
		$reqdfields[] = "name";
930
		$reqdfieldsn[] = "Name";
931
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
932

    
933
		if ($data['priority'] && (!is_numeric($data['priority'])
934
						|| ($data['priority'] < 1) || ($data['priority'] > 15))) {
935
					$input_errors[] = "The priority must be an integer between 1 and 15.";
936
		}
937
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
938
				$input_errors[] = "Queue limit must be an integer";
939
		if ($data['qlimit'] < 0)
940
				$input_errors[] = "Queue limit must be positive";
941
		if (!preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
942
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
943
		
944
	}
945

    
946
	function ReadConfig(&$q) {
947
		if (isset($q['name']))
948
				$this->SetQname($q['name']);
949
		if (isset($q['interface']))
950
				$this->SetInterface($q['interface']);
951
		if ($q['bandwidth'] <> "") {
952
			$this->SetBandwidth($q['bandwidth']);
953
			if ($q['bandwidthtype'] <> "")
954
				$this->SetBwscale($q['bandwidthtype']);
955
		}
956
		if (!empty($q['qlimit']))
957
			$this->SetQlimit($q['qlimit']);
958
		else
959
			$this->SetQlimit(""); // Default
960
		if (!empty($q['priority']))
961
			$this->SetQPriority($q['priority']);
962
		else
963
			$this->SetQpriority("");
964
		if (!empty($q['description']))
965
			$this->SetDescription($q['description']);
966
		else
967
			$this->SetDescription("");
968
		if (!empty($q['red']))
969
			$this->SetRed($q['red']);
970
		else
971
			$this->SetRed();
972
		if (!empty($q['rio']))
973
			$this->SetRio($q['rio']);
974
		else
975
			$this->SetRio();
976
		if (!empty($q['ecn']))
977
			$this->SetEcn($q['ecn']);
978
		else
979
			$this->SetEcn();
980
		if (!empty($q['default']))
981
			$this->SetDefault($q['default']);
982
		else
983
			$this->SetDefault();
984
		if (!empty($q['enabled']))
985
			$this->SetEnabled($q['enabled']);
986
		else
987
			$this->SetEnabled("");
988

    
989
	}
990

    
991
	function build_tree() {
992
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
993
		$tree .= "\" ";
994
		$tmpvalue = $this->GetDefault();
995
		if (!empty($tmpvalue))
996
			$tree .= " class=\"navlnk\"";
997
		$tree .= " >" . $this->GetQname() . "</a>";
998
		/* 
999
		 * Not needed here!
1000
		 * if (is_array($queues) {
1001
		 *	  $tree .= "<ul>";
1002
		 *	  foreach ($q as $queues) 
1003
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1004
		 *	  endforeach	
1005
		 *	  $tree .= "</ul>";
1006
		 * }
1007
		 */
1008

    
1009
		$tree .= "</li>"; 
1010

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

    
1057
		$pfq_rule .= " \n";
1058

    
1059
		return $pfq_rule;
1060
	}
1061

    
1062
	/*
1063
	 * To return the html form to show to user
1064
	 * for getting the parameters.
1065
	 * Should do even for first time when the
1066
	 * object is created and later when we may
1067
	 * need to update it.
1068
	 */
1069
	function build_form() {
1070
		$form .= "<tr>";
1071
		$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">";
1072
		$form .= "Queue Name</td><td width=\"78%\" class=\"vtable\">";
1073
		$form .= "<input name=\"name\" type=\"text\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1074
		$form .= htmlspecialchars($this->GetQname());
1075
		$form .= "\">";
1076
		$form .= "<br> <span class=\"vexpl\">Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.";
1077
		$form .= "</span></td>";
1078
		$form .= "</tr><tr>";
1079
		$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Priority</td>";
1080
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
1081
		$form .= htmlspecialchars($this->GetQpriority());
1082
		$form .= "\">";
1083
		$form .= "<br> <span class=\"vexpl\">For hfsc, the range is 0 to 7. The default is 1.  Hfsc queues with a higher priority are preferred in the case of overload.</span></td>";
1084
		$form .= "</tr>";
1085
		$form .= "</tr>";
1086
		$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Queue limit</td>";
1087
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"5\" value=\"";
1088
		$form .= htmlspecialchars($this->GetQlimit());
1089
		$form .= "\">";
1090
		$form .= "<br> <span class=\"vexpl\">Queue limit in packets per second."; 
1091
		$form .= "</span></td>";
1092
		$form .= "<tr>";
1093
		$form .= "<td width=\"22%\" valign=\"top\" class=\"vncell\">Scheduler options</td>";
1094
		$form .= "<td width=\"78%\" class=\"vtable\">";
1095
		$tmpvalue = $this->GetDefault();	
1096
		if (!empty($tmpvalue)) { 
1097
			$form .= "<input type=\"checkbox\" id=\"default\" CHECKED name=\"default\" value=\"default\"";
1098
			$form .= "> Default queue<br>";
1099
		} else {
1100
			$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\" value=\"default\"";
1101
			$form .= "> Default queue<br>";
1102
		}
1103
		$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\" value=\"red\" ";
1104
		$tmpvalue = $this->GetRed();
1105
		if(!empty($tmpvalue)) 
1106
			$form .=  " CHECKED";
1107
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">Random Early Detection</a><br>";
1108
		$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\" value=\"rio\"";
1109
		$tmpvalue = $this->GetRio();
1110
		if(!empty($tmpvalue)) 
1111
			$form .=  " CHECKED";
1112
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">Random Early Detection In and Out</a><br>";
1113
		$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\" value=\"ecn\"";
1114
		$tmpvalue = $this->GetEcn();
1115
		if(!empty($tmpvalue)) 
1116
			$form .=  " CHECKED";
1117
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">Explicit Congestion Notification</a><br>";
1118
		$form .= "<span class=\"vexpl\"><br>Select options for this queue";
1119
		$form .= "</tr><tr>";
1120
		$form .= "<td width=\"22%\" class=\"vncellreq\">Description</td>";
1121
		$form .= "<td width=\"78%\" class=\"vtable\">";
1122
		$form .= "<input type=\"text\" name=\"description\" size=\"50%\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\"  >";
1123
		$form .= "</td></tr>";
1124
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1125
		$form .= " value=\"".$this->GetInterface()."\">";
1126

    
1127
		return $form;
1128
	}
1129

    
1130
	function build_shortform() {
1131
		/* XXX: Hacks in site. Mostly layer violations!  */
1132
		global $g, $altq_list_queues;
1133

    
1134
		$altq =& $altq_list_queues[$this->GetInterface()];
1135
		if ($altq)
1136
			$scheduler = ": " . $altq->GetScheduler();
1137
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
1138
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=" . $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
1139
		$form .= "</td></tr>";
1140
		/* 
1141
		 * XXX: Hack in sight maybe fix with a class that wraps all
1142
		 * of this layer violations
1143
		 */
1144
		$form .= "<tr>";
1145
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1146
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
1147
		$form .= "</td><td width=\"50%\"></td></tr>";
1148
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1149
		$tmpvalue = $this->GetQpriority();
1150
		if (!empty($tmpvalue))
1151
			$form .= "Priority: on </td></tr>";
1152
		$tmpvalue = $this->GetDefault();
1153
		if (!empty($tmpvalue))
1154
			$form .= "<tr><td class=\"vncellreq\">Default: on </td></tr>";
1155
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1156
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1157
		$form .= $this->GetInterface() . "&queue=";
1158
		$form .= $this->GetQname() . "&action=delete\">";
1159
		$form .= "<img src=\"";
1160
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1161
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Delete queue from interface\">";
1162
		$form .= "<span>Delete queue from interface</span></a></td></tr>";
1163
		
1164
		return $form;
1165

    
1166
	}
1167

    
1168
		function update_altq_queue_data(&$q) { 
1169
		$this->ReadConfig($q);
1170
	}
1171

    
1172
	function wconfig() {
1173
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1174
		if (!is_array($cflink))
1175
			$cflink = array();
1176
		$cflink['name'] = $this->GetQname();
1177
		$cflink['interface'] = $this->GetInterface();
1178
		$cflink['qlimit'] = trim($this->GetQlimit());
1179
		if (empty($cflink['qlimit']))
1180
			unset($cflink['qlimit']);
1181
		$cflink['priority'] = trim($this->GetQpriority());
1182
		if (empty($cflink['priority']))
1183
			unset($cflink['priority']);
1184
		$cflink['description'] = trim($this->GetDescription());
1185
		if (empty($cflink['description']))
1186
			unset($cflink['description']);
1187
		$cflink['enabled'] = trim($this->GetEnabled());
1188
		if (empty($cflink['enabled']))
1189
			unset($cflink['enabled']);
1190
		$cflink['default'] = trim($this->GetDefault());
1191
		if (empty($cflink['default']))
1192
			unset($cflink['default']);
1193
		$cflink['red'] = trim($this->GetRed());
1194
		if (empty($cflink['red']))
1195
			unset($cflink['red']);
1196
		$cflink['rio'] = trim($this->GetRio());
1197
		if (empty($cflink['rio']))
1198
			unset($cflink['rio']);
1199
		$cflink['ecn'] = trim($this->GetEcn());
1200
		if (empty($cflink['ecn']))
1201
			unset($cflink['ecn']);
1202
	}
1203
}
1204

    
1205
class hfsc_queue extends priq_queue {
1206
	/* realtime */
1207
	var $realtime;
1208
	var $r_m1;
1209
	var $r_d;
1210
	var $r_m2;
1211
	/* linkshare */
1212
	var $linkshare;
1213
	var $l_m1;
1214
	var $l_d;
1215
	var $l_m2;
1216
	/* upperlimit */
1217
	var $upperlimit;
1218
	var $u_m1;
1219
	var $u_d;
1220
	var $u_m2;
1221

    
1222
	/*
1223
	 * HFSC can have nested queues.
1224
	 */
1225

    
1226
	function CanHaveChildren() {
1227
		return true;
1228
	}
1229
	function GetRealtime() {
1230
           return $this->realtime;
1231
	}
1232
	function GetR_m1() {
1233
		return $this->r_m1;
1234
	}
1235
	function GetR_d() {
1236
		return $this->r_d;
1237
	}
1238
	function GetR_m2() {
1239
		return $this->r_m2;
1240
	}
1241
	function SetRealtime() {
1242
		$this->realtime = "on";
1243
	}
1244
	function DisableRealtime() {
1245
		$this->realtime = "";
1246
	}
1247
	function SetR_m1($value) {
1248
		$this->r_m1 = $value;
1249
	}
1250
	function SetR_d($value) {
1251
		$this->r_d = $value;
1252
	}
1253
	function SetR_m2($value) {
1254
		$this->r_m2 = $value;
1255
	}
1256
	function GetLinkshare() {
1257
		return $this->linkshare;
1258
	}
1259
	function DisableLinkshare() {
1260
		$this->linkshare = "";
1261
	}
1262
	function GetL_m1() {
1263
		return $this->l_m1;
1264
	}
1265
	function GetL_d() {
1266
		return $this->l_d;
1267
	}
1268
	function GetL_m2() {
1269
		return $this->l_m2;
1270
	}
1271
	function SetLinkshare() {
1272
		$this->linkshare = "on";
1273
	}
1274
	function SetL_m1($value) {
1275
		$this->l_m1 = $value;
1276
	}
1277
	function SetL_d($value) {
1278
		$this->l_d = $value;
1279
	}
1280
	function SetL_m2($value) {
1281
		$this->l_m2 = $value;
1282
	}
1283
	function GetUpperlimit() {
1284
		return $this->upperlimit;
1285
	}
1286
	function GetU_m1() {
1287
		return $this->u_m1;
1288
	}
1289
	function GetU_d() {
1290
		return $this->u_d;
1291
	}
1292
	function GetU_m2() {
1293
		return $this->u_m2;
1294
	}
1295
	function SetUpperlimit() {
1296
		$this->upperlimit = "on";
1297
	}
1298
	function DisableUpperlimit() {
1299
		$this->upperlimit = "";
1300
	}
1301
	function SetU_m1($value) {
1302
		$this->u_m1 = $value;
1303
	}
1304
	function SetU_d($value) {
1305
		$this->u_d = $value;
1306
	}
1307
	function SetU_m2($value) {
1308
		$this->u_m2 = $value;
1309
	}
1310

    
1311
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1312

    
1313
		if (!is_array($this->subqueues))
1314
			$this->subqueues = array();
1315
		$q =& new hfsc_queue();
1316
		$q->SetInterface($this->GetInterface());
1317
		$q->SetParent(&$this);
1318
		$q->ReadConfig($qname);
1319
		$q->validate_input($qname, $input_errors);
1320
		if (count($input_errors)) {
1321
			return $q;
1322
		}
1323

    
1324
		$q->SetEnabled("on");
1325
		$q->SetLink($path);
1326
		switch ($q->GetBwscale()) {
1327
		case "%":
1328
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1329
			break;
1330
		default:
1331
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1332
			break;
1333
		}
1334
		$q->SetAvailableBandwidth($myBw);
1335
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1336

    
1337
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1338
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1339
		if (is_array($qname['queue'])) {
1340
			foreach ($qname['queue'] as $key1 => $que) {
1341
				array_push($path, $key1);
1342
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1343
				array_pop($path);
1344
			}
1345
		}
1346
	
1347
		return $q;
1348
	}
1349

    
1350
        function copy_queue($interface, &$cflink) {
1351

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

    
1435
		if (is_array($this->subqueues)) {
1436
			$cflinkp['queue'] = array();
1437
			foreach ($this->subqueues as $q) {
1438
				$cflink['queue'][$q->GetQname()] = array();
1439
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1440
			}
1441
		}
1442
	}
1443

    
1444
	function delete_queue() { 
1445
		unref_on_altq_queue_list($this->GetQname());
1446
		$tmpvalue = $this->GetDefault();
1447
		if (!empty($tmpvalue)) 
1448
			altq_set_default_queue($this->GetInterface(), "false");
1449
		cleanup_queue_from_rules($this->GetQname());
1450
		$parent =& $this->GetParent();
1451
		foreach ($this->subqueues as $q)  {
1452
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1453
			$q->delete_queue();
1454
		}
1455
		unset_object_by_reference($this->GetLink());
1456
	}
1457

    
1458
	/*
1459
	 * Should search even its children
1460
	 */
1461
	function &find_queue($interface, $qname) {
1462
		if ($qname == $this->GetQname()) 
1463
			return $this;
1464

    
1465
		foreach ($this->subqueues as $q) {
1466
			$result =& $q->find_queue("", $qname);
1467
			if ($result)
1468
				return $result;
1469
		}
1470
	}
1471

    
1472
	function &find_parentqueue($interface, $qname) {
1473
		if ($this->subqueues[$qname]) 
1474
			return $this;
1475
		foreach ($this->subqueues as $q) {
1476
			$result = $q->find_parentqueue("", $qname);
1477
			if ($result)
1478
				return $result;
1479
		}
1480
	}
1481
	
1482
	function validate_input($data, &$input_errors) {
1483
		parent::validate_input($data, $input_errors);
1484
		
1485
		$reqdfields[] = "bandwidth";
1486
		$reqdfieldsn[] = "Bandwidth";
1487
		$reqdfields[] = "bandwidthtype";
1488
		$reqdfieldsn[] = "Bandwidthtype";
1489

    
1490
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1491
		
1492
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1493
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1494
                        	$input_errors[] = "Bandwidth must be an integer.";
1495

    
1496
                	if ($data['bandwidth'] < 0)
1497
                        	$input_errors[] = "Bandwidth cannot be negative.";
1498

    
1499
			if ($data['bandwidthtype'] == "%") {
1500
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1501
					$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1502
			}
1503
		/*
1504
			$parent =& $this->GetParent();
1505
			switch ($data['bandwidthtype']) {
1506
			case "%":
1507
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1508
			default:
1509
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1510
				break;
1511
			}
1512
			if ($parent->GetAvailableBandwidth() < $myBw)
1513
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1514
		*/
1515
		}
1516

    
1517
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1518
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1519
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1520
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1521
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1522
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1523
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1524
			$input_errors[] = ("upperlimit d value needs to be numeric");
1525
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1526
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1527

    
1528
		/*
1529
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1530
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1531
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1532
			if (floatval($bw_1) < floatval($bw_2)) 
1533
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1534

    
1535
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1536
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1537
		}
1538
		*/
1539
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1540
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1541
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1542
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1543
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1544
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1545
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1546
			$input_errors[] = ("linkshare d value needs to be numeric");
1547
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1548
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1549
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1550
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1551
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1552
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1553

    
1554
		/*
1555
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1556
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1557
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1558
                	if (floatval($bw_1) < floatval($bw_2))
1559
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1560

    
1561
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1562
                        	$input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1563
		}
1564
		*/
1565

    
1566
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1567
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1568
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1569
			$input_errors[] = ("realtime d value needs to be numeric");
1570
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1571
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1572

    
1573
		/*
1574
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1575
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1576
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1577
                	if (floatval($bw_1) < floatval($bw_2))
1578
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1579

    
1580
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1581
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1582
		}
1583
		*/
1584

    
1585
	}
1586

    
1587
	function ReadConfig(&$cflink) {
1588
		if (!empty($cflink['linkshare'])) {
1589
			if (!empty($cflink['linkshare1'])) {
1590
				$this->SetL_m1($cflink['linkshare1']);
1591
                                $this->SetL_d($cflink['linkshare2']);
1592
				$this->SetLinkshare();
1593
			}
1594
			if (!empty($cflink['linkshare3'])) {
1595
                                $this->SetL_m2($cflink['linkshare3']);
1596
				$this->SetLinkshare();
1597
			}
1598
		} else
1599
			$this->DisableLinkshare();
1600
		if (!empty($cflink['realtime'])) {
1601
                        if (!empty($cflink['realtime1'])) {
1602
                                $this->SetR_m1($cflink['realtime1']);
1603
                                $this->SetR_d($cflink['realtime2']);
1604
				$this->SetRealtime();
1605
			}
1606
                        if (!empty($cflink['realtime3'])) {
1607
                                $this->SetR_m2($cflink['realtime3']);
1608
				$this->SetRealtime();
1609
			}
1610
		} else
1611
			$this->DisableRealtime(); 
1612
		if (!empty($cflink['upperlimit'])) {
1613
                        if (!empty($cflink['upperlimit1'])) {
1614
                                $this->SetU_m1($cflink['upperlimit1']);
1615
                                $this->SetU_d($cflink['upperlimit2']);
1616
				$this->SetUpperlimit();
1617
			}
1618
                        if (!empty($cflink['upperlimit3'])) {
1619
                                $this->SetU_m2($cflink['upperlimit3']);
1620
				$this->SetUpperlimit();
1621
			}
1622
		} else
1623
			$this->DisableUpperlimit();
1624
		parent::ReadConfig($cflink);
1625
	}
1626

    
1627
	function build_tree() {
1628
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1629
		$tree .= "\" ";
1630
		$tmpvalue = $this->GetDefault();
1631
		if (!empty($tmpvalue))
1632
			$tree .= " class=\"navlnk\"";
1633
		$tree .= " >" . $this->GetQname() . "</a>";
1634
		if (is_array($this->subqueues)) {
1635
			$tree .= "<ul>";
1636
			foreach ($this->subqueues as $q)  {
1637
				$tree .= $q->build_tree();
1638
			}	
1639
			$tree .= "</ul>";
1640
		}
1641
		$tree .= "</li>";
1642
		return $tree;
1643
	}
1644

    
1645
	/* Even this should take children into consideration */
1646
	function build_rules() {
1647

    
1648
		$pfq_rule = " queue ". $this->qname;
1649
		if ($this->GetInterface())
1650
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1651
		if ($this->GetBandwidth() && $this->GetBwscale())
1652
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1653
				
1654
		$tmpvalue = $this->GetQlimit();
1655
		if (!empty($tmpvalue))
1656
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1657
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1658
			$pfq_rule .= " hfsc ( ";
1659
			$tmpvalue = $this->GetRed();
1660
			if (!empty($tmpvalue)) {
1661
				$comma = 1;
1662
				$pfq_rule .= " red ";
1663
			}
1664
			
1665
			$tmpvalue = $this->GetRio();
1666
			if (!empty($tmpvalue)) {
1667
				if ($comma) 
1668
					$pfq_rule .= " ,";
1669
				$comma = 1;
1670
				$pfq_rule .= " rio ";
1671
			}
1672
			$tmpvalue = $this->GetEcn();
1673
			if (!empty($tmpvalue)) {
1674
				if ($comma) 
1675
					$pfq_rule .= " ,";
1676
				$comma = 1;
1677
				$pfq_rule .= " ecn ";
1678
			}
1679
			$tmpvalue = $this->GetDefault();
1680
			if (!empty($tmpvalue)) {
1681
				if ($comma)
1682
					$pfq_rule .= " ,";
1683
				$comma = 1;
1684
				$pfq_rule .= " default ";
1685
			}
1686

    
1687
			if ($this->GetRealtime() <> "")  {
1688
				if ($comma) 
1689
					$pfq_rule .= " , ";
1690
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1691
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1692
				else  if ($this->GetR_m2() <> "")
1693
					$pfq_rule .= " realtime " . $this->GetR_m2();
1694
				$comma = 1;
1695
			}
1696
			if ($this->GetLinkshare() <> "") {
1697
				if ($comma)
1698
					$pfq_rule .= " ,";
1699
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1700
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1701
				else if ($this->GetL_m2() <> "")
1702
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1703
				$comma = 1;
1704
			}
1705
			if ($this->GetUpperlimit() <> "") {
1706
				if ($comma)
1707
					$pfq_rule .= " ,";
1708
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1709
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1710
				else if ($this->GetU_m2() <> "")
1711
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1712
			}
1713
			$pfq_rule .= " ) ";
1714
		}
1715
		if (count($this->subqueues)) {
1716
			$i = count($this->subqueues);
1717
			$pfq_rule .= " { ";
1718
			foreach ($this->subqueues as $qkey => $qnone) {
1719
				if ($i > 1) {
1720
					$i--;
1721
					$pfq_rule .= " {$qkey}, ";
1722
				} else
1723
					$pfq_rule .= " {$qkey} ";
1724
			}
1725
			$pfq_rule .= " } \n";
1726
			foreach ($this->subqueues as $q)
1727
				$pfq_rule .= $q->build_rules();
1728
		}
1729

    
1730
		 $pfq_rule .= " \n";
1731
			
1732
		return $pfq_rule;
1733
	}
1734

    
1735
	function build_javascript() {
1736
		$javascript = parent::build_javascript();
1737
		$javascript .= "<script type=\"text/javascript\">";
1738
		$javascript .= "function enable_realtime(enable_over) { \n";
1739
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1740
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1741
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1742
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1743
		$javascript .= " } else { \n";
1744
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1745
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1746
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1747
		$javascript .= " } \n";
1748
		$javascript .= " } \n";
1749
		$javascript .= "function enable_linkshare(enable_over) { \n";
1750
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1751
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1752
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1753
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1754
		$javascript .= " } else { \n";
1755
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1756
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1757
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1758
		$javascript .= " } \n";
1759
		$javascript .= " } \n";
1760
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1761
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1762
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1763
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1764
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1765
		$javascript .= " } else { \n";
1766
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1767
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1768
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1769
		$javascript .= " } \n";
1770
			
1771
		$javascript .= "} \n";
1772
		$javascript .= "</script>";
1773

    
1774
		return $javascript;
1775
	}
1776

    
1777
	function build_form() {
1778
		$form = "<tr>";
1779
		$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
1780
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1781
		$form .= htmlspecialchars($this->GetBandwidth());
1782
		$form .= "\">";
1783
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1784
		$form .= "<option value=\"Gb\"";
1785
		if ($this->GetBwscale() == "Gb")
1786
			$form .= " selected=\"yes\"";
1787
		$form .= ">Gbit/s</option>";
1788
		$form .= "<option value=\"Mb\"";
1789
		if ($this->GetBwscale() == "Mb")
1790
			$form .= " selected=\"yes\"";
1791
		$form .= ">Mbit/s</option>";
1792
		$form .= "<option value=\"Kb\"";
1793
		if ($this->GetBwscale() == "Kb")
1794
			$form .= " selected=\"yes\"";
1795
		$form .= ">Kbit/s</option>";
1796
		$form .= "<option value=\"\"";
1797
		if ($this->GetBwscale() == "b")
1798
			$form .= " selected=\"yes\"";
1799
		$form .= ">Bit/s</option>";
1800
		$form .= "<option value=\"%\"";
1801
		if ($this->GetBwscale() == "%")
1802
			$form .= " selected=\"yes\"";
1803
		$form .= ">%</option>";
1804
		$form .= "</select> <br>";
1805
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
1806
		$form .= "</span></td>";
1807
		$form .= parent::build_form();
1808
		$form .= "<tr>";
1809
		$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Service Curve (sc)</td>";
1810
		$form .= "<td width=\"78%\" class=\"vtable\">";
1811
		$form .= "<table>";
1812
		$form .= "<tr><td>&nbsp;</td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>";
1813
		$form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\"";
1814
		if($this->GetUpperlimit()<> "") 
1815
			$form .=  " CHECKED ";
1816
		$form .= "onChange=\"enable_upperlimit()\"> Upperlimit:</td><td><input size=\"6\" value=\"";
1817
		$form .= htmlspecialchars($this->GetU_m1());
1818
		$form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" ";
1819
		if ($this->GetUpperlimit() == "")
1820
			$form .= " disabled";
1821
		$form .= "></td><td><input size=\"6\" value=\"";
1822
		$form .= htmlspecialchars($this->GetU_d());
1823
		$form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" ";
1824
		if ($this->GetUpperlimit() == "")
1825
			$form .= " disabled";
1826
		$form .= "></td><td><input size=\"6\" value=\"";
1827
		$form .= htmlspecialchars($this->GetU_m2());
1828
		$form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" ";
1829
		if ($this->GetUpperlimit() == "")
1830
			$form .= " disabled";
1831
		$form .= "></td><td>The maximum allowed bandwidth for the queue.</td></tr>";
1832
		$form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\"";
1833
		if($this->GetRealtime() <> "") 
1834
			$form .=  " CHECKED ";
1835
		$form .= "onChange=\"enable_realtime()\"> Real time:</td><td><input size=\"6\" value=\"";
1836
		$form .= htmlspecialchars($this->GetR_m1());
1837
		$form .= "\" id=\"realtime1\" name=\"realtime1\" ";
1838
		if ($this->GetRealtime() == "")
1839
			$form .= " disabled";
1840
		$form .= "></td><td><input size=\"6\" value=\"";
1841
		$form .= htmlspecialchars($this->GetR_d());
1842
		$form .= "\" id=\"realtime2\" name=\"realtime2\" ";
1843
		if ($this->GetRealtime() == "")
1844
			$form .= " disabled";
1845
		$form .= "></td><td><input size=\"6\" value=\"";
1846
		$form .= htmlspecialchars($this->GetR_m2());
1847
		$form .= "\" id=\"realtime3\" name=\"realtime3\" ";
1848
		if ($this->GetRealtime() == "")
1849
			$form .= " disabled";
1850
		$form .= "></td><td>The minimum required bandwidth for the queue.</td></tr>";
1851
		$form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" id=\"linkshare\" name=\"linkshare\"";
1852
		if($this->GetLinkshare() <> "") 
1853
			$form .=  " CHECKED ";
1854
		$form .= "onChange=\"enable_linkshare()\"> Link share:</td><td><input size=\"6\" value=\"";
1855
		$form .= htmlspecialchars($this->GetL_m1());
1856
		$form .= "\" id=\"linkshare1\" name=\"linkshare1\" ";
1857
		if ($this->GetLinkshare() == "")
1858
			$form .= " disabled";
1859
		$form .= "></td><td><input size=\"6\" value=\"";
1860
		$form .= htmlspecialchars($this->GetL_d());
1861
		$form .= "\" id=\"linkshare2\" name=\"linkshare2\" ";
1862
		if ($this->GetLinkshare() == "")
1863
			$form .= " disabled";
1864
		$form .= "></td><td><input size=\"6\" value=\"";
1865
		$form .= htmlspecialchars($this->GetL_m2());
1866
		$form .= "\" id=\"linkshare3\" name=\"linkshare3\" ";
1867
		if ($this->GetLinkshare() == "")
1868
			$form .= " disabled";
1869
		$form .= "></td><td>The bandwidth share of a backlogged queue - this overrides priority.</td></tr>";
1870
		$form .= "</table><br>";
1871
		$form .= "The format for service curve specifications is (m1, d, m2).  m2 controls";
1872
		$form .= "the bandwidth assigned to the queue.  m1 and d are optional and can be";
1873
		$form .= "used to control the initial bandwidth assignment.  For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value";
1874
		$form .= "given in m2.";
1875
		$form .= "</span></td>";
1876
		$form .= "</tr>";
1877

    
1878
		return $form;
1879
	}
1880

    
1881
	function update_altq_queue_data(&$data) { 
1882
		$this->ReadConfig($data);
1883
	}
1884

    
1885
	function wconfig() {
1886
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1887
		if (!is_array($cflink))
1888
			$cflink = array();
1889
		$cflink['name'] = $this->GetQname();
1890
		$cflink['interface'] = $this->GetInterface();
1891
		$cflink['qlimit'] = trim($this->GetQlimit());
1892
		if (empty($cflink['qlimit']))
1893
			unset($cflink['qlimit']);
1894
		$cflink['priority'] = $this->GetQpriority();
1895
		if (empty($cflink['priority']))
1896
			unset($cflink['priority']);
1897
		$cflink['description'] = $this->GetDescription();
1898
		if (empty($cflink['description']))
1899
			unset($cflink['description']);
1900
		$cflink['bandwidth'] = $this->GetBandwidth();
1901
		$cflink['bandwidthtype'] = $this->GetBwscale();
1902
		$cflink['enabled'] = $this->GetEnabled();
1903
		if (empty($cflink['enabled']))
1904
			unset($cflink['enabled']);
1905
		$cflink['default'] = $this->GetDefault();
1906
		if (empty($cflink['default']))
1907
			unset($cflink['default']);
1908
		$cflink['red'] = trim($this->GetRed());
1909
		if (empty($cflink['red']))
1910
			unset($cflink['red']);
1911
		$cflink['rio'] = $this->GetRio();
1912
		if (empty($cflink['rio']))
1913
			unset($cflink['rio']);
1914
		$cflink['ecn'] = trim($this->GetEcn());
1915
		if (empty($cflink['ecn']))
1916
			unset($cflink['ecn']);
1917
		if ($this->GetLinkshare() <> "") {
1918
			if ($this->GetL_m1() <> "") {
1919
				$cflink['linkshare1'] = $this->GetL_m1();
1920
				$cflink['linkshare2'] = $this->GetL_d();
1921
				$cflink['linkshare'] = "on";
1922
			} else {
1923
				unset($cflink['linkshare']);
1924
				unset($cflink['linkshare1']);
1925
				unset($cflink['linkshare2']);
1926
			}
1927
			if ($this->GetL_m2() <> "") {
1928
				$cflink['linkshare3'] = $this->GetL_m2();
1929
				$cflink['linkshare'] = "on";
1930
			} else {
1931
				unset($cflink['linkshare']);
1932
				unset($cflink['linkshare3']);
1933
			}
1934
		} else {
1935
			unset($cflink['linkshare']);
1936
			unset($cflink['linkshare1']);
1937
			unset($cflink['linkshare2']);
1938
			unset($cflink['linkshare3']);
1939
		}
1940
		if ($this->GetRealtime() <> "") {
1941
			if ($this->GetR_m1() <> "") {
1942
				$cflink['realtime1'] = $this->GetR_m1();
1943
				$cflink['realtime2'] = $this->GetR_d();
1944
				$cflink['realtime'] = "on";
1945
			} else {
1946
				unset($cflink['realtime']);
1947
				unset($cflink['realtime1']);
1948
				unset($cflink['realtime2']);
1949
			}
1950
			if ($this->GetR_m2() <> "") {
1951
				$cflink['realtime3'] = $this->GetR_m2();
1952
				$cflink['realtime'] = "on";
1953
			} else {
1954
				unset($cflink['realtime']);
1955
				unset($cflink['realtime3']);
1956
			}
1957
		} else {
1958
			unset($cflink['realtime']);
1959
			unset($cflink['realtime1']);
1960
			unset($cflink['realtime2']);
1961
			unset($cflink['realtime3']);
1962
		}
1963
		if ($this->GetUpperlimit() <> "") {
1964
			if ($this->GetU_m1() <> "") {
1965
				$cflink['upperlimit1'] = $this->GetU_m1();
1966
				$cflink['upperlimit2'] = $this->GetU_d();
1967
				$cflink['upperlimit'] = "on";
1968
			} else {
1969
				unset($cflink['upperlimit']);
1970
				unset($cflink['upperlimit1']);
1971
				unset($cflink['upperlimit2']);
1972
			}
1973
			if ($this->GetU_m2() <> "") {
1974
				$cflink['upperlimit3'] = $this->GetU_m2();
1975
				$cflink['upperlimit'] = "on";
1976
			} else {
1977
				unset($cflink['upperlimit']);
1978
				unset($cflink['upperlimit3']);
1979
			}
1980
		} else {
1981
			unset($cflink['upperlimit']);
1982
			unset($cflink['upperlimit1']);
1983
			unset($cflink['upperlimit2']);
1984
			unset($cflink['upperlimit3']);
1985
		}
1986
	}
1987
}
1988

    
1989
class cbq_queue extends priq_queue {
1990
	var $qborrow = "";
1991

    
1992
	function GetBorrow() {
1993
		return $this->qborrow;
1994
	}
1995
	function SetBorrow($borrow) {
1996
		$this->qborrow = $borrow;
1997
	}
1998
	function CanHaveChildren() {
1999
		return true;
2000
	}
2001

    
2002
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2003

    
2004
		if (!is_array($this->subqueues))
2005
			$this->subqueues = array();
2006
		$q =& new cbq_queue();
2007
		$q->SetInterface($this->GetInterface());
2008
		$q->SetParent(&$this);
2009
		$q->ReadConfig($qname);
2010
                $q->validate_input($qname, $input_errors);
2011
                if (count($input_errors)) {
2012
                        return $q;
2013
                }
2014
                switch ($q->GetBwscale()) {
2015
                case "%":
2016
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2017
                        break;
2018
                default:
2019
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2020
                        break;
2021
                }
2022
                $q->SetAvailableBandwidth($myBw);
2023
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2024

    
2025
		$q->SetEnabled("on");
2026
		$q->SetLink($path);
2027
		$this->subqueues[$q->GetQName()] = &$q;
2028
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2029
		if (is_array($qname['queue'])) {
2030
			foreach ($qname['queue'] as $key1 => $que) {
2031
				array_push($path, $key1);
2032
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2033
				array_pop($path);
2034
			}
2035
		}
2036

    
2037
		return $q;
2038
	}
2039

    
2040
	function copy_queue($interface, &$cflink) {
2041

    
2042
		$cflink['interface'] = $interface;
2043
		$cflink['qlimit'] = trim($this->GetQlimit());
2044
		if (empty($clink['qlimit']))
2045
			unset($cflink['qlimit']);
2046
		$cflink['priority'] = trim($this->GetQpriority());
2047
		if (empty($cflink['priority']))
2048
			unset($cflink['priority']);
2049
		$cflink['name'] = $this->GetQname();
2050
		$cflink['description'] = trim($this->GetDescription());
2051
		if (empty($cflink['description']))
2052
			unset($cflink['description']);
2053
		$cflink['bandwidth'] = $this->GetBandwidth();
2054
		$cflink['bandwidthtype'] = $this->GetBwscale();
2055
		$cflink['enabled'] = trim($this->GetEnabled());
2056
		if (empty($cflink['enabled']))
2057
			unset($cflink['enabled']);
2058
		$cflink['default'] = trim($this->GetDefault());
2059
		if (empty($cflink['default']))
2060
			unset($cflink['default']);
2061
		$cflink['red'] = trim($this->GetRed());
2062
		if (empty($cflink['red']))
2063
			unset($cflink['red']);
2064
		$cflink['rio'] = trim($this->GetRio());
2065
		if (empty($cflink['rio']))
2066
			unset($cflink['rio']);
2067
		$cflink['ecn'] = trim($this->GetEcn());
2068
		if (empty($cflink['ecn']))
2069
			unset($cflink['ecn']);
2070
		$cflink['borrow'] = trim($this->GetBorrow());
2071
		if (empty($cflink['borrow']))
2072
			unset($cflink['borrow']);
2073
		if (is_array($this->queues)) {
2074
			$cflinkp['queue'] = array();
2075
			foreach ($this->subqueues as $q) {
2076
				$cflink['queue'][$q->GetQname()] = array();
2077
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
2078
			}
2079
		}
2080
	}
2081
	
2082
	/*
2083
	 * Should search even its children
2084
	 */
2085
	function &find_queue($interface, $qname) {
2086
		if ($qname == $this->GetQname())
2087
			return $this;
2088
		foreach ($this->subqueues as $q) {
2089
			$result =& $q->find_queue("", $qname);
2090
			if ($result)
2091
				return $result;
2092
		}
2093
	}
2094

    
2095
	function &find_parentqueue($interface, $qname) {
2096
		if ($this->subqueues[$qname])
2097
			return $this;
2098
		foreach ($this->subqueues as $q) {
2099
			$result = $q->find_parentqueue("", $qname);
2100
			if ($result)
2101
				return $result;
2102
		}
2103
	}
2104

    
2105
	function delete_queue() {
2106
		unref_on_altq_queue_list($this->GetQname());
2107
		if ($this->GetDefault())
2108
			altq_set_default_queue($this->GetInterface(), "false");
2109
		cleanup_queue_from_rules($this->GetQname());
2110
		foreach ($this->subqueues as $q) {
2111
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2112
			$q->delete_queue();
2113
		}
2114
		unset_object_by_reference($this->GetLink());
2115
	}
2116
	
2117
	function validate_input($data, &$input_errors) {
2118
		parent::validate_input($data, $input_errors);
2119
		
2120
		if ($data['priority'] > 7)
2121
				$input_errors[] = "Priority must be an integer between 1 and 7.";
2122
		$reqdfields[] = "bandwidth";
2123
		$reqdfieldsn[] = "Bandwidth";
2124
		$reqdfields[] = "bandwidthtype";
2125
		$reqdfieldsn[] = "Bandwidthtype";
2126

    
2127
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2128
		
2129
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2130
			$input_errors[] = "Bandwidth must be an integer.";
2131

    
2132

    
2133
		if ($data['bandwidth'] < 0)
2134
                       $input_errors[] = "Bandwidth cannot be negative.";
2135

    
2136
		if ($data['bandwidthtype'] == "%") {
2137
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2138
				$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2139
		}
2140

    
2141
/*
2142
           $parent =& $this->GetParent();
2143
           switch ($data['bandwidthtype']) {
2144
                       case "%":
2145
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2146
                       default:
2147
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2148
                             break;
2149
           }
2150
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2151
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2152
*/
2153
	}
2154

    
2155
	function ReadConfig(&$q) {
2156
		parent::ReadConfig($q);
2157
		if (!empty($q['borrow']))
2158
			$this->SetBorrow("on");
2159
	}
2160
		
2161
	function build_javascript() {
2162
		return parent::build_javascript();
2163
	}
2164

    
2165
	function build_tree() {
2166
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2167
		$tree .= "\" ";
2168
		$tmpvalue = trim($this->GetDefault());
2169
		if (!empty($tmpvalue))
2170
			$tree .= " class=\"navlnk\"";
2171
		$tree .= " >" . $this->GetQname() . "</a>";
2172
		if (is_array($this->subqueues)) {
2173
			$tree .= "<ul>";
2174
			foreach ($this->subqueues as $q)  {
2175
				$tree .= $q->build_tree();
2176
			}	
2177
			$tree .= "</ul>";
2178
		}
2179
		$tree .= "</li>";
2180
		return $tree;
2181
	}
2182
		
2183
	/* Even this should take children into consideration */
2184
	function build_rules() {
2185
		$pfq_rule = "queue ". $this->qname;
2186
		if ($this->GetInterface())
2187
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2188
		if ($this->GetBandwidth() && $this->GetBwscale())
2189
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2190
		$tmpvalue = $this->GetQpriority();
2191
		if (!empty($tmpvalue))
2192
			$pfq_rule .= " priority " . $this->GetQpriority();
2193
		$tmpvalue = trim($this->GetQlimit());
2194
		if (!empty($tmpvalue))
2195
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2196
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow()) {
2197
			$pfq_rule .= " cbq ( ";
2198
			$tmpvalue = trim($this->GetRed());
2199
			if (!empty($tmpvalue)) {
2200
				$comma = 1;
2201
				$pfq_rule .= " red ";
2202
			}
2203
			$tmpvalue = trim($this->GetRio());
2204
			if (!empty($tmpvalue)) {
2205
				if ($comma) 
2206
					$pfq_rule .= " ,";
2207
				$comma = 1;
2208
				$pfq_rule .= " rio ";
2209
			}
2210
			$tmpvalue = trim($this->GetEcn());
2211
			if (!empty($tmpvalue)) {
2212
				if ($comma) 
2213
					$pfq_rule .= " ,";
2214
				$comma = 1;
2215
				$pfq_rule .= " ecn ";
2216
			}
2217
			$tmpvalue = trim($this->GetDefault());
2218
			if (!empty($tmpvalue)) {
2219
				if ($comma)
2220
					$pfq_rule .= " ,";
2221
				$comma = 1;
2222
				$pfq_rule .= " default ";
2223
			}
2224
			$tmpvalue = trim($this->GetBorrow());
2225
			if (!empty($tmpvalue)) {
2226
				if ($comma)
2227
					$pfq_rule .= ", ";
2228
				$pfq_rule .= " borrow ";
2229
			}
2230
			$pfq_rule .= " ) ";
2231
		} 
2232
		if (count($this->subqueues)) {
2233
			$i = count($this->subqueues);
2234
			$pfq_rule .= " { ";
2235
			foreach ($this->subqueues as $qkey => $qnone) {
2236
				if ($i > 1) {
2237
					$i--;
2238
					$pfq_rule .= " {$qkey}, ";
2239
				} else
2240
					$pfq_rule .= " {$qkey} ";
2241
			}
2242
			$pfq_rule .= " } \n";
2243
			foreach ($this->subqueues as $q)
2244
				$pfq_rule .= $q->build_rules();
2245
		}
2246

    
2247
		$pfq_rule .= " \n";
2248
		return $pfq_rule;
2249
	}
2250

    
2251
	function build_form() {
2252
		$form = "<tr>";
2253
		$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
2254
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2255
		if ($this->GetBandwidth() > 0)
2256
			$form .= htmlspecialchars($this->GetBandwidth());
2257
		$form .= "\">";
2258
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2259
		$form .= "<option value=\"Gb\"";
2260
		if ($this->GetBwscale() == "Gb")
2261
			$form .= " selected=\"yes\"";
2262
		$form .= ">Gbit/s</option>";
2263
		$form .= "<option value=\"Mb\"";
2264
		if ($this->GetBwscale() == "Mb")
2265
			$form .= " selected=\"yes\"";
2266
		$form .= ">Mbit/s</option>";
2267
		$form .= "<option value=\"Kb\"";
2268
		if ($this->GetBwscale() == "Kb")
2269
			$form .= " selected=\"yes\"";
2270
		$form .= ">Kbit/s</option>";
2271
		$form .= "<option value=\"\"";
2272
		if ($this->GetBwscale() == "b")
2273
			$form .= " selected=\"yes\"";
2274
		$form .= ">Bit/s</option>";
2275
		$form .= "<option value=\"%\"";
2276
		if ($this->GetBwscale() == "%")
2277
			$form .= " selected=\"yes\"";
2278
		$form .= ">%</option>";
2279
		$form .= "</select> <br>";
2280
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2281
		$form .= "</span></td></tr>";
2282
		$form .= parent::build_form();
2283
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2284
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2285
		if($this->GetBorrow() == "on") 
2286
			$form .=  " CHECKED ";
2287
		$form .= "> Borrow from other queues when available<br></td></tr>";
2288

    
2289
		return $form;
2290
	}
2291

    
2292
	function update_altq_queue_data(&$data) { 
2293
		$this->ReadConfig($data);
2294
	}
2295

    
2296
	function wconfig() {
2297
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2298
		if (!is_array($cflink))
2299
			$cflink = array();
2300
		$cflink['interface'] = $this->GetInterface();
2301
		$cflink['qlimit'] = trim($this->GetQlimit());
2302
		if (empty($cflink['qlimit']))
2303
			unset($cflink['qlimit']);
2304
		$cflink['priority'] = $this->GetQpriority();
2305
		if (empty($cflink['priority']))
2306
			unset($cflink['priority']);
2307
		$cflink['name'] = $this->GetQname();
2308
		$cflink['description'] = $this->GetDescription();
2309
		if (empty($cflink['description']))
2310
			unset($cflink['description']);
2311
		$cflink['bandwidth'] = $this->GetBandwidth();
2312
		$cflink['bandwidthtype'] = $this->GetBwscale();
2313
		$cflink['enabled'] = trim($this->GetEnabled());
2314
		if (empty($cflink['enabled']))
2315
			unset($cflink['enabled']);
2316
		$cflink['default'] = trim($this->GetDefault());
2317
		if (empty($cflink['default']))
2318
			unset($cflink['default']);
2319
		$cflink['red'] = trim($this->GetRed());
2320
		if (empty($cflink['red']))
2321
			unset($cflink['red']);
2322
		$cflink['rio'] = trim($this->GetRio());
2323
		if (empty($cflink['rio']))
2324
			unset($cflink['rio']);
2325
		$cflink['ecn'] = trim($this->GetEcn());
2326
		if (empty($cflink['ecn']))
2327
			unset($cflink['ecn']);
2328
		$cflink['borrow'] = trim($this->GetBorrow());
2329
		if (empty($cflink['borrow']))
2330
			unset($cflink['borrow']);
2331
	}
2332
}
2333

    
2334
class fairq_queue extends priq_queue {
2335
	var $hogs;
2336
	var $buckets;
2337

    
2338
	function GetBuckets() {
2339
		return $this->buckets;
2340
	}
2341
	function SetBuckets($buckets) {
2342
		$this->buckets = $buckets;
2343
	}
2344
	function GetHogs() {
2345
		return $this->hogs;
2346
	}
2347
	function SetHogs($hogs) {
2348
		$this->hogs = $hogs;
2349
	}
2350
	function CanHaveChildren() {
2351
		return false;
2352
	}
2353

    
2354

    
2355
	function copy_queue($interface, &$cflink) {
2356
                $cflink['interface'] = $interface;
2357
                $cflink['qlimit'] = $this->GetQlimit();
2358
                $cflink['priority'] = $this->GetQpriority();
2359
                $cflink['name'] = $this->GetQname();
2360
                $cflink['description'] = $this->GetDescription();
2361
                $cflink['bandwidth'] = $this->GetBandwidth();
2362
                $cflink['bandwidthtype'] = $this->GetBwscale();
2363
                $cflink['enabled'] = $this->GetEnabled();
2364
                $cflink['default'] = $this->GetDefault();
2365
                $cflink['red'] = $this->GetRed();
2366
                $cflink['rio'] = $this->GetRio();
2367
                $cflink['ecn'] = $this->GetEcn();
2368
                $cflink['buckets'] = $this->GetBuckets();
2369
		$cflink['hogs'] = $this->GetHogs();
2370
	}
2371
	
2372
	/*
2373
	 * Should search even its children
2374
	 */
2375
	function &find_queue($interface, $qname) {
2376
		if ($qname == $this->GetQname())
2377
			return $this;
2378
	}
2379

    
2380
	function find_parentqueue($interface, $qname) { return; }
2381

    
2382
	function delete_queue() {
2383
		unref_on_altq_queue_list($this->GetQname());
2384
		if ($this->GetDefault())
2385
			altq_set_default_queue($this->GetInterface(), "false");
2386
		cleanup_queue_from_rules($this->GetQname());
2387
		unset_object_by_reference($this->GetLink());
2388
	}
2389
	
2390
	function validate_input($data, &$input_errors) {
2391
		parent::validate_input($data, $input_errors);
2392
		
2393
		if ($data['priority'] > 255)
2394
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2395
		$reqdfields[] = "bandwidth";
2396
		$reqdfieldsn[] = "Bandwidth";
2397
		$reqdfields[] = "bandwidthtype";
2398
		$reqdfieldsn[] = "Bandwidthtype";
2399

    
2400
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2401
		
2402
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2403
	                 $input_errors[] = "Bandwidth must be an integer.";
2404

    
2405

    
2406
	        if ($data['bandwidth'] < 0)
2407
                       $input_errors[] = "Bandwidth cannot be negative.";
2408

    
2409

    
2410
        	if ($data['bandwidthtype'] == "%") {
2411
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2412
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2413
           	}
2414

    
2415
/*
2416
           	$parent =& $this->GetParent();
2417
           	switch ($data['bandwidthtype']) {
2418
                       case "%":
2419
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2420
                       default:
2421
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2422
                             break;
2423
           	}
2424
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2425
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2426
*/
2427
	}
2428
	
2429
	function ReadConfig(&$q) {
2430
		parent::ReadConfig($q);
2431
		if (!empty($q['buckets']))
2432
			$this->SetBuckets($q['buckets']);
2433
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2434
			$this->SetHogs($q['hogs']);
2435
	}
2436
		
2437
	function build_javascript() {
2438
		return parent::build_javascript();
2439
	}
2440

    
2441
	function build_tree() {
2442
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2443
		$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2444
		$tree .= "\" ";
2445
		$tmpvalue = trim($this->GetDefault());
2446
		if (!empty($tmpvalue))
2447
			$tree .= " class=\"navlnk\"";
2448
		$tree .= " >" . $this->GetQname() . "</a>";
2449
		$tree .= "</li>";
2450
		return $tree;
2451
	}
2452
		
2453
	/* Even this should take children into consideration */
2454
	function build_rules() {
2455
		$pfq_rule = "queue ". $this->qname;
2456
		if ($this->GetInterface())
2457
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2458
		if ($this->GetBandwidth() && $this->GetBwscale())
2459
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2460
		$tmpvalue = trim($this->GetQpriority());
2461
		if (!empty($tmpvalue))
2462
			$pfq_rule .= " priority " . $this->GetQpriority();
2463
		$tmpvalue = trim($this->GetQlimit());
2464
		if (!empty($tmpvalue))
2465
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2466
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2467
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2468
			$pfq_rule .= " fairq ( ";
2469
			$tmpvalue = trim($this->GetRed());
2470
			if (!empty($tmpvalue)) {
2471
				$comma = 1;
2472
				$pfq_rule .= " red ";
2473
			}
2474
			$tmpvalue = trim($this->GetRio());
2475
			if (!empty($tmpvalue)) {
2476
				if ($comma) 
2477
					$pfq_rule .= " ,";
2478
				$comma = 1;
2479
				$pfq_rule .= " rio ";
2480
			}
2481
			$tmpvalue = trim($this->GetEcn());
2482
			if (!empty($tmpvalue)) {
2483
				if ($comma) 
2484
					$pfq_rule .= " ,";
2485
				$comma = 1;
2486
				$pfq_rule .= " ecn ";
2487
			}
2488
			$tmpvalue = trim($this->GetDefault());
2489
			if (!empty($tmpvalue)) {
2490
				if ($comma)
2491
					$pfq_rule .= " ,";
2492
				$comma = 1;
2493
				$pfq_rule .= " default ";
2494
			}
2495
			$tmpvalue = trim($this->GetBuckets());
2496
			if (!empty($tmpvalue)) {
2497
				if ($comma)
2498
					$pfq_rule .= ", ";
2499
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2500
			}
2501
			$tmpvalue = trim($this->GetHogs());
2502
			if (!empty($tmpvalue)) {
2503
				if ($comma)
2504
					$pfq_rule .= ", ";
2505
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2506
			}
2507
				$pfq_rule .= " ) ";
2508
		} 
2509

    
2510
		$pfq_rule .= " \n";
2511
		return $pfq_rule;
2512
	}
2513

    
2514
	function build_form() {
2515
		$form = "<tr>";
2516
		$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
2517
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2518
		if ($this->GetBandwidth() > 0)
2519
			$form .= htmlspecialchars($this->GetBandwidth());
2520
		$form .= "\">";
2521
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2522
		$form .= "<option value=\"Gb\"";
2523
		if ($this->GetBwscale() == "Gb")
2524
			$form .= " selected=\"yes\"";
2525
		$form .= ">Gbit/s</option>";
2526
		$form .= "<option value=\"Mb\"";
2527
		if ($this->GetBwscale() == "Mb")
2528
			$form .= " selected=\"yes\"";
2529
		$form .= ">Mbit/s</option>";
2530
		$form .= "<option value=\"Kb\"";
2531
		if ($this->GetBwscale() == "Kb")
2532
			$form .= " selected=\"yes\"";
2533
		$form .= ">Kbit/s</option>";
2534
		$form .= "<option value=\"\"";
2535
		if ($this->GetBwscale() == "b")
2536
			$form .= " selected=\"yes\"";
2537
		$form .= ">Bit/s</option>";
2538
		$form .= "<option value=\"%\"";
2539
		if ($this->GetBwscale() == "%")
2540
			$form .= " selected=\"yes\"";
2541
		$form .= ">%</option>";
2542
		$form .= "</select> <br>";
2543
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2544
		$form .= "</span></td></tr>";
2545
		$form .= parent::build_form();
2546
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2547
		$form .= "<td class=\"vtable\"><table><tr><td>";
2548
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2549
		$tmpvalue = trim($this->GetBuckets());
2550
		if(!empty($tmpvalue)) 
2551
			$form .=  $this->GetBuckets();
2552
		$form .= "\"> Number of buckets available.<br></td></tr>";
2553
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2554
		$tmpvalue = trim($this->GetHogs());
2555
		if(!empty($tmpvalue)) 
2556
			$form .=  $this->GetHogs();
2557
		$form .= "\"> Bandwidth limit for hosts to not saturate link.<br></td></tr>";
2558
		$form .= "</table></td></tr>";
2559
		return $form;
2560
	}
2561

    
2562
	function update_altq_queue_data(&$data) { 
2563
		$this->ReadConfig($data);
2564
	}
2565

    
2566
	function wconfig() {
2567
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2568
		if (!is_array($cflink))
2569
			$cflink = array();
2570
		$cflink['interface'] = $this->GetInterface();
2571
		$cflink['qlimit'] = trim($this->GetQlimit());
2572
		if (empty($cflink['qlimit']))
2573
			unset($cflink['qlimit']);
2574
		$cflink['priority'] = trim($this->GetQpriority());
2575
		if (empty($cflink['priority']))
2576
			unset($cflink['priority']);
2577
		$cflink['name'] = $this->GetQname();
2578
		$cflink['description'] = trim($this->GetDescription());
2579
		if (empty($cflink['description']))
2580
			unset($cflink['description']);
2581
		$cflink['bandwidth'] = $this->GetBandwidth();
2582
		$cflink['bandwidthtype'] = $this->GetBwscale();
2583
		$cflink['enabled'] = $this->GetEnabled();
2584
		if (empty($cflink['enabled']))
2585
			unset($cflink['enabled']);
2586
		$cflink['default'] = trim($this->GetDefault());
2587
		if (empty($cflink['default']))
2588
			unset($cflink['default']);
2589
		$cflink['red'] = trim($this->GetRed());
2590
		if (empty($cflink['red']))
2591
			unset($cflink['red']);
2592
		$cflink['rio'] = trim($this->GetRio());
2593
		if (empty($cflink['rio']))
2594
			unset($cflink['rio']);
2595
		$cflink['ecn'] = trim($this->GetEcn());
2596
		if (empty($cflink['ecn']))
2597
			unset($cflink['ecn']);
2598
		$cflink['buckets'] = trim($this->GetBuckets());
2599
		if (empty($cflink['buckets']))
2600
			unset($cflink['buckets']);
2601
		$cflink['hogs'] = trim($this->GetHogs());
2602
		if (empty($cflink['hogs']))
2603
			unset($cflink['hogs']);
2604
	}
2605
}
2606

    
2607

    
2608
/*
2609
 * XXX: TODO Link dummynet(4) in the system. 
2610
 */
2611

    
2612

    
2613
/*
2614
 * List of respective objects!
2615
 */
2616
$dummynet_pipe_list = array();
2617

    
2618
class dummynet_class {
2619
        var $qname;
2620
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2621
        var $qlimit;
2622
        var $description;
2623
	var $qenabled;
2624
	var $link;
2625
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2626
        var $plr;
2627

    
2628
        var $buckets;
2629
        /* mask parameters */
2630
        var $mask;
2631
        var $noerror;
2632

    
2633
        /* Accessor functions */
2634
        function SetLink($link) {
2635
                $this->link = $link;
2636
        }
2637
        function GetLink() {
2638
                return $this->link;
2639
        }
2640
	function Getmask() {
2641
		return $this->mask;
2642
	}
2643
	function SetMask($mask) {
2644
		$this->mask = $mask;
2645
	}
2646
	function &GetParent() {
2647
		return $this->qparent;
2648
	}
2649
	function SetParent(&$parent) {
2650
		$this->qparent = &$parent;
2651
	}
2652
        function GetEnabled() {
2653
                return $this->qenabled;
2654
        }
2655
        function SetEnabled($value) {
2656
                $this->qenabled = $value;
2657
        }
2658
	function CanHaveChildren() {
2659
		return false;
2660
        }
2661
	function CanBeDeleted() {
2662
                return true;
2663
        }
2664
        function GetQname() {
2665
                return $this->qname;
2666
        }
2667
        function SetQname($name) {
2668
                $this->qname = trim($name);
2669
        }
2670
        function GetQlimit() {
2671
                return $this->qlimit;
2672
        }
2673
        function SetQlimit($limit) {
2674
               	$this->qlimit = $limit;
2675
        }
2676
        function GetDescription() {
2677
                return $this->description;
2678
        }
2679
        function SetDescription($str) {
2680
                $this->description = trim($str);
2681
        }
2682
        function GetFirstime() {
2683
                return $this->firsttime;
2684
        }
2685
        function SetFirsttime($number) {
2686
                $this->firsttime = $number;
2687
        }
2688
        function GetBuckets() {
2689
                return $this->buckets;
2690
        }
2691
        function SetBuckets($buckets) {
2692
                $this->buckets = $buckets;
2693
        }
2694
	function SetNumber($number) {
2695
		$this->qnumber = $number;
2696
	}
2697
	function GetNumber() {
2698
		return $this->qnumber;
2699
	}
2700
        function GetPlr() {
2701
                return $this->plr;
2702
        }
2703
        function SetPlr($plr) {
2704
                $this->plr = $plr;
2705
        }
2706

    
2707
	function build_javascript() { return; } /* Do not remove */
2708

    
2709
	function validate_input($data, &$input_errors) {
2710
		$reqdfields[] = "bandwidth";
2711
		$reqdfieldsn[] = "Bandwidth";
2712
		$reqdfields[] = "bandwidthtype";
2713
		$reqdfieldsn[] = "Bandwidthtype";
2714
		$reqdfields[] = "name";
2715
		$reqdfieldsn[] = "Name";
2716
	
2717
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2718

    
2719
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2720
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2721
            		$input_errors[] = "Plr must be an integer between 1 and 100.";
2722
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2723
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2724
            		$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2725
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2726
            		$input_errors[] = "Queue limit must be an integer";
2727
        	if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2728
			$input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2729
	}
2730
}
2731

    
2732
class dnpipe_class extends dummynet_class {
2733
        var $pipe_nr;
2734
        var $delay;
2735
	var $qbandwidth;
2736
	var $qbandwidthtype;
2737

    
2738
		/* This is here to help on form building and building rules/lists */
2739
        var $subqueues = array();
2740

    
2741
	function CanHaveChildren() {
2742
	        return true;
2743
        }
2744
	function SetDelay($delay) {
2745
		$this->delay = $delay;
2746
	}
2747
	function GetDelay() {
2748
		return $this->delay;
2749
	}
2750
	function GetBwscale() {
2751
                return $this->qbandwidthtype;
2752
        }
2753
        function SetBwscale($scale) {
2754
               	$this->qbandwidthtype = $scale;
2755
        }		
2756
	function delete_queue() {
2757
		cleanup_dnqueue_from_rules($this->GetQname());
2758
		foreach ($this->subqueues as $q)
2759
			$q->delete_queue();
2760
		unset_dn_object_by_reference($this->GetLink());
2761
        }
2762
        function GetBandwidth() {
2763
                return $this->qbandwidth;
2764
        }
2765
        function SetBandwidth($bandwidth) {
2766
                $this->qbandwidth = $bandwidth;
2767
        }
2768

    
2769
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2770

    
2771
		if (!is_array($this->subqueues))
2772
			$this->subqueues = array();
2773
			
2774
		$q =& new dnqueue_class();
2775
		$q->SetLink($path);
2776
		$q->SetEnabled("on");
2777
		$q->SetPipe($this->GetQname());
2778
		$q->SetParent(&$this);
2779
		$q->ReadConfig($queue);
2780
		$q->validate_input($queue, $input_errors);
2781
		if (count($input_errors))
2782
			return $q;
2783
		$this->subqueues[$q->GetQname()] = &$q;
2784
            
2785
		return $q;
2786
	}
2787

    
2788
	function &get_queue_list($q = null) {
2789
		$qlist = array();
2790

    
2791
		$qlist[$this->GetQname()] = $this->GetNumber();
2792
		if (is_array($this->subqueues)) {
2793
			foreach ($this->subqueues as $queue)
2794
				$queue->get_queue_list(&$qlist);
2795
		}
2796
		return $qlist;
2797
	}
2798
		
2799
        /*
2800
         * Should search even its children
2801
         */
2802
        function &find_queue($pipe, $qname) {
2803
                if ($qname == $this->GetQname()) 
2804
                        return $this;
2805
               	foreach ($this->subqueues as $q) {
2806
                       	$result =& $q->find_queue("", $qname);
2807
						if ($result)
2808
                       	        return $result;
2809
               	}
2810
        }
2811

    
2812
	function &find_parentqueue($pipe, $qname) {
2813
		return NULL;
2814
       	}
2815

    
2816
	function validate_input($data, &$input_errors) {
2817
		parent::validate_input($data, $input_errors);
2818

    
2819
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2820
       		     	$input_errors[] = "Bandwidth must be an integer.";
2821
		if ($data['delay'] && (!is_numeric($data['delay'])))
2822
            		$input_errors[] = "Delay must be an integer.";
2823
		}
2824

    
2825
	function ReadConfig(&$q) {
2826
           	$this->SetQname($q['name']);
2827
		$this->SetNumber($q['number']);
2828
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2829
			$this->SetBandwidth($q['bandwidth']);
2830
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2831
				$this->SetBwscale($q['bandwidthtype']);
2832
		}
2833
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2834
              		$this->SetQlimit($q['qlimit']);
2835
		if (isset($q['mask']) && $q['mask'] <> "")
2836
              		$this->SetMask($q['mask']);
2837
		if (isset($q['buckets']) && $q['buckets'] <> "")
2838
              		$this->SetBuckets($q['buckets']);
2839
            	if (isset($q['plr']) && $q['plr'] <> "")
2840
            		$this->SetPlr($q['plr']);
2841
		if (isset($q['delay']) && $q['delay'] <> "")
2842
            		$this->SetDelay($q['delay']);
2843
            	if (isset($q['description']) && $q['description'] <> "")
2844
			$this->SetDescription($q['description']);
2845
		$this->SetEnabled($q['enabled']);
2846

    
2847
        }
2848

    
2849
	function build_tree() {
2850
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2851
		$tree .= $this->GetQname() . "</a>";
2852
		if (is_array($this->subqueues)) {
2853
			$tree .= "<ul>";
2854
			foreach ($this->subqueues as $q)  {
2855
				$tree .= $q->build_tree();
2856
			}	
2857
			$tree .= "</ul>";
2858
		}
2859
		$tree .= "</li>";
2860
		
2861
		return $tree;
2862
	}
2863

    
2864
        function build_rules() {
2865
		if ($this->GetEnabled() == "")
2866
			return;
2867

    
2868
       		$pfq_rule = "\ndnpipe ". $this->GetNumber();
2869
		if ($this->GetBandwidth() && $this->GetBwscale())
2870
                    	$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2871
		if ($this->GetQlimit())
2872
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2873
		if ($this->GetPlr())
2874
			$pfq_rule .= " plr " . $this->GetPlr();
2875
		if ($this->GetBuckets())
2876
			$pfq_rule .= " buckets " . $this->GetBuckets();
2877
		if ($this->GetDelay())
2878
			$pfq_rule .= " delay " . $this->GetDelay();
2879

    
2880
		$mask = $this->GetMask();
2881
		if (!empty($mask)) {
2882
			/* XXX TODO extend this to support more complicated masks */
2883
			switch ($mask) {
2884
			case 'srcaddress':
2885
				$pfq_rule .= " mask src-ip 0xffffffff ";
2886
				break;
2887
			case 'dstaddress':
2888
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2889
				break;
2890
			default:
2891
				break;
2892
			}
2893
			$pfq_rule .= "\n";
2894

    
2895
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2896
       			        foreach ($this->subqueues as $q)
2897
				$pfq_rule .= $q->build_rules();
2898
               		}
2899
    		}            
2900
		$pfq_rule .= " \n";
2901

    
2902
		return $pfq_rule;
2903
        }
2904

    
2905
	function update_dn_data(&$data) { 
2906
		$this->ReadConfig($data);
2907
	}
2908

    
2909
        function build_form() { 
2910
		$form = "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
2911
		$form .= "<td class=\"vncellreq\">";
2912
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
2913
		$form .= $this->GetQname()."\">";
2914
		$form .= "</td></tr>";
2915
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Bandwidth";
2916
		$form .= "</td><td class=\"vncellreq\">";
2917
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
2918
		$form .= $this->GetBandwidth() . "\">"; 
2919
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
2920
		$form .= "<option value=\"Kb\"";
2921
		if ($this->GetBwscale() == "Kb")
2922
			$form .= " selected=\"yes\"";
2923
		$form .= ">Kbit/s</option>";
2924
		$form .= "<option value=\"Mb\"";
2925
		if ($this->GetBwscale() == "Mb")
2926
			$form .= " selected=\"yes\"";
2927
		$form .= ">Mbit/s</option>";
2928
		$form .= "<option value=\"Gb\"";
2929
		if ($this->GetBwscale() == "Gb")
2930
			$form .= " selected=\"yes\"";
2931
		$form .= ">Gbit/s</option>";		
2932
		$form .= "<option value=\"\"";
2933
		if ($this->GetBwscale() == "b")
2934
			$form .= " selected=\"yes\"";
2935
		$form .= ">Bit/s</option>";
2936
		$form .= "</select>";
2937
		$form .= "</td></tr>";
2938
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Mask</td>";
2939
		$form .= "<td class=\"vncellreq\">";
2940
		$form .= "<select name=\"mask\" class=\"formselect\">";
2941
		$form .= "<option value=\"none\"";
2942
		if ($this->GetMask() == "none")
2943
			$form .= " selected=\"yes\"";
2944
		$form .= ">none</option>";
2945
		$form .= "<option value=\"srcaddress\"";
2946
		if ($this->GetMask() == "srcaddress")
2947
			$form .= " selected=\"yes\"";
2948
		$form .= ">Source addresses</option>";
2949
		$form .= "<option value=\"dstaddress\"";
2950
		if ($this->GetMask() == "dstaddress")
2951
			$form .= " selected=\"yes\"";
2952
		$form .= ">Destination addresses</option>";
2953
		$form .= "</select>";
2954
		$form .= "&nbsp;<br>";
2955
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
2956
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
2957
		$form .= "be created for each source/destination IP address encountered, \n";
2958
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
2959
		$form .= "limits per host.</span>";
2960
		$form .= "</td></tr>";
2961
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Description</td>";
2962
		$form .= "<td class=\"vncellreq\">";
2963
		$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
2964
		$form .= $this->GetDescription();
2965
		$form .= "\">";
2966
		$form .= "<br> <span class=\"vexpl\">";
2967
		$form .= "You may enter a description here ";
2968
		$form .= "for your reference (not parsed).</span>";
2969
		$form .= "</td></tr>";
2970
      		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
2971
		$form .= "<td></td>";
2972
                $form .= "<td><div id=\"showadvancedboxspr\">";
2973
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
2974
		$form .= " value=\"Show advanced options\"></input></a>";
2975
                $form .= "</div></td></tr>";
2976
                $form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
2977

    
2978
		$form .= "<td valign=\"top\" class=\"vncellreq\">Delay</td>";
2979
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
2980
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
2981
		$form .= $this->GetDelay() . "\">";
2982
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you "; 
2983
		$form .= "should specify 0 here (or leave the field empty)</span>";
2984
		$form .= "</td></tr><br/>";
2985
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
2986
		$form .= "<td valign=\"top\" class=\"vncellreq\">Packet loss rate</td>";
2987
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
2988
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
2989
		$form .= $this->GetPlr() . "\">";
2990
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
2991
        	$form .= "should specify 0 here (or leave the field empty).";
2992
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
2993
		$form .= "</td></tr>";
2994
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
2995
		$form .= "<td valign=\"top\" class=\"vncellreq\">Queue Size</td>";
2996
		$form .= "<td class=\"vncellreq\">";
2997
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
2998
		$form .= $this->GetQlimit() . "\">";
2999
		$form .= "&nbsp;slots<br>";
3000
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3001
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
3002
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
3003
		$form .= "are delivered to their destination.</span>";
3004
		$form .= "</td></tr>";
3005
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3006
                $form .= "<td valign=\"top\" class=\"vncellreq\">Bucket Size</td>";
3007
                $form .= "<td class=\"vncellreq\">";
3008
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3009
                $form .= $this->GetBuckets() . "\">";
3010
                $form .= "&nbsp;slots<br>";
3011
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3012
                $form .= "should leave the field empty. It increases the hash size set.";
3013
                $form .= "</td></tr>";
3014

    
3015
		return $form;
3016
			
3017
		}
3018

    
3019
	function wconfig() {
3020
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3021
            	if (!is_array($cflink))
3022
            		$cflink = array();
3023
		$cflink['name'] = $this->GetQname();
3024
		$cflink['number'] = $this->GetNumber();
3025
            	$cflink['qlimit'] = $this->GetQlimit();
3026
            	$cflink['plr'] = $this->GetPlr();
3027
            	$cflink['description'] = $this->GetDescription();
3028
		$cflink['bandwidth'] = $this->GetBandwidth();
3029
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3030
		$cflink['enabled'] = $this->GetEnabled();
3031
		$cflink['buckets'] = $this->GetBuckets();
3032
		$cflink['mask'] = $this->GetMask();
3033
		$cflink['delay'] = $this->GetDelay();
3034
	}
3035

    
3036
}
3037

    
3038
class dnqueue_class extends dummynet_class {
3039
        var $pipeparent;
3040
        var $weight;
3041

    
3042
        function GetWeight() {
3043
                return $this->weight;
3044
        }
3045
        function SetWeight($weight) {
3046
                $this->weight = $weight;
3047
        }
3048
	function GetPipe() {
3049
		return $this->pipeparent;
3050
	}
3051
	function SetPipe($pipe) {
3052
		$this->pipeparent = $pipe;
3053
	}
3054

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

    
3058
	function delete_queue() {
3059
		cleanup_dnqueue_from_rules($this->GetQname());
3060
		unset_dn_object_by_reference($this->GetLink());
3061
        }
3062

    
3063
	function validate_input($data, &$input_errors) {
3064
		parent::validate_input($data, $input_errors);
3065

    
3066
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3067
			($data['weight'] < 1 && $data['weight'] > 100))) 
3068
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
3069
	}
3070

    
3071
        /*
3072
         * Should search even its children
3073
         */
3074
        function &find_queue($pipe, $qname) {
3075
                if ($qname == $this->GetQname()) 
3076
                	return $this;
3077
		else
3078
			return NULL;
3079
        }
3080

    
3081
	function &find_parentqueue($pipe, $qname) {
3082
		return $this->qparent;
3083
        }
3084

    
3085
        function &get_queue_list(&$qlist) {
3086
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3087
        }		
3088

    
3089
	function ReadConfig(&$q) {
3090
          	$this->SetQname($q['name']);
3091
		$this->SetNumber($q['number']);
3092
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3093
       		       	$this->SetQlimit($q['qlimit']);
3094
		if (isset($q['mask']) && $q['mask'] <> "")
3095
              		$this->SetMask($q['mask']);
3096
       		if (isset($q['weight']) && $q['weight'] <> "")
3097
            		$this->SetWeight($q['weight']);
3098
            	if (isset($q['description']) && $q['description'] <> "")
3099
			$this->SetDescription($q['description']);
3100
		$this->SetEnabled($q['enabled']);
3101
        }
3102

    
3103
	function build_tree() {
3104
		$parent =& $this->GetParent();
3105
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3106
		$tree .= $this->GetQname() . "</a>";
3107
		$tree .= "</li>";
3108
		
3109
		return $tree;
3110
	}
3111

    
3112
        function build_rules() {
3113
		if ($this->GetEnabled() == "")
3114
			return; 
3115

    
3116
		$parent =& $this->GetParent();
3117
            	$pfq_rule = "dnqueue ". $this->GetNumber() . " dnpipe " . $parent->GetNumber();
3118
		if ($this->GetQlimit())
3119
                    	$pfq_rule .= " queue " . $this->GetQimit();
3120
		if ($this->GetWeight())
3121
			$pfq_rule .= " weight " . $this->GetWeight();
3122
		if ($this->GetBuckets())
3123
			$pfq_rule .= " buckets " . $this->GetBuckets();
3124
		$mask = $this->GetMask();
3125
		if (!empty($mask)) {
3126
			/* XXX TODO extend this to support more complicated masks */
3127
			switch ($mask) {
3128
			case 'srcaddress':
3129
				$pfq_rule .= " mask src-ip 0xffffffff ";
3130
				break;
3131
			case 'dstaddress':
3132
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3133
				break;
3134
			default:
3135
				break;
3136
			}
3137
			$pfq_rule .= "\n";
3138
		}
3139

    
3140
		return $pfq_rule;
3141
	}
3142

    
3143
        function build_form() { 
3144
		$form = "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
3145
		$form .= "<td class=\"vncellreq\">";
3146
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
3147
		$form .= $this->GetQname()."\">";
3148
		$form .= "</td></tr>";
3149
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Mask</td>";
3150
		$form .= "<td class=\"vncellreq\">";
3151
		$form .= "<select name=\"mask\" class=\"formselect\">";
3152
		$form .= "<option value=\"none\"";
3153
		if ($this->GetMask() == "none")
3154
			$form .= " selected=\"yes\"";
3155
		$form .= ">none</option>";
3156
		$form .= "<option value=\"srcaddress\"";
3157
		if ($this->GetMask() == "srcaddress")
3158
			$form .= " selected=\"yes\"";
3159
		$form .= ">Source addresses</option>";
3160
		$form .= "<option value=\"dstaddress\"";
3161
		if ($this->GetMask() == "dstaddress")
3162
			$form .= " selected=\"yes\"";
3163
		$form .= ">Destination addresses</option>";
3164
		$form .= "</select>";
3165
		$form .= "&nbsp;slots<br>";
3166
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
3167
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
3168
		$form .= "be created for each source/destination IP address encountered, \n";
3169
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
3170
		$form .= "limits per host.</span>";
3171
		$form .= "</td></tr>";
3172
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Description</td>";
3173
		$form .= "<td class=\"vncellreq\">";
3174
		$form .= "<input type=\"text\" id=\"description\" class=\"formfld unknown\" size=\"50%\" name=\"description\" value=\"";
3175
		$form .= $this->GetDescription();
3176
		$form .= "\">";
3177
		$form .= "<br> <span class=\"vexpl\">";
3178
		$form .= "You may enter a description here ";
3179
		$form .= "for your reference (not parsed).</span>";
3180
		$form .= "</td></tr>";
3181
		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3182
		$form .= "<td></td>";
3183
                $form .= "<td><div id=\"showadvancedboxspr\">";
3184
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3185
		$form .= " value=\"Show advanced options\"></input></a>";
3186
                $form .= "</div></td></tr>";
3187
		$form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3188
		$form .= "<td valign=\"top\" class=\"vncellreq\">Weight</td>";
3189
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
3190
		$form .= "<input name=\"weight\" type=\"text\" id=\"weight\" size=\"5\" value=\"";
3191
		$form .= $this->GetWeight() . "\">";
3192
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: For queues under the same parent "; 
3193
		$form .= "this specifies the share that a queue gets(values range from 1 to 100, you can leave it blank otherwise)</span>";
3194
		$form .= "</td></tr>";
3195
		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3196
		$form .= "<td valign=\"top\" class=\"vncellreq\">Packet loss rate</td>";
3197
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
3198
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3199
		$form .= $this->GetPlr() . "\">";
3200
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you "; 
3201
        	$form .= "should specify 0 here (or leave the field empty).";
3202
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
3203
		$form .= "</td></tr>";
3204
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3205
		$form .= "<td valign=\"top\" class=\"vncellreq\">Queue Size</td>";
3206
		$form .= "<td class=\"vncellreq\">";
3207
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3208
		$form .= $this->GetQlimit() . "\">";
3209
		$form .= "&nbsp;slots<br>";
3210
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3211
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, ";
3212
        	$form .= "then they are delayed by value specified in the Delay field, and then they ";
3213
		$form .= "are delivered to their destination.</span>";
3214
		$form .= "</td></tr>";
3215
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3216
                $form .= "<td valign=\"top\" class=\"vncellreq\">Bucket Size</td>";
3217
                $form .= "<td class=\"vncellreq\">";
3218
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3219
                $form .= $this->GetBuckets() . "\">";
3220
                $form .= "&nbsp;slots<br>";
3221
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
3222
                $form .= "should leave the field empty. It increases the hash size set.";
3223
                $form .= "</td></tr>";
3224

    
3225
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3226
		$form .= " value=\"" . $this->GetPipe() . "\">";
3227

    
3228
		return $form;
3229
			
3230
	}
3231

    
3232
        function update_dn_data(&$data) { 
3233
		$this->ReadConfig($data);
3234
	}
3235

    
3236
	function wconfig() {
3237
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3238
            	if (!is_array($cflink))
3239
            		$cflink = array();
3240
		$cflink['name'] = $this->GetQname();
3241
		$cflink['number'] = $this->GetNumber();
3242
            	$cflink['qlimit'] = $this->GetQlimit();
3243
            	$cflink['description'] = $this->GetDescription();
3244
		$cflink['weight'] = $this->GetWeight();
3245
		$cflink['enabled'] = $this->GetEnabled();
3246
		$cflink['buckets'] = $this->GetBuckets();
3247
		$cflink['mask'] = $this->GetMask();
3248
	}
3249
}
3250

    
3251
// List of layer7 objects
3252
$layer7_rules_list = array();
3253

    
3254
class layer7 {
3255
    
3256
    var $rname; //alias
3257
    var $rdescription; //alias description
3258
    var $rport; //divert port
3259
    var $renabled; //rule enabled
3260
    var $rsets = array(); //array of l7 associations
3261
    
3262
    // Auxiliary functions
3263
    
3264
    function GetRName() {
3265
        return $this->rname;
3266
    }
3267
    function SetRName($rname) {
3268
        $this->rname = $rname;
3269
    }
3270
    function GetRDescription() {
3271
        return $this->rdescription;
3272
    }
3273
    function SetRDescription($rdescription) {
3274
        $this->rdescription = $rdescription;
3275
    }
3276
    function GetRPort() {
3277
        return $this->rport;
3278
    }
3279
    function SetRPort($rport) {
3280
        $this->rport = $rport;
3281
    }
3282
    function GetREnabled() {
3283
        return $this->renabled;
3284
    }
3285
    function SetREnabled($value) {
3286
        $this->renabled = $value;
3287
    }
3288
    function GetRl7() {
3289
        return $this->rsets;
3290
    }
3291
    function SetRl7($rsets) {
3292
        $this->rsets = $rsets;
3293
    }
3294
    
3295
    //Add a tuple (rule,sctructure,element) to the $rsets
3296
    
3297
    function add_rule($l7set) {
3298
       	$this->rsets[] = $l7set;
3299
    }
3300
    
3301
    // Build the layer7 rules
3302
    function build_l7_rules() {
3303
        if($this->GetREnabled() == "") {
3304
            return;
3305
        }
3306
        //$l7rules = "#" . $this->rdescription . "\n";
3307
        foreach ($this->rsets as $rl7) {
3308
            $l7rules .= $rl7->build_rules();
3309
        }
3310
        return $l7rules;
3311
    }
3312
    
3313
    // Read the config from array
3314
    function ReadConfig(&$qname, &$q) {
3315
        $this->SetRName($qname);
3316
        $this->SetREnabled($q['enabled']);
3317
        $this->SetRPort($q['divert_port']);
3318
        if(isset($q['description']) && $q['description'] <> "")
3319
            $this->SetRDescription($q['description']);
3320
        $rsets = $q['l7rules'];
3321
        //Put individual rules in the array
3322
	if(is_array($rsets)) {
3323
	    $this->rsets = array(); // XXX: ugly hack
3324
	    foreach($rsets as $l7r) {
3325
	        $l7obj = new l7rule();
3326
	        $l7obj->SetRProtocol($l7r['protocol']);
3327
	        $l7obj->SetRStructure($l7r['structure']);
3328
	        $l7obj->SetRBehaviour($l7r['behaviour']);
3329
	        $this->add_rule($l7obj);
3330
	    }
3331
	}
3332
    }
3333
    
3334
    //Generate a random port for the divert socket
3335
    function gen_divert_port() {
3336
        $dports = get_divert_ports(); //array of used ports
3337
	$divert_port = 1; // Initialize
3338
	while (($divert_port % 2) != 0 || in_array($divert_port, $dports)) {
3339
		$divert_port = rand(40000, 60000);
3340
	}
3341
        return $divert_port;
3342
    }
3343
    
3344
    //Helps building the left tree
3345
    function build_tree() {
3346
        $tree = " <li><a href=\"firewall_shaper_layer7.php?container=" . $this->GetRName() ."&action=show\">"; 
3347
        $tree .= $this->GetRName() . "</a>";
3348
	$tree .= "</li>";
3349
		
3350
	return $tree;
3351
    }
3352
    
3353
    function build_form() {
3354
        $form = "<tr><td valign=\"top\" class=\"vncellreq\"><br>";
3355
	$form .= "Enable/Disable";
3356
	$form .= "</td><td class=\"vncellreq\">";
3357
	$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\"";
3358
	if ($this->GetREnabled()) {
3359
       	    $form .=  "checked = \"CHECKED\"";
3360
	}
3361
	$form .= " ><span class=\"vexpl\"> Enable/Disable layer7 Container</span>";
3362
	$form .= "</td></tr>";
3363
        $form .= "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
3364
	$form .= "<td class=\"vncellreq\">";
3365
	$form .= "<input type=\"text\" id=\"container\" name=\"container\" value=\"";
3366
	$form .= $this->GetRName()."\">";
3367
	$form .= "</td></tr>";
3368
	$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Description</td>";
3369
	$form .= "<td class=\"vncellreq\">";
3370
	$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3371
	$form .= $this->GetRDescription();
3372
	$form .= "\">";
3373
	$form .= "<br> <span class=\"vexpl\">";
3374
	$form .= "You may enter a description here ";
3375
	$form .= "for your reference (not parsed).</span>";
3376
	$form .= "</td></tr>";
3377
	
3378
	return $form;
3379
    }
3380
    
3381
    //Write the setting to the $config array
3382
    function wconfig() {
3383
	global $config;
3384
	
3385
	if(!is_array($config['l7shaper']['container'])) {
3386
		$config['l7shaper']['container'] = array();
3387
	}
3388
        //
3389
        $cflink =& get_l7c_reference_to_me_in_config($this->GetRName());
3390
	// Test if this rule does exists already
3391
	if(!$cflink) {
3392
		$cflink =& $config['l7shaper']['container'][];
3393
	}
3394
	$cflink['name'] = $this->GetRName();
3395
        $cflink['enabled'] = $this->GetREnabled();
3396
        $cflink['description'] = $this->GetRDescription();
3397
        $cflink['divert_port'] = $this->GetRPort();
3398
        
3399
	//Destroy previously existent rules
3400
	if(is_array($cflink['rules'])) {
3401
		unset($cflink['l7rules']);
3402
	}
3403
	
3404
        $cflink['l7rules'] = array();
3405
	
3406
        $i = 0;
3407
        foreach($this->rsets as $rulel7) {
3408
            $cflink['l7rules'][$i]['protocol'] = $rulel7->GetRProtocol();
3409
            $cflink['l7rules'][$i]['structure'] = $rulel7->GetRStructure();
3410
            $cflink['l7rules'][$i]['behaviour'] = $rulel7->GetRBehaviour();
3411
            $i++;
3412
        }
3413
    }
3414
    
3415
    //This function is necessary to help producing the overload options for keep state
3416
    function get_unique_structures() {
3417
        
3418
        $unique_structures = array("action" => false, "dummynet" => false, "altq" => false);
3419
        foreach($this->rsets as $l7rule) {
3420
		if($l7rule->GetRStructure() == "action")
3421
			$unique_structures['action'] = true;
3422
		else if($l7rule->GetRStructure() == "limiter")
3423
			$unique_structures['dummynet'] = true;
3424
		else
3425
			$unique_structures['altq'] = true;
3426
        }
3427
	//Delete non used structures so we don't have to check this in filter.inc
3428
	foreach($unique_structures as $key => $value)
3429
		if(!$value)
3430
			unset($unique_structures[$key]);
3431
        return $unique_structures;
3432
    }
3433
    
3434
    function validate_input($data, &$input_errors) {
3435
	$reqdfields[] = "container";
3436
	$reqdfieldsn[] = "Name";
3437
		
3438
	shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
3439
        
3440
        if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['container']))
3441
            $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
3442
    }
3443
    
3444
    function delete_l7c() {
3445
	$l7pid = `/bin/ps -ax | /usr/bin/grep ipfw-classifyd | /usr/bin/grep ". $l7rules->GetRPort() . " | /usr/bin/grep -v grep | /usr/bin/awk '{ print $1 }'`;
3446
	mwexec("/bin/kill {$l7pid}");
3447
	unset_l7_object_by_reference($this->GetRName());
3448
	cleanup_l7_from_rules($this->GetRName());
3449
    }
3450
}
3451

    
3452
class l7rule {
3453
    
3454
    var $rprotocol; //protocol
3455
    var $rstructure; //action, limiter, queue
3456
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3457
    
3458
    //Auxiliary Functions
3459
    
3460
    function GetRProtocol() {
3461
        return $this->rprotocol;
3462
    }
3463
    function SetRProtocol($rprotocol) {
3464
        $this->rprotocol = $rprotocol;
3465
    }
3466
    function GetRStructure() {
3467
        return $this->rstructure;
3468
    }
3469
    function SetRStructure($rstructure) {
3470
        $this->rstructure = $rstructure;
3471
    }
3472
    function GetRBehaviour() {
3473
        return $this->rbehaviour;
3474
    }
3475
    function SetRBehaviour($rbehaviour) {
3476
        $this->rbehaviour = $rbehaviour;
3477
    }
3478
    
3479
    //XXX Do we need to test any particularity for AltQ queues?
3480
    function build_rules() {
3481
	global $dummynet_pipe_list;
3482
	switch ($this->GetRStructure()) {
3483
		case "limiter":
3484
			read_dummynet_config();
3485
			$dn_list =& get_unique_dnqueue_list();
3486
			$found = false;
3487
			if(is_array($dn_list)) {
3488
				foreach($dn_list as $key => $value) {
3489
					if($key == $this->GetRBehaviour()) {
3490
						if($value[0] == "?")
3491
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3492
						else
3493
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3494
						$found = true;
3495
					}
3496
					if($found)
3497
						break;
3498
				}
3499
			}
3500
			break;
3501
		default: //This is for action and for altq
3502
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3503
			break;
3504
	}
3505
        return $l7rule;
3506
    }
3507
}
3508

    
3509
/*
3510
 * This function allows to return an array with all the used divert socket ports
3511
 */
3512
function get_divert_ports() {
3513
    global $layer7_rules_list;
3514
    $dports = array();
3515
    
3516
    foreach($layer7_rules_list as $l7r)
3517
        $dports[] = $l7r->GetRPort();
3518
    
3519
    return $dports;
3520
}
3521

    
3522
function &get_l7c_reference_to_me_in_config(&$name) {
3523
	global $config;
3524
	
3525
	$ptr = NULL;
3526
	
3527
	if(is_array($config['l7shaper']['container'])) {
3528
		foreach($config['l7shaper']['container'] as $key => $value) {
3529
			if($value['name'] == $name)
3530
				$ptr =& $config['l7shaper']['container'][$key];
3531
		}
3532
	}	
3533
	return $ptr;
3534
// $ptr can be null. has to be checked later
3535
}
3536

    
3537
function unset_l7_object_by_reference(&$name) {
3538
	global $config;
3539
        
3540
	if(is_array($config['l7shaper']['container'])) {
3541
		foreach($config['l7shaper']['container'] as $key => $value) {
3542
			if($value['name'] == $name) {
3543
				unset($config['l7shaper']['container'][$key]['l7rules']);
3544
				unset($config['l7shaper']['container'][$key]);
3545
				break;
3546
			}
3547
		}
3548
	}
3549
}
3550

    
3551
function read_layer7_config() {
3552
    global $layer7_rules_list, $config;
3553
    
3554
    $l7cs = &$config['l7shaper']['container'];
3555
    
3556
    $layer7_rules_list = array();
3557
    
3558
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3559
	return;
3560
    
3561
    foreach ($l7cs as $conf) {
3562
	if (empty($conf['name']))
3563
		continue; /* XXX: grrrrrr at php */ 
3564
        $root =& new layer7();
3565
        $root->ReadConfig($conf['name'],$conf);
3566
        $layer7_rules_list[$root->GetRName()] = &$root;
3567
    }
3568
}
3569

    
3570
function generate_layer7_files() {
3571
    global $layer7_rules_list, $g;
3572
    
3573
    read_layer7_config();
3574
    
3575
    if (!empty($layer7_rules_list)) {
3576
	if (!is_module_loaded("ipdivert.ko"))
3577
		mwexec("/sbin/kldload ipdivert.ko");
3578

    
3579
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3580
    }
3581
    
3582
    foreach($layer7_rules_list as $l7rules) {
3583
        if($l7rules->GetREnabled()) {
3584
            $filename = $l7rules->GetRName() . ".l7";
3585
            $path = "{$g['tmp_path']}/" . $filename;
3586
        
3587
            $rules = $l7rules->build_l7_rules();
3588
        
3589
            $fp = fopen($path,'w');
3590
            fwrite($fp,$rules);
3591
            fclose($fp);
3592
        }
3593
    }
3594
}
3595

    
3596
function layer7_start_l7daemon() {
3597
    global $layer7_rules_list, $g;
3598

    
3599
    /*
3600
     * XXX: ermal - Needed ?!
3601
     * read_layer7_config();
3602
     */
3603

    
3604
    foreach($layer7_rules_list as $l7rules) {
3605
        if($l7rules->GetREnabled()) {
3606
            $filename = $l7rules->GetRName() . ".l7";
3607
            $path = "{$g['tmp_path']}/" . $filename;
3608

    
3609
	    unset($l7pid);
3610
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3611
	    exec("/bin/ps -ax | /usr/bin/grep ipfw-classifyd | /usr/bin/grep ". $l7rules->GetRPort() . " | /usr/bin/grep -v grep | /usr/bin/awk '{ print $1}'", $l7pid);
3612
	    if (count($l7pid) > 0) {
3613
		log_error("Sending HUP signal to {$l7pid[0]}");
3614
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3615
	    } else {
3616
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3617
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3618
		mwexec_bg($ipfw_classifyd_init);
3619
	    }
3620
        }
3621
    }
3622
}
3623

    
3624
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3625
function generate_protocols_array() {
3626
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3627
	$protocols_new = array();
3628
	if(is_array($protocols)) {
3629
		foreach($protocols as $key => $proto) {
3630
			if (strstr($proto, ".pat"))
3631
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3632
		}
3633
		sort($protocols_new);
3634
	}		
3635
	return $protocols_new;
3636
}
3637

    
3638
function get_l7_unique_list() {
3639
	global $layer7_rules_list;
3640
	
3641
	$l7list = array();
3642
	if(is_array($layer7_rules_list)) 
3643
		foreach($layer7_rules_list as $l7c)
3644
			if($l7c->GetREnabled())
3645
				$l7list[] = $l7c->GetRName();
3646
	
3647
	return $l7list;
3648
}
3649

    
3650
// Disable a removed l7 container from the filter
3651
function cleanup_l7_from_rules(&$name) {
3652
	global $config;
3653

    
3654
	if(is_array($config['filter']['rule']))
3655
		foreach ($config['filter']['rule'] as $key => $rule) {
3656
			if ($rule['l7container'] == $name)
3657
				unset($config['filter']['rule'][$key]['l7container']);
3658
		}
3659
}
3660

    
3661
function get_dummynet_name_list() {
3662
	
3663
	$dn_name_list =& get_unique_dnqueue_list();
3664
	$dn_name = array();
3665
	if(is_array($dn_name_list))
3666
		foreach($dn_name_list as $key => $value)
3667
			$dn_name[] = $key;
3668
	
3669
	return $dn_name;
3670
	
3671
}
3672

    
3673
function get_altq_name_list() {
3674
	$altq_name_list =& get_unique_queue_list();
3675
	$altq_name = array();
3676
	if(is_array($altq_name_list))
3677
		foreach($altq_name_list as $key => $aqobj)
3678
			$altq_name[] = $key;
3679
		
3680
	return $altq_name;
3681
}
3682

    
3683
/*
3684
 * XXX: TODO Make a class shaper to hide all these function
3685
 * from the global namespace.
3686
 */
3687

    
3688
/* 
3689
 * This is a layer violation but for now there is no way 
3690
 * i can find to properly do this with PHP.
3691
 */
3692
function altq_set_default_queue($interface, $value) {
3693
	global $altq_list_queues;
3694
		
3695
	$altq_tmp =& $altq_list_queues[$interface];
3696
	if ($altq_tmp) {
3697
		if ($value) {
3698
			$altq_tmp->SetDefaultQueuePresent("true");
3699
		}
3700
		else {
3701
			$altq_tmp->SetDefaultQueuePresent("false");
3702
		}
3703
	}
3704
}
3705

    
3706
function altq_get_default_queue($interface) {
3707
	global $altq_list_queues;
3708

    
3709
	$altq_tmp = $altq_list_queues[$interface];
3710
	if ($altq_tmp)  
3711
		return $altq_tmp->GetDefaultQueuePresent(); 
3712
}
3713

    
3714
function altq_check_default_queues() {
3715
	global $altq_list_queues;
3716

    
3717
	$count = 0;
3718
	if (is_array($altq_list_queues)) {
3719
		foreach($altq_list_queues as $altq) {
3720
			if ($altq->GetDefaultQueuePresent())
3721
				$count++;
3722
		}
3723
	}
3724
	else  $count++;;
3725
	
3726
	return 0;
3727
}
3728

    
3729
function &get_unique_queue_list() {
3730
	global $altq_list_queues;
3731
	
3732
	$qlist = array();
3733
	if (is_array($altq_list_queues)) {
3734
		foreach ($altq_list_queues as $altq) {
3735
			$tmplist =& $altq->get_queue_list();
3736
			foreach ($tmplist as $qname => $link)
3737
				$qlist[$qname] = $link;	
3738
		}
3739
	}
3740
	return $qlist;
3741
}
3742

    
3743
function &get_unique_dnqueue_list() {
3744
	global $dummynet_pipe_list;
3745
	
3746
	$qlist = array();
3747
	if (is_array($dummynet_pipe_list)) {
3748
		foreach ($dummynet_pipe_list as $dn) {
3749
			$tmplist =& $dn->get_queue_list();
3750
			foreach ($tmplist as $qname => $link)
3751
				$qlist[$qname] = $link;	
3752
		}
3753
	}
3754
	return $qlist;
3755
}
3756

    
3757
function ref_on_altq_queue_list($parent, $qname) {
3758
	if (isset($GLOBALS['queue_list'][$qname]))
3759
		$GLOBALS['queue_list'][$qname]++;
3760
	else
3761
		$GLOBALS['queue_list'][$qname] = 1;
3762

    
3763
	unref_on_altq_queue_list($parent);
3764
}
3765

    
3766
function unref_on_altq_queue_list($qname) {
3767
	$GLOBALS['queue_list'][$qname]--;
3768
	if ($GLOBALS['queue_list'][$qname] <= 1)
3769
		unset($GLOBALS['queue_list'][$qname]);	
3770
}
3771

    
3772
function read_altq_config() {
3773
	global $altq_list_queues, $config;
3774
	$path = array();
3775
	
3776
	if (!is_array($config['shaper']))
3777
		$config['shaper'] = array();
3778
	if (!is_array($config['shaper']['queue']))
3779
		$config['shaper']['queue'] = array();
3780
	$a_int = &$config['shaper']['queue'];
3781

    
3782
	$altq_list_queues = array();
3783
	
3784
	if (!is_array($config['shaper']['queue']))
3785
		return;
3786

    
3787
	foreach ($a_int as $key => $conf) {
3788
				$int = $conf['interface'];
3789
				$root =& new altq_root_queue();
3790
				$root->SetInterface($int);
3791
				$altq_list_queues[$root->GetInterface()] = &$root;
3792
				$root->ReadConfig($conf);
3793
		array_push($path, $key);
3794
		$root->SetLink($path);
3795
		if (is_array($conf['queue'])) {
3796
			foreach ($conf['queue'] as $key1 => $q) {
3797
				array_push($path, $key1);
3798
				/* 
3799
				 * XXX: we compeletely ignore errors here but anyway we must have 
3800
				 *	checked them before so no harm should be come from this.
3801
				 */
3802
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3803
				array_pop($path);
3804
			} 	
3805
				}
3806
		array_pop($path);
3807
	}
3808
}
3809

    
3810
function read_dummynet_config() {
3811
	global $dummynet_pipe_list, $config;
3812
	$path = array();
3813
	$dnqueuenumber = 1;
3814
	$dnpipenumber = 1;
3815

    
3816
	if (!is_array($config['dnshaper']))
3817
		$config['dnshaper'] = array();
3818
	if (!is_array($config['dnshaper']['queue']))
3819
		$config['dnshaper']['queue'] = array();
3820
	$a_int = &$config['dnshaper']['queue'];
3821

    
3822
	$dummynet_pipe_list = array();
3823
	
3824
	if (!is_array($config['dnshaper']['queue'])
3825
		|| !count($config['dnshaper']['queue']))
3826
		return;
3827

    
3828
	foreach ($a_int as $key => $conf) {
3829
		if (empty($conf['name']))
3830
			continue; /* XXX: grrrrrr at php */ 
3831
		$root =& new dnpipe_class();
3832
		$root->ReadConfig($conf);
3833
		$root->SetNumber($dnpipenumber);	
3834
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3835
		array_push($path, $key);
3836
		$root->SetLink($path);
3837
		if (is_array($conf['queue'])) {
3838
			foreach ($conf['queue'] as $key1 => $q) {
3839
				array_push($path, $key1);
3840
				/* XXX: We cheat a little here till a better way is found. */
3841
				$q['number'] = $dnqueuenumber;
3842
				/* 
3843
				 * XXX: we compeletely ignore errors here but anyway we must have 
3844
				 *	checked them before so no harm should be come from this.
3845
				 */	
3846
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3847
				array_pop($path);
3848

    
3849
				$dnqueuenumber++;
3850
			} 	
3851
		}
3852
		array_pop($path);
3853
			
3854
		$dnpipenumber++;
3855
	}
3856
}
3857

    
3858
function get_interface_list_to_show() {
3859
	global $altq_list_queues, $config;
3860
	global $shaperIFlist;
3861

    
3862
	$tree = "";
3863
	foreach ($shaperIFlist as $shif => $shDescr) {
3864
		if ($altq_list_queues[$shif]) {
3865
			continue;
3866
		} else  {
3867
			if (!is_altq_capable(get_real_interface($shif)))
3868
				continue;
3869
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3870
		}
3871
	}
3872
	
3873
	return $tree;
3874
}
3875

    
3876
function filter_generate_altq_queues() {
3877
	global $altq_list_queues;
3878
	
3879
	read_altq_config();
3880

    
3881
	$altq_rules = "";
3882
	foreach ($altq_list_queues as $altq) 
3883
		$altq_rules .= $altq->build_rules();
3884

    
3885
	return $altq_rules;
3886
}
3887

    
3888
function filter_generate_dummynet_rules() {
3889
	global $dummynet_pipe_list;
3890
	
3891
	read_dummynet_config();
3892
	
3893
	if (!empty($dummynet_pipe_list)) {
3894
		if (!is_module_loaded("dummynet.ko"))
3895
			mwexec("/sbin/kldload dummynet");
3896
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
3897
		//mwexec("pfctl -F dummynet");
3898
	}
3899

    
3900
	$dn_rules = "";
3901
	foreach ($dummynet_pipe_list as $dn) 
3902
		$dn_rules .= $dn->build_rules();
3903

    
3904
	return $dn_rules;
3905
}
3906

    
3907
function build_iface_without_this_queue($iface, $qname) {
3908
	global $g, $altq_list_queues;
3909

    
3910
	$altq =& $altq_list_queues[$iface];
3911
				if ($altq)
3912
						$scheduler = ": " . $altq->GetScheduler();
3913
	$form = "<tr><td width=\"20%\" >";
3914
	$form .= "<a href=\"firewall_shaper.php?interface" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
3915
		$form .= "</td></tr>";
3916
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
3917
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
3918
		$form .= $iface . "&queue=". $qname . "&action=add\">";
3919
		$form .= "<img src=\"";
3920
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
3921
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
3922
		$form .= " Clone shaper/queue on this interface</a></td></tr>";
3923

    
3924
		return $form;
3925

    
3926
}
3927

    
3928

    
3929
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3930
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
3931
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3932
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3933
$default_shaper_msg .= " </p></strong></span>";
3934
$default_shaper_msg .= "</td></tr>";
3935

    
3936
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3937
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the {$g['product_name']} Traffic Shaper.</b><br />";
3938
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3939
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3940
$dn_default_shaper_msg .= " </p></strong></span>";
3941
$dn_default_shaper_msg .= "</td></tr>";
3942

    
3943

    
3944

    
3945
?>
(37-37/50)