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 $delay;
2734
	var $qbandwidth;
2735
	var $qbandwidthtype;
2736

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

    
2740
	function CanHaveChildren() {
2741
	        return true;
2742
        }
2743
	function SetDelay($delay) {
2744
		$this->delay = $delay;
2745
	}
2746
	function GetDelay() {
2747
		return $this->delay;
2748
	}
2749
	function GetBwscale() {
2750
                return $this->qbandwidthtype;
2751
        }
2752
        function SetBwscale($scale) {
2753
               	$this->qbandwidthtype = $scale;
2754
        }		
2755
	function delete_queue() {
2756
		cleanup_dnqueue_from_rules($this->GetQname());
2757
		foreach ($this->subqueues as $q)
2758
			$q->delete_queue();
2759
		unset_dn_object_by_reference($this->GetLink());
2760
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
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 = "\npipe ". $this->GetNumber();
2869
		if ($this->GetBandwidth() && $this->GetBwscale())
2870
                    	$pfq_rule .= " bw ".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
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3062
        }
3063

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

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

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

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

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

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

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

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

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

    
3141
		return $pfq_rule;
3142
	}
3143

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

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

    
3229
		return $form;
3230
			
3231
	}
3232

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3764
	unref_on_altq_queue_list($parent);
3765
}
3766

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3886
	return $altq_rules;
3887
}
3888

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

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

    
3905
	if (!empty($dnrules)) {
3906
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
3907
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
3908
	}
3909
	//return $dn_rules;
3910
}
3911

    
3912
function build_iface_without_this_queue($iface, $qname) {
3913
	global $g, $altq_list_queues;
3914

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

    
3929
		return $form;
3930

    
3931
}
3932

    
3933

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

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

    
3948

    
3949

    
3950
?>
(37-37/50)