Project

General

Profile

Download (121 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

    
28
/* include all configuration functions */
29
require_once("functions.inc");
30

    
31
/*
32
 * I admit :) this is derived from xmplparse.inc StartElement()
33
 */
34
function &get_reference_to_me_in_config(&$mypath) 
35
{
36
	global $config;
37

    
38
		 $ptr =& $config['shaper'];
39
	foreach ($mypath as $indeks) {
40
				$ptr =& $ptr['queue'][$indeks];
41
		}
42

    
43
	return $ptr;
44
}
45

    
46
function unset_object_by_reference(&$mypath) 
47
{
48
	global $config;
49

    
50
		$ptr =& $config['shaper'];
51
		for ($i = 0; $i < count($mypath) - 1; $i++) {
52
				$ptr =& $ptr['queue'][$mypath[$i]];
53
		}
54
	unset($ptr['queue'][$mypath[$i]]);
55
}
56

    
57
function &get_dn_reference_to_me_in_config(&$mypath) 
58
{
59
	global $config;
60

    
61
		 $ptr =& $config['dnshaper'];
62
	foreach ($mypath as $indeks) {
63
				$ptr =& $ptr['queue'][$indeks];
64
		}
65

    
66
	return $ptr;
67
}
68

    
69
function unset_dn_object_by_reference(&$mypath) 
70
{
71
	global $config;
72

    
73
		$ptr =& $config['dnshaper'];
74
		for ($i = 0; $i < count($mypath) - 1; $i++) {
75
				$ptr =& $ptr['queue'][$mypath[$i]];
76
		}
77
	unset($ptr['queue'][$mypath[$i]]);
78
}
79

    
80
function clean_child_queues($type, $mypath) 
81
{
82
	$ref = &get_reference_to_me_in_config($mypath);
83

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

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

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

    
159
function get_interface_bandwidth($object) 
160
{
161
	global $altq_list_queues;
162

    
163
        $int = $object->GetInterface();
164
        $altq =& $altq_list_queues[$int];
165
        if ($altq) {
166
                $bw_3 = $altq->GetBandwidth();
167
                $bw_3 = $bw_3 *  get_bandwidthtype_scale($altq->GetBwscale());
168
		return floatval($bw_3);
169
        } else return 0;
170
}
171

    
172
/*
173
 * This is duplicated here since we cannot include guiconfig.inc.
174
 * Including it makes all stuff break.
175
 */
176
function shaper_do_input_validation($postdata, $reqdfields, $reqdfieldsn, $input_errors) 
177
{
178

    
179
        /* check for bad control characters */
180
        foreach ($postdata as $pn => $pd) {
181
                if (is_string($pd) && preg_match("/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/", $pd)) {
182
                        $input_errors[] = "The field '" . $pn . "' contains invalid characters.";
183
                }
184
        }
185

    
186
        for ($i = 0; $i < count($reqdfields); $i++) {
187
                if ($postdata[$reqdfields[$i]] == "") {
188
                        $input_errors[] = "The field '" . $reqdfieldsn[$i] . "' is required.";
189
                }
190
        }
191
}
192

    
193
function cleanup_queue_from_rules($queue) 
194
{
195
	global $config;
196

    
197
	foreach ($config['filter']['rule'] as $rule) {
198
		if ($rule['defaultqueue'] == $queue)
199
			unset($rule['defaultqueue']);
200
		if ($rule['ackqueue'] == $queue)
201
			unset($rule['ackqueue']);
202
	}
203
}
204

    
205
function cleanup_dnqueue_from_rules($queue) 
206
{
207
	global $config;
208

    
209
	foreach ($config['filter']['rule'] as $rule) {
210
		if ($rule['dnpipe'] == $queue)
211
			unset($rule['dnpipe']);
212
		if ($rule['pdnpipe'] == $queue)
213
			unset($rule['pdnpipe']);
214
	}
215
}
216

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

    
230
		/* Accesor functions */
231
	function GetAvailableBandwidth() {
232
		return $this->available_bw;
233
	}
234
	function SetAvailableBandwidth($bw) {
235
		$this->available_bw = $bw;
236
	}
237
	function SetDefaultQueuePresent($value) {
238
		$this->default_present = $value;
239
	}
240
	function GetDefaultQueuePresent() {
241
		return trim($this->default_present);
242
	}
243
	function SetLink($link) {
244
		$this->link = $link;
245
	}
246
	function GetLink() {
247
		return $this->link;
248
	}	
249
	function GetEnabled() {
250
		return $this->qenabled;
251
	}
252
	function SetEnabled($value) {
253
		$this->qenabled = $value;
254
	}
255
	function CanHaveChilds() {
256
		return true;
257
	}
258
	function CanBeDeleted() {
259
		return false;
260
	}
261
	function GetQname() {
262
		return $this->interface;
263
	}
264
	function SetQname($name) {
265
		$this->interface = trim($name);
266
	}
267
	function GetInterface() {
268
			return $this->interface;
269
	}
270
	function SetInterface($name) {
271
			$this->interface = trim($name);
272
	}
273
	function GetTbrConfig() {
274
			return $this->tbrconfig;
275
	}
276
	function SetTbrConfig($tbrconfig) {
277
			$this->tbrconfig = $tbrconfig;
278
	}
279
	function GetBandwidth() {
280
			return $this->bandwidth;
281
	}
282
	function SetBandwidth($bw) {
283
			$this->bandwidth = $bw;
284
	}
285
	function GetBwscale() {
286
			return $this->bandwidthtype;
287
	}
288
	function SetBwscale($bwscale) {
289
			$this->bandwidthtype = $bwscale;
290
	}
291
	function GetScheduler() {
292
			return $this->scheduler;
293
	}
294
	function SetScheduler($scheduler) {
295
			$this->scheduler = trim($scheduler);
296
	}
297
	function GetQlimit() {
298
		return $this->qlimit;
299
	}
300
	function SetQlimit($limit) {
301
		$this->qlimit = $limit;
302
	}
303
	
304
	function validate_input($data, &$input_errors) {
305
		
306
		$reqdfields[] = "bandwidth";
307
		$reqdfieldsn[] = "Bandwidth";
308
		$reqdfields[] = "bandwidthtype";
309
		$reqdfieldsn[] = "Bandwidthtype";
310
		
311
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
312
		
313
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
314
                                                $input_errors[] = "Bandwidth must be an integer.";
315
                if ($data['bandwidth'] < 0)
316
                                                $input_errors[] = "Bandwidth cannot be negative.";
317
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
318
                                                $input_errors[] = "Qlimit must be an integer.";
319
	 	if ($data['qlimit'] < 0)
320
                                                $input_errors[] = "Qlimit must be an positive.";
321
                if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig'])))
322
                                                $input_errors[] = "Tbrsize must be an integer.";
323
                if ($data['tbrconfig'] < 0)
324
                                                $input_errors[] = "Tbrsize must be an positive.";
325
	}
326

    
327

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

    
352
	}
353
	
354
	function copy_queue($interface, &$cflink) {
355
                $cflink['interface'] = $interface;
356
                $cflink['name'] = $interface;
357
                $cflink['scheduler'] = $this->GetScheduler();
358
                $cflink['bandwidth'] = $this->GetBandwidth();
359
                $cflink['bandwidthtype'] = $this->GetBwscale();
360
                $cflink['qlimit'] = $this->GetQlimit();
361
                $cflink['tbrconfig'] = $this->GetTbrConfig();
362
                $cflink['enabled'] = $this->GetEnabled();
363
		if (is_array($this->queues)) {
364
			$cflink['queue'] = array();
365
			foreach ($this->queues as $q) {
366
				$cflink['queue'][$q->GetQname()] = array();
367
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
368
			}
369
		}
370
	}
371

    
372

    
373
		function &get_queue_list($q = null) {
374
			$qlist = array();
375
			
376
			$qlist[$this->GetQname()] = & $this;
377
			if (is_array($this->queues)) {
378
				foreach ($this->queues as $queue)
379
					$queue->get_queue_list(&$qlist);
380
			}
381
			return $qlist;
382
		}
383

    
384
		function &add_queue($interface, &$queue, &$path, &$input_errors) {
385

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

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

    
442
		/* interface here might be optional */
443
		function &find_queue($interface, $qname) {
444
			if ($qname == $this->GetQname()) {
445
				return $this;
446
			} 
447
			foreach ($this->queues as $q) {
448
				$result =& $q->find_queue("", $qname);
449
				if ($result)
450
					return $result;
451
			}
452
		}
453

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

    
468
	function build_tree() {
469
		global $shaperIFlist;
470

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

    
492
	function delete_all() {
493
                if (count($this->queues)) {
494
                        foreach ($this->queues as $q) {
495
                        	$q->delete_all();
496
                        	unset_object_by_reference($q->GetLink());
497
                                unset($q);
498
               		}
499
        	        unset($this->queues);
500
                }
501
        }
502

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

    
541
	function build_javascript() {
542
			$javascript = "<script type=\"text/javascript\">";
543
			$javascript .= "function mySuspend() {";
544
			$javascript .= "if (document.layers && document.layers['shaperarea'] != null);";
545
			$javascript .= "document.layers['shaperarea'].visibility = 'hidden';";
546
			$javascript .= "else if (document.all)";
547
			$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';";
548
			$javascript .= "}";
549

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

    
558
			return $javascript;
559
	}
560
	
561
	function build_shortform() {
562
			global $g;
563

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

    
584
			return $form;
585

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

    
665

    
666
		return $form;
667
	}
668

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

    
691
}
692

    
693
class priq_queue {
694
	var $qname;
695
	var $qinterface; 
696
	var $qlimit;
697
	var $qpriority;
698
	var $description;
699
	var $isparent;
700
	var $qbandwidth;
701
	var $qbandwidthtype;
702
	var $qdefault;
703
	var $qrio;
704
	var $qred;
705
	var $qecn;
706
	var $qack;
707
	var $qenabled;
708
	var $qparent;
709
	var $link;
710
	var $available_bw; /* in b/s */
711

    
712
	/* This is here to help on form building and building rules/lists */
713
		var $subqueues = array();
714

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

    
826
	function build_javascript() {
827
		$javascript = "<script type=\"text/javascript\">";
828
		$javascript .= "function mySuspend() { \n";
829
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);\n";
830
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
831
		$javascript .= "else if (document.all)\n";
832
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
833
		$javascript .= "}\n";
834

    
835
		$javascript .= "function myResume() {\n";
836
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
837
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
838
		$javascript .= "else if (document.all)\n";
839
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
840
		$javascript .= "}\n";
841
		$javascript .= "</script>";
842
		
843
		return $javascript;
844
	}
845
	
846
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
847

    
848
	/* 
849
	 * Currently this will not be called unless we decide to clonce whole 
850
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
851
	 */
852
	 function copy_queue($interface, &$cflink) {
853

    
854
 		$cflink['name'] = $this->GetQname();
855
                $cflink['interface'] = $interface;
856
                $cflink['qlimit'] = $this->GetQlimit();
857
                $cflink['priority'] = $this->GetQpriority();
858
                $cflink['description'] = $this->GetDescription();
859
                $cflink['enabled'] = $this->GetEnabled();
860
                $cflink['default'] = $this->GetDefault();
861
                $cflink['red'] = $this->GetRed();
862
                $cflink['rio'] = $this->GetRio();
863
                $cflink['ecn'] = $this->GetEcn();
864

    
865
                if (is_array($this->subqueues)) {
866
                        $cflinkp['queue'] = array();
867
                        foreach ($this->subqueues as $q) {
868
				 $cflink['queue'][$q->GetQname()] = array();
869
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
870
			}
871
                }
872

    
873
	 }
874

    
875
	function clean_queue($sched) {
876
		clean_child_queues($sched, $this->GetLink());
877
		if (is_array($this->subqueues)) {
878
				foreach ($this->subqueues as $q)
879
						$q->clean_queue($sched);
880
				}
881
		}
882

    
883

    
884
		
885
        function &get_queue_list(&$qlist) {
886
                        $qlist[$this->GetQname()] = & $this;
887
                        if (is_array($this->subqueues)) {
888
                                foreach ($this->subqueues as $queue)
889
                                        $queue->get_queue_list($qlist);
890
                        }
891
        }
892

    
893
	function delete_queue() {
894
		unref_on_altq_queue_list($this->GetQname());
895
		if ($this->GetDefault())
896
				altq_set_default_queue($this->GetInterface(), "false");
897
		cleanup_queue_from_rules($this->GetQname());
898
		unset_object_by_reference($this->GetLink());
899
	}
900
	
901
	function delete_all() {
902
                if (count($this->subqueues)) {
903
                        foreach ($this->subqueues as $q) {
904
                                $q->delete_all();
905
                                unset_object_by_reference($q->GetLink());
906
                                unset($q);
907
                        }
908
                        unset($this->subqueues);
909
                }
910
        }
911

    
912
	 function &find_queue($interface, $qname) { 
913
		if ($qname == $this->GetQname())
914
			return $this; 
915
	}
916
	
917
	function find_parentqueue($interface, $qname) { return; }
918
		
919
	function validate_input($data, &$input_errors) {
920
	
921
		$reqdfields[] = "name";
922
		$reqdfieldsn[] = "Name";
923
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
924

    
925
		if ($data['priority'] && (!is_numeric($data['priority'])
926
						|| ($data['priority'] < 1) || ($data['priority'] > 15))) {
927
					$input_errors[] = "The priority must be an integer between 1 and 15.";
928
		}
929
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
930
				$input_errors[] = "Queue limit must be an integer";
931
		if ($data['qlimit'] < 0)
932
				$input_errors[] = "Queue limit must be positive";
933
		if (!preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
934
			 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
935
		
936
	}
937

    
938
	function ReadConfig(&$q) {
939
		if (isset($q['name']))
940
				$this->SetQname($q['name']);
941
		if (isset($q['interface']))
942
				$this->SetInterface($q['interface']);
943
		if ($q['bandwidth'] <> "") {
944
			$this->SetBandwidth($q['bandwidth']);
945
			if ($q['bandwidthtype'] <> "")
946
				$this->SetBwscale($q['bandwidthtype']);
947
		}
948
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
949
					$this->SetQlimit($q['qlimit']);
950
				if (isset($q['priority']))
951
						$this->SetQPriority($q['priority']);
952
				if (isset($q['description']) && $q['description'] != "")
953
						$this->SetDescription($q['description']);
954
		$this->SetRed($q['red']);
955
		$this->SetRio($q['rio']);
956
		$this->SetEcn($q['ecn']);
957
		$this->SetDefault($q['default']);
958
		$this->SetEnabled($q['enabled']);
959

    
960
		}
961

    
962
	function build_tree() {
963
			$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
964
			$tree .= "\" ";
965
			if ($this->GetDefault())
966
				$tree .= " class=\"navlnk\"";
967
			$tree .= " >" . $this->GetQname() . "</a>";
968
			/* 
969
			 * Not needed here!
970
			 * if (is_array($queues) {
971
			 *	  $tree .= "<ul>";
972
			 *	  foreach ($q as $queues) 
973
			 *		  $tree .= $queues['$q->GetName()']->build_tree();
974
			 *	  endforeach	
975
			 *	  $tree .= "</ul>";
976
			 * }
977
			 */
978

    
979
			$tree .= "</li>"; 
980

    
981
			return $tree;
982
		}
983
		
984
		/* Should return something like:
985
		 * queue $qname on $qinterface bandwidth ....
986
		 */
987
		function build_rules() {
988
				$pfq_rule = " queue ". $this->qname;
989
				if ($this->GetInterface())
990
						$pfq_rule .= " on ".get_real_interface($this->GetInterface());
991
				if ($this->GetQpriority())
992
						$pfq_rule .= " priority ".$this->GetQpriority();
993
				if ($this->GetQlimit())
994
						$pfq_rule .= " qlimit " . $this->GetQlimit();
995
				if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
996
						$pfq_rule .= " priq ( ";
997
					if ($this->GetRed()) {
998
						$comma = 1;
999
						$pfq_rule .= " red ";
1000
					}
1001
					if ($this->GetRio()) {
1002
						if ($comma) 
1003
								$pfq_rule .= " ,";
1004
						$comma = 1;
1005
						$pfq_rule .= " rio ";
1006
					}
1007
					if ($this->GetEcn()) {
1008
						if ($comma) 
1009
								$pfq_rule .= " ,";
1010
						$comma = 1;
1011
						$pfq_rule .= " ecn ";
1012
					}	
1013
					if ($this->GetDefault()) {
1014
						if ($comma)
1015
							$pfq_rule .= " ,";
1016
						$pfq_rule .= " default ";
1017
					}
1018
					$pfq_rule .= " ) ";
1019
				}
1020
	
1021
				$pfq_rule .= " \n";
1022
		
1023
				return $pfq_rule;
1024
		}
1025

    
1026
		/*
1027
		 * To return the html form to show to user
1028
		 * for getting the parameters.
1029
		 * Should do even for first time when the
1030
		 * object is created and later when we may
1031
		 * need to update it.
1032
		 */
1033
		function build_form() {
1034
				$form .= "<tr>";
1035
		$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">";
1036
		$form .= "Queue Name</td><td width=\"78%\" class=\"vtable\">";
1037
		$form .= "<input name=\"name\" type=\"text\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1038
		$form .= htmlspecialchars($this->GetQname());
1039
		$form .= "\">";
1040
				$form .= "<br> <span class=\"vexpl\">Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.";
1041
				$form .= "</span></td>";
1042
		$form .= "</tr><tr>";
1043
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Priority</td>";
1044
				$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
1045
				$form .= htmlspecialchars($this->GetQpriority());
1046
				$form .= "\">";
1047
				$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>";
1048
				$form .= "</tr>";
1049
				$form .= "</tr>";
1050
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Queue limit</td>";
1051
				$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"5\" value=\"";
1052
				$form .= htmlspecialchars($this->GetQlimit());
1053
				$form .= "\">";
1054
		$form .= "<br> <span class=\"vexpl\">Queue limit in packet per second."; 
1055
				$form .= "</span></td>";
1056
				$form .= "<tr>";
1057
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncell\">Scheduler options</td>";
1058
				$form .= "<td width=\"78%\" class=\"vtable\">";
1059
		if ($this->GetDefault()) { 
1060
				$form .= "<input type=\"checkbox\" id=\"default\" CHECKED name=\"default\"";
1061
		$form .= "> Default queue<br>";
1062
		} else {
1063
			$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\"";
1064
					$form .= "> Default queue<br>";
1065
		}
1066
				$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\"";
1067
				if($this->GetRed()) 
1068
			$form .=  " CHECKED";
1069
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">Random Early Detection</a><br>";
1070
				$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\"";
1071
				if($this->GetRio()) 
1072
			$form .=  " CHECKED";
1073
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">Random Early Detection In and Out</a><br>";
1074
				$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\"";
1075
				if($this->GetEcn()) 
1076
			$form .=  " CHECKED";
1077
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">Explicit Congestion Notification</a><br>";
1078
				$form .= "<span class=\"vexpl\"><br>Select options for this queue";
1079
				$form .= "</tr><tr>";
1080
		$form .= "<td width=\"22%\" class=\"vncellreq\">Description</td>";
1081
		$form .= "<td width=\"78%\" class=\"vtable\">";
1082
		$form .= "<input type=\"text\" name=\"description\" size=\"50%\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\"  >";
1083
		$form .= "</td></tr>";
1084
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1085
				$form .= " value=\"".$this->GetInterface()."\">";
1086

    
1087
		return $form;
1088
		}
1089

    
1090
	function build_shortform() {
1091
		/* XXX: Hacks in site. Mostly layer violations!  */
1092
		global $g, $altq_list_queues;
1093

    
1094
		$altq =& $altq_list_queues[$this->GetInterface()];
1095
		if ($altq)
1096
			$scheduler = ": " . $altq->GetScheduler();
1097
		 $form = "<tr><td width=\"20%\" class=\"vtable\">";
1098
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=" . $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
1099
		$form .= "</td></tr>";
1100
		/* 
1101
		 * XXX: Hack in sight maybe fix with a class that wraps all
1102
		 * of this layer violations
1103
		 */
1104
		$form .= "<tr>";
1105
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1106
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
1107
		$form .= "</td><td width=\"50%\"></td></tr>";
1108
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1109
		if ($this->GetQpriority())
1110
			$form .= "Priority: on </td></tr>";
1111
		if ($this->GetDefault())
1112
			$form .= "<tr><td class=\"vncellreq\">Default: on </td></tr>";
1113
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1114
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1115
			$form .= $this->GetInterface() . "&queue=";
1116
			$form .= $this->GetQname() . "&action=delete\">";
1117
			$form .= "<img src=\"";
1118
			$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1119
			$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Delete queue from interface\">";
1120
			$form .= "<span>Delete queue from interface</span></a></td></tr>";
1121
		
1122
		return $form;
1123

    
1124
	}
1125

    
1126
		function update_altq_queue_data(&$q) { 
1127
		$this->ReadConfig($q);
1128
	}
1129

    
1130
		function wconfig() {
1131
			$cflink =& get_reference_to_me_in_config($this->GetLink());
1132
		if (!is_array($cflink))
1133
			$cflink = array();
1134
		$cflink['name'] = $this->GetQname();
1135
				$cflink['interface'] = $this->GetInterface();
1136
				$cflink['qlimit'] = $this->GetQlimit();
1137
				$cflink['priority'] = $this->GetQpriority();
1138
		$cflink['description'] = $this->GetDescription();
1139
		$cflink['enabled'] = $this->GetEnabled();
1140
		$cflink['default'] = $this->GetDefault();
1141
		$cflink['red'] = $this->GetRed();
1142
		$cflink['rio'] = $this->GetRio();
1143
		$cflink['ecn'] = $this->GetEcn();
1144
	}
1145
}
1146

    
1147
class hfsc_queue extends priq_queue {
1148
		/* realtime */
1149
	var $realtime;
1150
		var $r_m1;
1151
		var $r_d;
1152
		var $r_m2;
1153
		/* linkshare */
1154
	var $linkshare;
1155
		var $l_m1;
1156
		var $l_d;
1157
		var $l_m2;
1158
		/* upperlimit */
1159
	var $upperlimit;
1160
		var $u_m1;
1161
		var $u_d;
1162
		var $u_m2;
1163

    
1164
		/*
1165
		 * HFSC can have nested queues.
1166
		 */
1167

    
1168
	function CanHaveChilds() {
1169
				return true;
1170
		}
1171
	function GetRealtime() {
1172
           return $this->realtime;
1173
     }
1174
     function GetR_m1() {
1175
           return $this->r_m1;
1176
     }
1177
     function GetR_d() {
1178
           return $this->r_d;
1179
     }
1180
     function GetR_m2() {
1181
           return $this->r_m2;
1182
     }
1183
     function SetRealtime() {
1184
           $this->realtime = "on";
1185
     }
1186
     function DisableRealtime() {
1187
           $this->realtime = "";
1188
     }
1189
     function SetR_m1($value) {
1190
           $this->r_m1 = $value;
1191
     }
1192
     function SetR_d($value) {
1193
           $this->r_d = $value;
1194
     }
1195
     function SetR_m2($value) {
1196
           $this->r_m2 = $value;
1197
     }
1198
     function GetLinkshare() {
1199
           return $this->linkshare;
1200
     }
1201
     function DisableLinkshare() {
1202
           $this->linkshare = "";
1203
     }
1204
     function GetL_m1() {
1205
           return $this->l_m1;
1206
     }
1207
     function GetL_d() {
1208
           return $this->l_d;
1209
     }
1210
     function GetL_m2() {
1211
           return $this->l_m2;
1212
     }
1213
     function SetLinkshare() {
1214
           $this->linkshare = "on";
1215
     }
1216
     function SetL_m1($value) {
1217
           $this->l_m1 = $value;
1218
     }
1219
     function SetL_d($value) {
1220
           $this->l_d = $value;
1221
     }
1222
     function SetL_m2($value) {
1223
           $this->l_m2 = $value;
1224
     }
1225
     function GetUpperlimit() {
1226
           return $this->upperlimit;
1227
     }
1228
     function GetU_m1() {
1229
           return $this->u_m1;
1230
     }
1231
     function GetU_d() {
1232
           return $this->u_d;
1233
     }
1234
     function GetU_m2() {
1235
           return $this->u_m2;
1236
     }
1237
     function SetUpperlimit() {
1238
           $this->upperlimit = "on";
1239
     }
1240
     function DisableUpperlimit() {
1241
           $this->upperlimit = "";
1242
     }
1243
     function SetU_m1($value) {
1244
           $this->u_m1 = $value;
1245
     }
1246
     function SetU_d($value) {
1247
           $this->u_d = $value;
1248
     }
1249
     function SetU_m2($value) {
1250
           $this->u_m2 = $value;
1251
     }
1252

    
1253

    
1254

    
1255
		function &add_queue($interface, &$qname, &$path, &$input_errors) {
1256

    
1257
			if (!is_array($this->subqueues))
1258
							$this->subqueues = array();
1259
			$q =& new hfsc_queue();
1260
			$q->SetInterface($this->GetInterface());
1261
			$q->SetParent(&$this);
1262
			$q->ReadConfig($qname);
1263
			$q->validate_input($qname, $input_errors);
1264
			if (count($input_errors)) {
1265
				return $q;
1266
			}
1267
			
1268
			$q->SetEnabled("on");
1269
			$q->SetLink($path);
1270
			switch ($q->GetBwscale()) {
1271
                        case "%":
1272
                                $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1273
                                break;
1274
                        default:
1275
                                $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1276
                                break;
1277
                	}
1278
                        $q->SetAvailableBandwidth($myBw);
1279
                        $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1280

    
1281
			$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1282
			ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1283
			if (is_array($qname['queue'])) {
1284
				foreach ($qname['queue'] as $key1 => $que) {
1285
					array_push($path, $key1);
1286
								$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1287
					array_pop($path);
1288
				}
1289
					}
1290
	
1291
			return $q;
1292
		}
1293

    
1294
 	        function copy_queue($interface, &$cflink) {
1295

    
1296
                        $cflink['name'] = $this->GetQname();
1297
                        $cflink['interface'] = $interface;
1298
                        $cflink['qlimit'] = $this->GetQlimit();
1299
                        $cflink['priority'] = $this->GetQpriority();
1300
                        $cflink['description'] = $this->GetDescription();
1301
                        $cflink['bandwidth'] = $this->GetBandwidth();
1302
                        $cflink['bandwidthtype'] = $this->GetBwscale();
1303
                        $cflink['enabled'] = $this->GetEnabled();
1304
                        $cflink['default'] = $this->GetDefault();
1305
                        $cflink['red'] = $this->GetRed();
1306
                        $cflink['rio'] = $this->GetRio();
1307
                        $cflink['ecn'] = $this->GetEcn();
1308
                        if ($this->GetLinkshare() <> "") {
1309
                                if ($this->GetL_m1() <> "") {
1310
                                        $cflink['linkshare1'] = $this->GetL_m1();
1311
                                        $cflink['linkshare2'] = $this->GetL_d();
1312
                                        $cflink['linkshare'] = "on";
1313
                                }
1314
                                if ($this->GetL_m2() <> "") {
1315
                                        $cflink['linkshare3'] = $this->GetL_m2();
1316
                                        $cflink['linkshare'] = "on";
1317
                                }
1318
                        } else $cflink['linkshare'] = "";
1319
                        if ($this->GetRealtime() <> "") {
1320
                                if ($this->GetR_m1() <> "") {
1321
                                        $cflink['realtime1'] = $this->GetR_m1();
1322
                                        $cflink['realtime2'] = $this->GetR_d();
1323
                                        $cflink['realtime'] = "on";
1324
                                }
1325
                                if ($this->GetR_m2() <> "") {
1326
                                        $cflink['realtime3'] = $this->GetR_m2();
1327
                                        $cflink['realtime'] = "on";
1328
                                }
1329
                        } else $cflink['realtime'] = "";
1330
                        if ($this->GetUpperlimit() <> "") {
1331
                                if ($this->GetU_m1() <> "") {
1332
                                        $cflink['upperlimit1'] = $this->GetU_m1();
1333
                                        $cflink['upperlimit2'] = $this->GetU_d();
1334
                                        $cflink['upperlimit'] = "on";
1335
                                }
1336
                                if ($this->GetU_m2() <> "") {
1337
                                        $cflink['upperlimit3'] = $this->GetU_m2();
1338
                                        $cflink['upperlimit'] = "on";
1339
                                }
1340
                        } else $cflink['upperlimit'] = "";
1341

    
1342
	                if (is_array($this->subqueues)) {
1343
        	                $cflinkp['queue'] = array();
1344
                	        foreach ($this->subqueues as $q) {
1345
                	                 $cflink['queue'][$q->GetQname()] = array();
1346
        	                        $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1347
				}
1348
                	}
1349

    
1350
         	}
1351

    
1352
		function delete_queue() { 
1353
			unref_on_altq_queue_list($this->GetQname());
1354
			if ($this->GetDefault()) 
1355
				altq_set_default_queue($this->GetInterface(), "false");
1356
			cleanup_queue_from_rules($this->GetQname());
1357
			$parent =& $this->GetParent();
1358
			foreach ($this->subqueues as $q)  {
1359
			$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1360
				$q->delete_queue();
1361
			}
1362
			unset_object_by_reference($this->GetLink());
1363
			}
1364
	
1365
			/*
1366
			 * Should search even its childs
1367
			 */
1368
			function &find_queue($interface, $qname) {
1369
					if ($qname == $this->GetQname()) 
1370
							return $this;
1371
		
1372
					foreach ($this->subqueues as $q) {
1373
							$result =& $q->find_queue("", $qname);
1374
				if ($result)
1375
									return $result;
1376
					}
1377
			}
1378

    
1379
	function &find_parentqueue($interface, $qname) {
1380
		if ($this->subqueues[$qname]) 
1381
			return $this;
1382
				foreach ($this->subqueues as $q) {
1383
					$result = $q->find_parentqueue("", $qname);
1384
			if ($result)
1385
				return $result;
1386
		}
1387
		}
1388
	
1389
	function validate_input($data, &$input_errors) {
1390
		parent::validate_input($data, $input_errors);
1391
		
1392
		$reqdfields[] = "bandwidth";
1393
		$reqdfieldsn[] = "Bandwidth";
1394
		$reqdfields[] = "bandwidthtype";
1395
		$reqdfieldsn[] = "Bandwidthtype";
1396

    
1397
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1398
		
1399
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1400
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1401
                        $input_errors[] = "Bandwidth must be an integer.";
1402

    
1403
                if ($data['bandwidth'] < 0)
1404
                        $input_errors[] = "Bandwidth cannot be negative.";
1405

    
1406
                if ($data['bandwidthtype'] == "%") {
1407
                 if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1408
                       $input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1409
                 }
1410
/*
1411
                $parent =& $this->GetParent();
1412
                switch ($data['bandwidthtype']) {
1413
                       case "%":
1414
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1415
                       default:
1416
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1417
                             break;
1418
                }
1419
                if ($parent->GetAvailableBandwidth() < $myBw)
1420
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
1421
*/
1422
                if ($data['priority'] > 7)
1423
                        $input_errors[] = "Priority must be an integer between 1 and 7.";
1424
		}
1425

    
1426
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1427
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1428
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1429
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1430
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1431
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1432
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1433
			$input_errors[] = ("upperlimit d value needs to be numeric");
1434
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1435
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1436
/*
1437

    
1438
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1439
		$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1440
		$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1441
		if (floatval($bw_1) < floatval($bw_2)) 
1442
			$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1443

    
1444
		
1445
		if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1446
			$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1447
		}
1448
*/
1449
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1450
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1451
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1452
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1453
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1454
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1455
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1456
			$input_errors[] = ("linkshare d value needs to be numeric");
1457
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1458
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1459
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1460
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1461
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1462
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1463

    
1464
/*
1465
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1466
		$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1467
                $bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1468
                if (floatval($bw_1) < floatval($bw_2))
1469
                        $input_errors[] = ("linkshare m1 cannot be smaller than m2");
1470

    
1471

    
1472
                if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1473
                        $input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1474
		}
1475
*/
1476

    
1477
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1478
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1479
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1480
			$input_errors[] = ("realtime d value needs to be numeric");
1481
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1482
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1483

    
1484
/*
1485
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1486
		$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1487
                $bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1488
                if (floatval($bw_1) < floatval($bw_2))
1489
                        $input_errors[] = ("realtime m1 cannot be smaller than m2");
1490

    
1491

    
1492
                if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1493
                        $input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1494
		}
1495
*/
1496

    
1497
	}
1498

    
1499
		function ReadConfig(&$cflink) {
1500
		if (isset($cflink['linkshare']) && $cflink['linkshare'] <> "") {
1501
			if (isset($cflink['linkshare1']) && $cflink['linkshare1'] <> "") {
1502
				$this->SetL_m1($cflink['linkshare1']);
1503
                                $this->SetL_d($cflink['linkshare2']);
1504
				$this->SetLinkshare();
1505
			}
1506
			if (isset($cflink['linkshare3']) && $cflink['linkshare3'] <> "") {
1507
                                $this->SetL_m2($cflink['linkshare3']);
1508
				$this->SetLinkshare();
1509
			}
1510
		} else $this->DisableLinkshare();
1511
		if (isset($cflink['realtime']) && $cflink['realtime'] <> "") {
1512
                        if (isset($cflink['realtime1']) && $cflink['realtime1'] <> "") {
1513
                                $this->SetR_m1($cflink['realtime1']);
1514
                                $this->SetR_d($cflink['realtime2']);
1515
				$this->SetRealtime();
1516
			}
1517
                        if (isset($cflink['realtime3']) && $cflink['realtime3'] <> "") {
1518
                                $this->SetR_m2($cflink['realtime3']);
1519
				$this->SetRealtime();
1520
			}
1521
		} else $this->DisableRealtime(); 
1522
		if (isset($cflink['upperlimit']) && $cflink['upperlimit'] <> "") {
1523
                        if (isset($cflink['upperlimit1']) && $cflink['upperlimit1'] <> "") {
1524
                                $this->SetU_m1($cflink['upperlimit1']);
1525
                                $this->SetU_d($cflink['upperlimit2']);
1526
				$this->SetUpperlimit();
1527
			}
1528
                        if (isset($cflink['upperlimit3']) && $cflink['upperlimit3'] <> "") {
1529
                                $this->SetU_m2($cflink['upperlimit3']);
1530
				$this->SetUpperlimit();
1531
			}
1532
		} else $this->DisableUpperlimit();
1533
		parent::ReadConfig($cflink);
1534

    
1535
		}
1536

    
1537
	function build_tree() {
1538
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1539
		$tree .= "\" ";
1540
		if ($this->GetDefault())
1541
								$tree .= " class=\"navlnk\"";
1542
		$tree .= " >" . $this->GetQname() . "</a>";
1543
		if (is_array($this->subqueues)) {
1544
			$tree .= "<ul>";
1545
			foreach ($this->subqueues as $q)  {
1546
				$tree .= $q->build_tree();
1547
			}	
1548
			$tree .= "</ul>";
1549
		}
1550
		$tree .= "</li>";
1551
		return $tree;
1552
	}
1553

    
1554
		/* Even this should take childs in consideration */
1555
		function build_rules() {
1556

    
1557
				$pfq_rule = " queue ". $this->qname;
1558
				if ($this->GetInterface())
1559
						$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1560
		if ($this->GetBandwidth() && $this->GetBwscale())
1561
						$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1562
					
1563
				if ($this->GetQpriority())
1564
						$pfq_rule .= " priority " . $this->GetQpriority();
1565
				if ($this->GetQlimit())
1566
						$pfq_rule .= " qlimit " . $this->GetQlimit();
1567
		  if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1568
						$pfq_rule .= " hfsc ( ";
1569
						if ($this->GetRed()) {
1570
								$comma = 1;
1571
								$pfq_rule .= " red ";
1572
						}
1573
						if ($this->GetRio()) {
1574
								if ($comma) 
1575
										$pfq_rule .= " ,";
1576
								$comma = 1;
1577
								$pfq_rule .= " rio ";
1578
						}
1579
						if ($this->GetEcn()) {
1580
								if ($comma) 
1581
										$pfq_rule .= " ,";
1582
								$comma = 1;
1583
								$pfq_rule .= " ecn ";
1584
						}
1585
						if ($this->GetDefault()) {
1586
								if ($comma)
1587
										$pfq_rule .= " ,";
1588
								$comma = 1;
1589
								$pfq_rule .= " default ";
1590
						}
1591

    
1592
						if ($this->GetRealtime() <> "")  {
1593
				if ($comma) 
1594
									$pfq_rule .= " , ";
1595
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1596
			$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1597
				else  if ($this->GetR_m2() <> "")
1598
					$pfq_rule .= " realtime " . $this->GetR_m2();
1599
				$comma = 1;
1600
			}
1601
						if ($this->GetLinkshare() <> "") {
1602
								if ($comma)
1603
					$pfq_rule .= " ,";
1604
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1605
			$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1606
				else if ($this->GetL_m2() <> "")
1607
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1608
				$comma = 1;
1609
			}
1610
						if ($this->GetUpperlimit() <> "") {
1611
				if ($comma)
1612
					$pfq_rule .= " ,";
1613
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1614
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1615
				else if ($this->GetU_m2() <> "")
1616
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1617
			}
1618
					$pfq_rule .= " ) ";
1619
					}
1620
					if (count($this->subqueues)) {
1621
						$i = count($this->subqueues);
1622
						$pfq_rule .= " { ";
1623
						foreach ($this->subqueues as $qkey => $qnone) {
1624
								if ($i > 1) {
1625
										$i--;
1626
										$pfq_rule .= " {$qkey}, ";
1627
								} else
1628
										$pfq_rule .= " {$qkey} ";
1629
						}
1630
								$pfq_rule .= " } \n";
1631
								foreach ($this->subqueues as $q)
1632
									$pfq_rule .= $q->build_rules();
1633
					}
1634

    
1635
				 $pfq_rule .= " \n";
1636
			
1637
				return $pfq_rule;
1638
		}
1639

    
1640
	function build_javascript() {
1641
		$javascript = parent::build_javascript();
1642
		$javascript .= "<script type=\"text/javascript\">";
1643
		$javascript .= "function enable_realtime(enable_over) { \n";
1644
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1645
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1646
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1647
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1648
		$javascript .= " } else { \n";
1649
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1650
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1651
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1652
		$javascript .= " } \n";
1653
		$javascript .= " } \n";
1654
		$javascript .= "function enable_linkshare(enable_over) { \n";
1655
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1656
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1657
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1658
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1659
		$javascript .= " } else { \n";
1660
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1661
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1662
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1663
		$javascript .= " } \n";
1664
		$javascript .= " } \n";
1665
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1666
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1667
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1668
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1669
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1670
		$javascript .= " } else { \n";
1671
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1672
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1673
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1674
		$javascript .= " } \n";
1675
			
1676
		$javascript .= "} \n";
1677
		$javascript .= "</script>";
1678

    
1679
		return $javascript;
1680
	}
1681

    
1682
		function build_form() {
1683
				$form = "<tr>";
1684
				$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
1685
				$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1686
				$form .= htmlspecialchars($this->GetBandwidth());
1687
				$form .= "\">";
1688
				$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1689
				$form .= "<option value=\"Gb\"";
1690
				if ($this->GetBwscale() == "Gb")
1691
						$form .= " selected=\"yes\"";
1692
				$form .= ">Gbit/s</option>";
1693
				$form .= "<option value=\"Mb\"";
1694
				if ($this->GetBwscale() == "Mb")
1695
						$form .= " selected=\"yes\"";
1696
				$form .= ">Mbit/s</option>";
1697
				$form .= "<option value=\"Kb\"";
1698
				if ($this->GetBwscale() == "Kb")
1699
						$form .= " selected=\"yes\"";
1700
				$form .= ">Kbit/s</option>";
1701
				$form .= "<option value=\"\"";
1702
				if ($this->GetBwscale() == "b")
1703
						$form .= " selected=\"yes\"";
1704
				$form .= ">Bit/s</option>";
1705
				$form .= "<option value=\"%\"";
1706
				if ($this->GetBwscale() == "%")
1707
						$form .= " selected=\"yes\"";
1708
				$form .= ">%</option>";
1709
				$form .= "</select> <br>";
1710
				$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
1711
				$form .= "</span></td>";
1712
				$form .= parent::build_form();
1713
				$form .= "<tr>";
1714
				$form .= "<td width=\"22%\" valign=\"top\" class=\"vncellreq\">Service Curve (sc)</td>";
1715
				$form .= "<td width=\"78%\" class=\"vtable\">";
1716
				$form .= "<table>";
1717
				$form .= "<tr><td>&nbsp;</td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>";
1718
				$form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\"";
1719
				if($this->GetUpperlimit()<> "") 
1720
					$form .=  " CHECKED ";
1721
				$form .= "onChange=\"enable_upperlimit()\"> Upperlimit:</td><td><input size=\"6\" value=\"";
1722
				$form .= htmlspecialchars($this->GetU_m1());
1723
				$form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" ";
1724
				if ($this->GetUpperlimit() == "") $form .= " disabled";
1725
				$form .= "></td><td><input size=\"6\" value=\"";
1726
				$form .= htmlspecialchars($this->GetU_d());
1727
				$form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" ";
1728
		if ($this->GetUpperlimit() == "") $form .= " disabled";
1729
		$form .= "></td><td><input size=\"6\" value=\"";
1730
				$form .= htmlspecialchars($this->GetU_m2());
1731
				$form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" ";
1732
		if ($this->GetUpperlimit() == "") $form .= " disabled";
1733
		$form .= "></td><td>The maximum allowed bandwidth for the queue.</td></tr>";
1734
				$form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\"";
1735
				if($this->GetRealtime() <> "") 
1736
			$form .=  " CHECKED ";
1737
				$form .= "onChange=\"enable_realtime()\"> Real time:</td><td><input size=\"6\" value=\"";
1738
				$form .= htmlspecialchars($this->GetR_m1());
1739
				$form .= "\" id=\"realtime1\" name=\"realtime1\" ";
1740
		if ($this->GetRealtime() == "") $form .= " disabled";
1741
		$form .= "></td><td><input size=\"6\" value=\"";
1742
				$form .= htmlspecialchars($this->GetR_d());
1743
				$form .= "\" id=\"realtime2\" name=\"realtime2\" ";
1744
		if ($this->GetRealtime() == "") $form .= " disabled";
1745
		$form .= "></td><td><input size=\"6\" value=\"";
1746
				$form .= htmlspecialchars($this->GetR_m2());
1747
				$form .= "\" id=\"realtime3\" name=\"realtime3\" ";
1748
		if ($this->GetRealtime() == "") $form .= " disabled";
1749
		$form .= "></td><td>The minimum required bandwidth for the queue.</td></tr>";
1750
				$form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" id=\"linkshare\" name=\"linkshare\"";
1751
				if($this->GetLinkshare() <> "") 
1752
			$form .=  " CHECKED ";
1753
				$form .= "onChange=\"enable_linkshare()\"> Link share:</td><td><input size=\"6\" value=\"";
1754
				$form .= htmlspecialchars($this->GetL_m1());
1755
				$form .= "\" id=\"linkshare1\" name=\"linkshare1\" ";
1756
		if ($this->GetLinkshare() == "") $form .= " disabled";
1757
		$form .= "></td><td><input size=\"6\" value=\"";
1758
				$form .= htmlspecialchars($this->GetL_d());
1759
				$form .= "\" id=\"linkshare2\" name=\"linkshare2\" ";
1760
		if ($this->GetLinkshare() == "") $form .= " disabled";
1761
		$form .= "></td><td><input size=\"6\" value=\"";
1762
				$form .= htmlspecialchars($this->GetL_m2());
1763
				$form .= "\" id=\"linkshare3\" name=\"linkshare3\" ";
1764
		if ($this->GetLinkshare() == "") $form .= " disabled";
1765
		$form .= "></td><td>The bandwidth share of a backlogged queue - this overrides priority.</td></tr>";
1766
				$form .= "</table><br>";
1767
				$form .= "The format for service curve specifications is (m1, d, m2).  m2 controls";
1768
				$form .= "the bandwidth assigned to the queue.  m1 and d are optional and can be";
1769
				$form .= "used to control the initial bandwidth assignment.  For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value";
1770
				$form .= "given in m2.";
1771
				$form .= "</span></td>";
1772
				$form .= "</tr>";
1773

    
1774
				return $form;
1775
		}
1776

    
1777
	function update_altq_queue_data(&$data) { 
1778
		$this->ReadConfig($data);
1779
	}
1780

    
1781
	function wconfig() {
1782
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1783
		if (!is_array($cflink))
1784
			$cflink = array();
1785
			$cflink['name'] = $this->GetQname();
1786
			$cflink['interface'] = $this->GetInterface();
1787
			$cflink['qlimit'] = $this->GetQlimit();
1788
			$cflink['priority'] = $this->GetQpriority();
1789
			$cflink['description'] = $this->GetDescription();
1790
			$cflink['bandwidth'] = $this->GetBandwidth();
1791
			$cflink['bandwidthtype'] = $this->GetBwscale();
1792
			$cflink['enabled'] = $this->GetEnabled();
1793
			$cflink['default'] = $this->GetDefault();
1794
			$cflink['red'] = $this->GetRed();
1795
			$cflink['rio'] = $this->GetRio();
1796
			$cflink['ecn'] = $this->GetEcn();
1797
			if ($this->GetLinkshare() <> "") {
1798
				if ($this->GetL_m1() <> "") {
1799
					$cflink['linkshare1'] = $this->GetL_m1();
1800
					$cflink['linkshare2'] = $this->GetL_d();
1801
					$cflink['linkshare'] = "on";
1802
				}
1803
				if ($this->GetL_m2() <> "") {
1804
					$cflink['linkshare3'] = $this->GetL_m2();
1805
					$cflink['linkshare'] = "on";
1806
				}
1807
			} else $cflink['linkshare'] = "";
1808
			if ($this->GetRealtime() <> "") {
1809
				if ($this->GetR_m1() <> "") {
1810
					$cflink['realtime1'] = $this->GetR_m1();
1811
					$cflink['realtime2'] = $this->GetR_d();
1812
					$cflink['realtime'] = "on";
1813
				}
1814
				if ($this->GetR_m2() <> "") {
1815
					$cflink['realtime3'] = $this->GetR_m2();
1816
					$cflink['realtime'] = "on";
1817
				}
1818
			} else $cflink['realtime'] = "";
1819
			if ($this->GetUpperlimit() <> "") {
1820
				if ($this->GetU_m1() <> "") {
1821
					$cflink['upperlimit1'] = $this->GetU_m1();
1822
					$cflink['upperlimit2'] = $this->GetU_d();
1823
					$cflink['upperlimit'] = "on";
1824
				}
1825
				if ($this->GetU_m2() <> "") {
1826
					$cflink['upperlimit3'] = $this->GetU_m2();
1827
					$cflink['upperlimit'] = "on";
1828
				}
1829
			} else $cflink['upperlimit'] = "";
1830
		}
1831
	}
1832

    
1833
class cbq_queue extends priq_queue {
1834
		var $qborrow;
1835

    
1836
	function GetBorrow() {
1837
		return $this->qborrow;
1838
	}
1839
	function SetBorrow($borrow) {
1840
		$this->qborrow = $borrow;
1841
	}
1842
	function CanHaveChilds() {
1843
			return true;
1844
	}
1845

    
1846
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1847

    
1848
		if (!is_array($this->subqueues))
1849
						$this->subqueues = array();
1850
		$q =& new cbq_queue();
1851
		$q->SetInterface($this->GetInterface());
1852
		$q->SetParent(&$this);
1853
		$q->ReadConfig($qname);
1854
                $q->validate_input($qname, $input_errors);
1855
                if (count($input_errors)) {
1856
                        return $q;
1857
                }
1858
                switch ($q->GetBwscale()) {
1859
                        case "%":
1860
                                $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1861
                                break;
1862
                        default:
1863
                                $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1864
                                break;
1865
                }
1866
                $q->SetAvailableBandwidth($myBw);
1867
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1868

    
1869
		$q->SetEnabled("on");
1870
		$q->SetLink($path);
1871
		$this->subqueues[$q->GetQName()] = &$q;
1872
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1873
		if (is_array($qname['queue'])) {
1874
				foreach ($qname['queue'] as $key1 => $que) {
1875
						array_push($path, $key1);
1876
						$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1877
						array_pop($path);
1878
				}
1879
		}
1880

    
1881
		return $q;
1882
		}
1883

    
1884
		function copy_queue($interface, &$cflink) {
1885

    
1886
                                $cflink['interface'] = $interface;
1887
                                $cflink['qlimit'] = $this->GetQlimit();
1888
                                $cflink['priority'] = $this->GetQpriority();
1889
                                $cflink['name'] = $this->GetQname();
1890
                                $cflink['description'] = $this->GetDescription();
1891
                                $cflink['bandwidth'] = $this->GetBandwidth();
1892
                                $cflink['bandwidthtype'] = $this->GetBwscale();
1893
                                $cflink['enabled'] = $this->GetEnabled();
1894
                                $cflink['default'] = $this->GetDefault();
1895
                                $cflink['red'] = $this->GetRed();
1896
                                $cflink['rio'] = $this->GetRio();
1897
                                $cflink['ecn'] = $this->GetEcn();
1898
                                $cflink['borrow'] = $this->GetBorrow();
1899
                		if (is_array($this->queues)) {
1900
 		                       $cflinkp['queue'] = array();
1901
                        		foreach ($this->subqueues as $q) {
1902
 		                                $cflink['queue'][$q->GetQname()] = array();
1903
                		                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1904
					}
1905
                		}
1906

    
1907
		}
1908
	
1909
		/*
1910
		 * Should search even its childs
1911
		 */
1912
		function &find_queue($interface, $qname) {
1913
				if ($qname == $this->GetQname())
1914
						return $this;
1915
				foreach ($this->subqueues as $q) {
1916
						$result =& $q->find_queue("", $qname);
1917
			if ($result)
1918
								return $result;
1919
				}
1920
		}
1921

    
1922
	function &find_parentqueue($interface, $qname) {
1923
				if ($this->subqueues[$qname])
1924
						return $this;
1925
				foreach ($this->subqueues as $q) {
1926
					$result = $q->find_parentqueue("", $qname);
1927
			if ($result)
1928
				return $result;
1929
		}
1930
		}
1931

    
1932
		function delete_queue() {
1933
			unref_on_altq_queue_list($this->GetQname());
1934
			if ($this->GetDefault())
1935
				altq_set_default_queue($this->GetInterface(), "false");
1936
			cleanup_queue_from_rules($this->GetQname());
1937
			foreach ($this->subqueues as $q) {
1938
			$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1939
				$q->delete_queue();
1940
			}
1941
			unset_object_by_reference($this->GetLink());
1942
		}
1943
	
1944
	function validate_input($data, &$input_errors) {
1945
		parent::validate_input($data, $input_errors);
1946
		
1947
		if ($data['priority'] > 7)
1948
				$input_errors[] = "Priority must be an integer between 1 and 7.";
1949
		$reqdfields[] = "bandwidth";
1950
		$reqdfieldsn[] = "Bandwidth";
1951
		$reqdfields[] = "bandwidthtype";
1952
		$reqdfieldsn[] = "Bandwidthtype";
1953

    
1954
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1955
		
1956
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
1957
                 $input_errors[] = "Bandwidth must be an integer.";
1958

    
1959

    
1960
           if ($data['bandwidth'] < 0)
1961
                       $input_errors[] = "Bandwidth cannot be negative.";
1962

    
1963

    
1964
           if ($data['bandwidthtype'] == "%") {
1965
                 if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1966
                       $input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1967
           }
1968

    
1969
/*
1970
           $parent =& $this->GetParent();
1971
           switch ($data['bandwidthtype']) {
1972
                       case "%":
1973
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1974
                       default:
1975
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1976
                             break;
1977
           }
1978
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
1979
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
1980
*/
1981
	}
1982
		function ReadConfig(&$q) {
1983
				parent::ReadConfig($q);
1984
		if ($q['borrow'])
1985
			$this->SetBorrow("on");
1986
		}
1987
		
1988
	function build_javascript() {
1989
		return parent::build_javascript();
1990
	}
1991

    
1992
	function build_tree() {
1993
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
1994
			$tree .= "\" ";
1995
			if ($this->GetDefault())
1996
								$tree .= " class=\"navlnk\"";
1997
			$tree .= " >" . $this->GetQname() . "</a>";
1998
			if (is_array($this->subqueues)) {
1999
				$tree .= "<ul>";
2000
				foreach ($this->subqueues as $q)  {
2001
					$tree .= $q->build_tree();
2002
				}	
2003
				$tree .= "</ul>";
2004
			}
2005
			$tree .= "</li>";
2006
			return $tree;
2007
	}
2008
		
2009
	/* Even this should take childs in consideration */
2010
	function build_rules() {
2011
		   $pfq_rule = "queue ". $this->qname;
2012
			if ($this->GetInterface())
2013
					$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2014
			if ($this->GetBandwidth() && $this->GetBwscale())
2015
					$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2016
			if ($this->GetQpriority())
2017
					$pfq_rule .= " priority " . $this->GetQpriority();
2018
			if ($this->GetQlimit())
2019
					$pfq_rule .= " qlimit " . $this->GetQlimit();
2020
			if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow()) {
2021
				$pfq_rule .= " cbq ( ";
2022
				if ($this->GetRed()) {
2023
						$comma = 1;
2024
						$pfq_rule .= " red ";
2025
				}
2026
				if ($this->GetRio()) {
2027
						if ($comma) 
2028
								$pfq_rule .= " ,";
2029
						$comma = 1;
2030
						$pfq_rule .= " rio ";
2031
				}
2032
				if ($this->GetEcn()) {
2033
						if ($comma) 
2034
								$pfq_rule .= " ,";
2035
						$comma = 1;
2036
						$pfq_rule .= " ecn ";
2037
				}
2038
				if ($this->GetDefault()) {
2039
						if ($comma)
2040
								$pfq_rule .= " ,";
2041
						$comma = 1;
2042
						$pfq_rule .= " default ";
2043
				}
2044
				if ($this->GetBorrow()) {
2045
					if ($comma)
2046
						$pfq_rule .= ", ";
2047
					$pfq_rule .= " borrow ";
2048
				}
2049
				$pfq_rule .= " ) ";
2050
			} 
2051
			if (count($this->subqueues)) {
2052
					$i = count($this->subqueues);
2053
					$pfq_rule .= " { ";
2054
					foreach ($this->subqueues as $qkey => $qnone) {
2055
							if ($i > 1) {
2056
									$i--;
2057
									$pfq_rule .= " {$qkey}, ";
2058
							} else
2059
									$pfq_rule .= " {$qkey} ";
2060
					}
2061
					$pfq_rule .= " } \n";
2062
					foreach ($this->subqueues as $q)
2063
							$pfq_rule .= $q->build_rules();
2064
			}
2065

    
2066
			$pfq_rule .= " \n";
2067
			return $pfq_rule;
2068
	}
2069

    
2070
	function build_form() {
2071
		$form = "<tr>";
2072
		$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
2073
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2074
		if ($this->GetBandwidth() > 0)
2075
				$form .= htmlspecialchars($this->GetBandwidth());
2076
		$form .= "\">";
2077
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2078
		$form .= "<option value=\"Gb\"";
2079
		if ($this->GetBwscale() == "Gb")
2080
				$form .= " selected=\"yes\"";
2081
		$form .= ">Gbit/s</option>";
2082
		$form .= "<option value=\"Mb\"";
2083
		if ($this->GetBwscale() == "Mb")
2084
				$form .= " selected=\"yes\"";
2085
		$form .= ">Mbit/s</option>";
2086
		$form .= "<option value=\"Kb\"";
2087
		if ($this->GetBwscale() == "Kb")
2088
				$form .= " selected=\"yes\"";
2089
		$form .= ">Kbit/s</option>";
2090
		$form .= "<option value=\"\"";
2091
		if ($this->GetBwscale() == "b")
2092
				$form .= " selected=\"yes\"";
2093
		$form .= ">Bit/s</option>";
2094
		$form .= "<option value=\"%\"";
2095
		if ($this->GetBwscale() == "%")
2096
				$form .= " selected=\"yes\"";
2097
		$form .= ">%</option>";
2098
		$form .= "</select> <br>";
2099
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2100
		$form .= "</span></td></tr>";
2101
		$form .= parent::build_form();
2102
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2103
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2104
			if($this->GetBorrow() == "on") 
2105
		$form .=  " CHECKED ";
2106
		$form .= "> Borrow from other queues when available<br></td></tr>";
2107

    
2108
		return $form;
2109
	}
2110

    
2111
	function update_altq_queue_data(&$data) { 
2112
		$this->ReadConfig($data);
2113
	}
2114

    
2115
	function wconfig() {
2116
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2117
				if (!is_array($cflink))
2118
						$cflink = array();
2119
				$cflink['interface'] = $this->GetInterface();
2120
				$cflink['qlimit'] = $this->GetQlimit();
2121
				$cflink['priority'] = $this->GetQpriority();
2122
				$cflink['name'] = $this->GetQname();
2123
				$cflink['description'] = $this->GetDescription();
2124
				$cflink['bandwidth'] = $this->GetBandwidth();
2125
				$cflink['bandwidthtype'] = $this->GetBwscale();
2126
				$cflink['enabled'] = $this->GetEnabled();
2127
				$cflink['default'] = $this->GetDefault();
2128
				$cflink['red'] = $this->GetRed();
2129
				$cflink['rio'] = $this->GetRio();
2130
				$cflink['ecn'] = $this->GetEcn();
2131
				$cflink['borrow'] = $this->GetBorrow();
2132
		}
2133
}
2134

    
2135
class fairq_queue extends priq_queue {
2136
		var $hogs;
2137
		var $buckets;
2138

    
2139
	function GetBuckets() {
2140
		return $this->buckets;
2141
	}
2142
	function SetBuckets($buckets) {
2143
		$this->buckets = $buckets;
2144
	}
2145
	function GetHogs() {
2146
		return $this->hogs;
2147
	}
2148
	function SetHogs($hogs) {
2149
		$this->hogs = $hogs;
2150
	}
2151
	function CanHaveChilds() {
2152
		return false;
2153
	}
2154

    
2155

    
2156
	function copy_queue($interface, &$cflink) {
2157
                $cflink['interface'] = $interface;
2158
                $cflink['qlimit'] = $this->GetQlimit();
2159
                $cflink['priority'] = $this->GetQpriority();
2160
                $cflink['name'] = $this->GetQname();
2161
                $cflink['description'] = $this->GetDescription();
2162
                $cflink['bandwidth'] = $this->GetBandwidth();
2163
                $cflink['bandwidthtype'] = $this->GetBwscale();
2164
                $cflink['enabled'] = $this->GetEnabled();
2165
                $cflink['default'] = $this->GetDefault();
2166
                $cflink['red'] = $this->GetRed();
2167
                $cflink['rio'] = $this->GetRio();
2168
                $cflink['ecn'] = $this->GetEcn();
2169
                $cflink['buckets'] = $this->GetBuckets();
2170
		$cflink['hogs'] = $this->GetHogs();
2171
	}
2172
	
2173
	/*
2174
	 * Should search even its childs
2175
	 */
2176
	function &find_queue($interface, $qname) {
2177
		if ($qname == $this->GetQname())
2178
			return $this;
2179
	}
2180

    
2181
	function find_parentqueue($interface, $qname) { return; }
2182

    
2183
	function delete_queue() {
2184
		unref_on_altq_queue_list($this->GetQname());
2185
		if ($this->GetDefault())
2186
			altq_set_default_queue($this->GetInterface(), "false");
2187
		cleanup_queue_from_rules($this->GetQname());
2188
		unset_object_by_reference($this->GetLink());
2189
	}
2190
	
2191
	function validate_input($data, &$input_errors) {
2192
		parent::validate_input($data, $input_errors);
2193
		
2194
		if ($data['priority'] > 255)
2195
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2196
		$reqdfields[] = "bandwidth";
2197
		$reqdfieldsn[] = "Bandwidth";
2198
		$reqdfields[] = "bandwidthtype";
2199
		$reqdfieldsn[] = "Bandwidthtype";
2200

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

    
2206

    
2207
	        if ($data['bandwidth'] < 0)
2208
                       $input_errors[] = "Bandwidth cannot be negative.";
2209

    
2210

    
2211
        	if ($data['bandwidthtype'] == "%") {
2212
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2213
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2214
           	}
2215

    
2216
/*
2217
           	$parent =& $this->GetParent();
2218
           	switch ($data['bandwidthtype']) {
2219
                       case "%":
2220
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2221
                       default:
2222
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2223
                             break;
2224
           	}
2225
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2226
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
2227
*/
2228
	}
2229
	
2230
	function ReadConfig(&$q) {
2231
		parent::ReadConfig($q);
2232
		if ($q['buckets'])
2233
			$this->SetBuckets($q['buckets']);
2234
		if ($q['hogs'] && is_valid_shaperbw($q['hogs']))
2235
			$this->SetHogs($q['hogs']);
2236
	}
2237
		
2238
	function build_javascript() {
2239
		return parent::build_javascript();
2240
	}
2241

    
2242
	function build_tree() {
2243
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2244
			$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2245
			$tree .= "\" ";
2246
			if ($this->GetDefault())
2247
				$tree .= " class=\"navlnk\"";
2248
			$tree .= " >" . $this->GetQname() . "</a>";
2249
			$tree .= "</li>";
2250
			return $tree;
2251
	}
2252
		
2253
	/* Even this should take childs in consideration */
2254
	function build_rules() {
2255
		$pfq_rule = "queue ". $this->qname;
2256
		if ($this->GetInterface())
2257
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2258
		if ($this->GetBandwidth() && $this->GetBwscale())
2259
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2260
		if ($this->GetQpriority())
2261
			$pfq_rule .= " priority " . $this->GetQpriority();
2262
		if ($this->GetQlimit())
2263
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2264
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2265
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2266
			$pfq_rule .= " fairq ( ";
2267
			if ($this->GetRed()) {
2268
				$comma = 1;
2269
				$pfq_rule .= " red ";
2270
			}
2271
			if ($this->GetRio()) {
2272
				if ($comma) 
2273
					$pfq_rule .= " ,";
2274
				$comma = 1;
2275
				$pfq_rule .= " rio ";
2276
			}
2277
			if ($this->GetEcn()) {
2278
				if ($comma) 
2279
					$pfq_rule .= " ,";
2280
				$comma = 1;
2281
				$pfq_rule .= " ecn ";
2282
			}
2283
			if ($this->GetDefault()) {
2284
				if ($comma)
2285
					$pfq_rule .= " ,";
2286
				$comma = 1;
2287
				$pfq_rule .= " default ";
2288
			}
2289
			if ($this->GetBuckets()) {
2290
				if ($comma)
2291
					$pfq_rule .= ", ";
2292
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2293
			}
2294
			if ($this->GetHogs()) {
2295
				if ($comma)
2296
					$pfq_rule .= ", ";
2297
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2298
			}
2299
				$pfq_rule .= " ) ";
2300
		} 
2301

    
2302
		$pfq_rule .= " \n";
2303
		return $pfq_rule;
2304
	}
2305

    
2306
	function build_form() {
2307
		$form = "<tr>";
2308
		$form .= "<td valign=\"top\" class=\"vncellreq\">Bandwidth</td>";
2309
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2310
		if ($this->GetBandwidth() > 0)
2311
				$form .= htmlspecialchars($this->GetBandwidth());
2312
		$form .= "\">";
2313
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2314
		$form .= "<option value=\"Gb\"";
2315
		if ($this->GetBwscale() == "Gb")
2316
				$form .= " selected=\"yes\"";
2317
		$form .= ">Gbit/s</option>";
2318
		$form .= "<option value=\"Mb\"";
2319
		if ($this->GetBwscale() == "Mb")
2320
				$form .= " selected=\"yes\"";
2321
		$form .= ">Mbit/s</option>";
2322
		$form .= "<option value=\"Kb\"";
2323
		if ($this->GetBwscale() == "Kb")
2324
				$form .= " selected=\"yes\"";
2325
		$form .= ">Kbit/s</option>";
2326
		$form .= "<option value=\"\"";
2327
		if ($this->GetBwscale() == "b")
2328
				$form .= " selected=\"yes\"";
2329
		$form .= ">Bit/s</option>";
2330
		$form .= "<option value=\"%\"";
2331
		if ($this->GetBwscale() == "%")
2332
				$form .= " selected=\"yes\"";
2333
		$form .= ">%</option>";
2334
		$form .= "</select> <br>";
2335
		$form .= "<span class=\"vexpl\">Choose the amount of bandwidth for this queue";
2336
		$form .= "</span></td></tr>";
2337
		$form .= parent::build_form();
2338
		$form .= "<tr><td class=\"vncellreq\">Scheduler specific options</td>";
2339
		$form .= "<td class=\"vtable\"><table><tr><td>";
2340
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2341
			if($this->GetBuckets()) 
2342
				$form .=  $this->GetBuckets();
2343
		$form .= "\"> Number of buckets available.<br></td></tr>";
2344
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2345
			if($this->GetHogs()) 
2346
				$form .=  $this->GetHogs();
2347
		$form .= "\"> Bandwidth limit for hosts to not saturate link.<br></td></tr>";
2348
		$form .= "</table></td></tr>";
2349
		return $form;
2350
	}
2351

    
2352
	function update_altq_queue_data(&$data) { 
2353
		$this->ReadConfig($data);
2354
	}
2355

    
2356
	function wconfig() {
2357
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2358
		if (!is_array($cflink))
2359
			$cflink = array();
2360
		$cflink['interface'] = $this->GetInterface();
2361
		$cflink['qlimit'] = $this->GetQlimit();
2362
		$cflink['priority'] = $this->GetQpriority();
2363
		$cflink['name'] = $this->GetQname();
2364
		$cflink['description'] = $this->GetDescription();
2365
		$cflink['bandwidth'] = $this->GetBandwidth();
2366
		$cflink['bandwidthtype'] = $this->GetBwscale();
2367
		$cflink['enabled'] = $this->GetEnabled();
2368
		$cflink['default'] = $this->GetDefault();
2369
		$cflink['red'] = $this->GetRed();
2370
		$cflink['rio'] = $this->GetRio();
2371
		$cflink['ecn'] = $this->GetEcn();
2372
		$cflink['buckets'] = $this->GetBuckets();
2373
		$cflink['hogs'] = $this->GetHogs();
2374
	}
2375
}
2376

    
2377

    
2378
/*
2379
 * XXX: TODO Link dummynet(4) in the system. 
2380
 */
2381

    
2382

    
2383
/*
2384
 * List of respective objects!
2385
 */
2386
$dummynet_pipe_list = array();
2387

    
2388
class dummynet_class {
2389
        var $qname;
2390
		var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2391
        var $qlimit;
2392
        var $description;
2393
		var $qenabled;
2394
		var $link;
2395
		var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2396
        var $plr;
2397

    
2398
        var $buckets;
2399
        /* mask parameters */
2400
        var $mask;
2401
        var $noerror;
2402

    
2403
        /* Accesor functions */
2404
        function SetLink($link) {
2405
                $this->link = $link;
2406
        }
2407
        function GetLink() {
2408
                return $this->link;
2409
        }
2410
		function Getmask() {
2411
			return $this->mask;
2412
		}
2413
		function SetMask($mask) {
2414
			$this->mask = $mask;
2415
		}
2416
		function &GetParent() {
2417
			return $this->qparent;
2418
		}
2419
		function SetParent(&$parent) {
2420
			$this->qparent = &$parent;
2421
		}
2422
        function GetEnabled() {
2423
                return $this->qenabled;
2424
        }
2425
        function SetEnabled($value) {
2426
                $this->qenabled = $value;
2427
        }
2428
		function CanHaveChilds() {
2429
                return false;
2430
        }
2431
		function CanBeDeleted() {
2432
                return true;
2433
        }
2434
        function GetQname() {
2435
                return $this->qname;
2436
        }
2437
        function SetQname($name) {
2438
                $this->qname = trim($name);
2439
        }
2440
        function GetQlimit() {
2441
                return $this->qlimit;
2442
        }
2443
        function SetQlimit($limit) {
2444
               	$this->qlimit = $limit;
2445
        }
2446
        function GetDescription() {
2447
                return $this->description;
2448
        }
2449
        function SetDescription($str) {
2450
                $this->descritpion = trim($str);
2451
        }
2452
        function GetFirstime() {
2453
                return $this->firsttime;
2454
        }
2455
        function SetFirsttime($number) {
2456
                $this->firsttime = $number;
2457
        }
2458
        function GetBuckets() {
2459
                return $this->buckets;
2460
        }
2461
        function SetBuckets($buckets) {
2462
                $this->buckets = $buckets;
2463
        }
2464
		function SetNumber($number) {
2465
			$this->qnumber = $number;
2466
		}
2467
		function GetNumber() {
2468
			return $this->qnumber;
2469
		}
2470
        function GetPlr() {
2471
                return $this->plr;
2472
        }
2473
        function SetPlr($plr) {
2474
                $this->plr = $plr;
2475
        }
2476

    
2477
		function build_javascript() { return; } /* Do not remove */
2478

    
2479
		function validate_input($data, &$input_errors) {
2480
			$reqdfields[] = "bandwidth";
2481
			$reqdfieldsn[] = "Bandwidth";
2482
			$reqdfields[] = "bandwidthtype";
2483
			$reqdfieldsn[] = "Bandwidthtype";
2484
			$reqdfields[] = "name";
2485
			$reqdfieldsn[] = "Name";
2486
		
2487
			shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2488

    
2489
			if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2490
					($data['plr'] <= 0 && $data['plr'] > 1))) 
2491
            	$input_errors[] = "Plr must be an integer between 1 and 100.";
2492
			if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2493
					($data['buckets'] < 1 && $data['buckets'] > 100)) 
2494
            	$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2495
			if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2496
            	$input_errors[] = "Queue limit must be an integer";
2497
        	if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2498
               	 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2499
		}
2500
}
2501

    
2502
class dnpipe_class extends dummynet_class {
2503
        var $pipe_nr;
2504
        var $delay;
2505
	var $qbandwidth;
2506
	var $qbandwidthtype;
2507

    
2508
		/* This is here to help on form building and building rules/lists */
2509
        var $subqueues = array();
2510

    
2511
	function CanHaveChilds() {
2512
	        return true;
2513
        }
2514
	function SetDelay($delay) {
2515
		$this->delay = $delay;
2516
	}
2517
	function GetDelay() {
2518
		return $this->delay;
2519
	}
2520
	function GetBwscale() {
2521
                return $this->qbandwidthtype;
2522
        }
2523
        function SetBwscale($scale) {
2524
               	$this->qbandwidthtype = $scale;
2525
        }		
2526
	function delete_queue() {
2527
		cleanup_dnqueue_from_rules($this->GetQname());
2528
		foreach ($this->subqueues as $q)
2529
			$q->delete_queue();
2530
		unset_dn_object_by_reference($this->GetLink());
2531
        }
2532
        function GetBandwidth() {
2533
                return $this->qbandwidth;
2534
        }
2535
        function SetBandwidth($bandwidth) {
2536
                $this->qbandwidth = $bandwidth;
2537
        }
2538

    
2539
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2540

    
2541
		if (!is_array($this->subqueues))
2542
			$this->subqueues = array();
2543
			
2544
		$q =& new dnqueue_class();
2545
		$q->SetLink($path);
2546
		$q->SetEnabled("on");
2547
		$q->SetPipe($this->GetQname());
2548
		$q->SetParent(&$this);
2549
		$q->ReadConfig($queue);
2550
		$q->validate_input($queue, $input_errors);
2551
		if (count($input_errors))
2552
			return $q;
2553
		$this->subqueues[$q->GetQname()] = &$q;
2554
            
2555
		return $q;
2556
	}
2557

    
2558
	function &get_queue_list($q = null) {
2559
		$qlist = array();
2560

    
2561
		$qlist[$this->GetQname()] = $this->GetNumber();
2562
		if (is_array($this->subqueues)) {
2563
			foreach ($this->subqueues as $queue)
2564
				$queue->get_queue_list(&$qlist);
2565
		}
2566
		return $qlist;
2567
	}
2568
		
2569
        /*
2570
         * Should search even its childs
2571
         */
2572
        function &find_queue($pipe, $qname) {
2573
                if ($qname == $this->GetQname()) 
2574
                        return $this;
2575
               	foreach ($this->subqueues as $q) {
2576
                       	$result =& $q->find_queue("", $qname);
2577
						if ($result)
2578
                       	        return $result;
2579
               	}
2580
        }
2581

    
2582
	function &find_parentqueue($pipe, $qname) {
2583
		return NULL;
2584
       	}
2585

    
2586
	function validate_input($data, &$input_errors) {
2587
		parent::validate_input($data, $input_errors);
2588

    
2589
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2590
       		     	$input_errors[] = "Bandwidth must be an integer.";
2591
		if ($data['delay'] && (!is_numeric($data['delay'])))
2592
            		$input_errors[] = "Delay must be an integer.";
2593
		}
2594

    
2595
	function ReadConfig(&$q) {
2596
           	$this->SetQname($q['name']);
2597
		$this->SetNumber($q['number']);
2598
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2599
			$this->SetBandwidth($q['bandwidth']);
2600
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2601
				$this->SetBwscale($q['bandwidthtype']);
2602
		}
2603
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2604
              		$this->SetQlimit($q['qlimit']);
2605
		if (isset($q['mask']) && $q['mask'] <> "")
2606
              		$this->SetMask($q['mask']);
2607
		if (isset($q['buckets']) && $q['buckets'] <> "")
2608
              		$this->SetBuckets($q['buckets']);
2609
            	if (isset($q['plr']) && $q['plr'] <> "")
2610
            		$this->SetPlr($q['plr']);
2611
		if (isset($q['delay']) && $q['delay'] <> "")
2612
            		$this->SetDelay($q['delay']);
2613
            	if (isset($q['description']) && $q['description'] <> "")
2614
			$this->SetDescription($q['description']);
2615
		$this->SetEnabled($q['enabled']);
2616

    
2617
        }
2618

    
2619
	function build_tree() {
2620
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2621
		$tree .= $this->GetQname() . "</a>";
2622
		if (is_array($this->subqueues)) {
2623
			$tree .= "<ul>";
2624
			foreach ($this->subqueues as $q)  {
2625
				$tree .= $q->build_tree();
2626
			}	
2627
			$tree .= "</ul>";
2628
		}
2629
		$tree .= "</li>";
2630
		
2631
		return $tree;
2632
	}
2633

    
2634
        function build_rules() {
2635
		if ($this->GetEnabled() == "")
2636
			return;
2637

    
2638
       		$pfq_rule = "\ndnpipe ". $this->GetNumber();
2639
		if ($this->GetBandwidth() && $this->GetBwscale())
2640
                    	$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2641
		if ($this->GetQlimit())
2642
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2643
		if ($this->GetPlr())
2644
			$pfq_rule .= " plr " . $this->GetPlr();
2645
		if ($this->GetBuckets())
2646
			$pfq_rule .= " buckets " . $this->GetBuckets();
2647
		if ($this->GetDelay())
2648
			$pfq_rule .= " delay " . $this->GetDelay();
2649

    
2650
		$mask = $this->GetMask();
2651
		if (!empty($mask)) {
2652
			/* XXX TODO extend this to support more complicated masks */
2653
			switch ($mask) {
2654
			case 'srcaddress':
2655
				$pfq_rule .= " mask src-ip 0xffffffff ";
2656
				break;
2657
			case 'dstaddress':
2658
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2659
				break;
2660
			default:
2661
				break;
2662
			}
2663
			$pfq_rule .= "\n";
2664

    
2665
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2666
       			        foreach ($this->subqueues as $q)
2667
				$pfq_rule .= $q->build_rules();
2668
               		}
2669
    		}            
2670
		$pfq_rule .= " \n";
2671

    
2672
		return $pfq_rule;
2673
        }
2674

    
2675
	function update_dn_data(&$data) { 
2676
		$this->ReadConfig($data);
2677
	}
2678

    
2679
        function build_form() { 
2680
		$form = "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
2681
		$form .= "<td class=\"vncellreq\">";
2682
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
2683
		$form .= $this->GetQname()."\">";
2684
		$form .= "</td></tr>";
2685
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Bandwidth";
2686
		$form .= "</td><td class=\"vncellreq\">";
2687
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
2688
		$form .= $this->GetBandwidth() . "\">"; 
2689
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
2690
		$form .= "<option value=\"Kb\"";
2691
		if ($this->GetBwscale() == "Kb")
2692
			$form .= " selected=\"yes\"";
2693
		$form .= ">Kbit/s</option>";
2694
		$form .= "<option value=\"Mb\"";
2695
		if ($this->GetBwscale() == "Mb")
2696
			$form .= " selected=\"yes\"";
2697
		$form .= ">Mbit/s</option>";
2698
		$form .= "<option value=\"Gb\"";
2699
		if ($this->GetBwscale() == "Gb")
2700
			$form .= " selected=\"yes\"";
2701
		$form .= ">Gbit/s</option>";		
2702
		$form .= "<option value=\"\"";
2703
		if ($this->GetBwscale() == "b")
2704
			$form .= " selected=\"yes\"";
2705
		$form .= ">Bit/s</option>";
2706
		$form .= "</select>";
2707
		$form .= "</td></tr>";
2708
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Mask</td>";
2709
		$form .= "<td class=\"vncellreq\">";
2710
		$form .= "<select name=\"mask\" class=\"formselect\">";
2711
		$form .= "<option value=\"none\"";
2712
		if ($this->GetMask() == "none")
2713
			$form .= " selected=\"yes\"";
2714
		$form .= ">none</option>";
2715
		$form .= "<option value=\"srcaddress\"";
2716
		if ($this->GetMask() == "srcaddress")
2717
			$form .= " selected=\"yes\"";
2718
		$form .= ">Source addresses</option>";
2719
		$form .= "<option value=\"dstaddress\"";
2720
		if ($this->GetMask() == "dstaddress")
2721
			$form .= " selected=\"yes\"";
2722
		$form .= ">Destination addresses</option>";
2723
		$form .= "</select>";
2724
		$form .= "&nbsp;<br>";
2725
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
2726
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
2727
		$form .= "be created for each source/destination IP address encountered, \n";
2728
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
2729
		$form .= "limits per host.</span>";
2730
		$form .= "</td></tr>";
2731
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Description</td>";
2732
		$form .= "<td class=\"vncellreq\">";
2733
		$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
2734
		$form .= $this->GetDescription();
2735
		$form .= "\">";
2736
		$form .= "<br> <span class=\"vexpl\">";
2737
		$form .= "You may enter a description here ";
2738
		$form .= "for your reference (not parsed).</span>";
2739
		$form .= "</td></tr>";
2740
      		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
2741
		$form .= "<td></td>";
2742
                $form .= "<td><div id=\"showadvancedboxspr\">";
2743
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
2744
		$form .= " value=\"Show advanced options\"></input></a>";
2745
                $form .= "</div></td></tr>";
2746
                $form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
2747

    
2748
		$form .= "<td valign=\"top\" class=\"vncellreq\">Delay</td>";
2749
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
2750
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
2751
		$form .= $this->GetDelay() . "\">";
2752
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: in most cases, you"; 
2753
		$form .= "should specify 0 here (or leave the field empty)</span>";
2754
		$form .= "</td></tr><br/>";
2755
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
2756
		$form .= "<td valign=\"top\" class=\"vncellreq\">Packet loss rate</td>";
2757
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
2758
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
2759
		$form .= $this->GetPlr() . "\">";
2760
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you"; 
2761
        $form .= "should specify 0 here (or leave the field empty).";
2762
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
2763
		$form .= "</td></tr>";
2764
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
2765
		$form .= "<td valign=\"top\" class=\"vncellreq\">Queue Size</td>";
2766
		$form .= "<td class=\"vncellreq\">";
2767
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
2768
		$form .= $this->GetQlimit() . "\">";
2769
		$form .= "&nbsp;slots<br>";
2770
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
2771
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
2772
	        $form .= "then they are delayed by value specified in the Delay field, and then they ";
2773
		$form .= "are delivered to their destination.</span>";
2774
		$form .= "</td></tr>";
2775
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
2776
                $form .= "<td valign=\"top\" class=\"vncellreq\">Bucket Size</td>";
2777
                $form .= "<td class=\"vncellreq\">";
2778
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
2779
                $form .= $this->GetBuckets() . "\">";
2780
                $form .= "&nbsp;slots<br>";
2781
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
2782
                $form .= "should leave the field empty. It increases the hash size set.";
2783
                $form .= "</td></tr>";
2784

    
2785
		return $form;
2786
			
2787
		}
2788

    
2789
	function wconfig() {
2790
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
2791
            	if (!is_array($cflink))
2792
            		$cflink = array();
2793
		$cflink['name'] = $this->GetQname();
2794
		$cflink['number'] = $this->GetNumber();
2795
            	$cflink['qlimit'] = $this->GetQlimit();
2796
            	$cflink['plr'] = $this->GetPlr();
2797
            	$cflink['description'] = $this->GetDescription();
2798
		$cflink['bandwidth'] = $this->GetBandwidth();
2799
            	$cflink['bandwidthtype'] = $this->GetBwscale();
2800
		$cflink['enabled'] = $this->GetEnabled();
2801
		$cflink['buckets'] = $this->GetBuckets();
2802
		$cflink['mask'] = $this->GetMask();
2803
		$cflink['delay'] = $this->GetDelay();
2804
	}
2805

    
2806
}
2807

    
2808
class dnqueue_class extends dummynet_class {
2809
        var $pipeparent;
2810
        var $weight;
2811

    
2812
        function GetWeight() {
2813
                return $this->weight;
2814
        }
2815
        function SetWeight($weight) {
2816
                $this->weight = $weight;
2817
        }
2818
	function GetPipe() {
2819
		return $this->pipeparent;
2820
	}
2821
	function SetPipe($pipe) {
2822
		$this->pipeparent = $pipe;
2823
	}
2824

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

    
2828
	function delete_queue() {
2829
		cleanup_dnqueue_from_rules($this->GetQname());
2830
		unset_dn_object_by_reference($this->GetLink());
2831
        }
2832

    
2833
	function validate_input($data, &$input_errors) {
2834
		parent::validate_input($data, $input_errors);
2835

    
2836
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
2837
			($data['weight'] < 1 && $data['weight'] > 100))) 
2838
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
2839
	}
2840

    
2841
        /*
2842
         * Should search even its childs
2843
         */
2844
        function &find_queue($pipe, $qname) {
2845
                if ($qname == $this->GetQname()) 
2846
                	return $this;
2847
		else
2848
			return NULL;
2849
        }
2850

    
2851
	function &find_parentqueue($pipe, $qname) {
2852
		return $this->qparent;
2853
        }
2854

    
2855
        function &get_queue_list(&$qlist) {
2856
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
2857
        }		
2858

    
2859
	function ReadConfig(&$q) {
2860
          	$this->SetQname($q['name']);
2861
		$this->SetNumber($q['number']);
2862
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2863
       		       	$this->SetQlimit($q['qlimit']);
2864
		if (isset($q['mask']) && $q['mask'] <> "")
2865
              		$this->SetMask($q['mask']);
2866
       		if (isset($q['weight']) && $q['weight'] <> "")
2867
            		$this->SetWeight($q['weight']);
2868
            	if (isset($q['descritption']) && $q['description'] <> "")
2869
			$this->SetDescription($q['description']);
2870
		$this->SetEnabled($q['enabled']);
2871
        }
2872

    
2873
	function build_tree() {
2874
		$parent =& $this->GetParent();
2875
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
2876
		$tree .= $this->GetQname() . "</a>";
2877
		$tree .= "</li>";
2878
		
2879
		return $tree;
2880
	}
2881

    
2882
        function build_rules() {
2883
		if ($this->GetEnabled() == "")
2884
			return; 
2885

    
2886
		$parent =& $this->GetParent();
2887
            	$pfq_rule = "dnqueue ". $this->GetNumber() . " dnpipe " . $parent->GetNumber();
2888
		if ($this->GetQlimit())
2889
                    	$pfq_rule .= " queue " . $this->GetQimit();
2890
		if ($this->GetWeight())
2891
			$pfq_rule .= " weight " . $this->GetWeight();
2892
		if ($this->GetBuckets())
2893
			$pfq_rule .= " buckets " . $this->GetBuckets();
2894
		$mask = $this->GetMask();
2895
		if (!empty($mask)) {
2896
			/* XXX TODO extend this to support more complicated masks */
2897
			switch ($mask) {
2898
			case 'srcaddress':
2899
				$pfq_rule .= " mask src-ip 0xffffffff ";
2900
				break;
2901
			case 'dstaddress':
2902
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2903
				break;
2904
			default:
2905
				break;
2906
			}
2907
			$pfq_rule .= "\n";
2908
		}
2909

    
2910
		return $pfq_rule;
2911
	}
2912

    
2913
        function build_form() { 
2914
		$form = "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
2915
		$form .= "<td class=\"vncellreq\">";
2916
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
2917
		$form .= $this->GetQname()."\">";
2918
		$form .= "</td></tr>";
2919
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Mask</td>";
2920
		$form .= "<td class=\"vncellreq\">";
2921
		$form .= "<select name=\"mask\" class=\"formselect\">";
2922
		$form .= "<option value=\"none\"";
2923
		if ($this->GetMask() == "none")
2924
			$form .= " selected=\"yes\"";
2925
		$form .= ">none</option>";
2926
		$form .= "<option value=\"srcaddress\"";
2927
		if ($this->GetMask() == "srcaddress")
2928
			$form .= " selected=\"yes\"";
2929
		$form .= ">Source addresses</option>";
2930
		$form .= "<option value=\"dstaddress\"";
2931
		if ($this->GetMask() == "dstaddress")
2932
			$form .= " selected=\"yes\"";
2933
		$form .= ">Destination addresses</option>";
2934
		$form .= "</select>";
2935
		$form .= "&nbsp;slots<br>";
2936
		$form .= "<span class=\"vexpl\">If 'source' or 'destination' is chosen, \n";
2937
		$form .= "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n";
2938
		$form .= "be created for each source/destination IP address encountered, \n";
2939
		$form .= "respectively. This makes it possible to easily specify bandwidth \n";
2940
		$form .= "limits per host.</span>";
2941
		$form .= "</td></tr>";
2942
		$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Description</td>";
2943
		$form .= "<td class=\"vncellreq\">";
2944
		$form .= "<input type=\"text\" id=\"description\" class=\"formfld unknown\" size=\"50%\" name=\"description\" value=\"";
2945
		$form .= $this->GetDescription();
2946
		$form .= "\">";
2947
		$form .= "<br> <span class=\"vexpl\">";
2948
		$form .= "You may enter a description here ";
2949
		$form .= "for your reference (not parsed).</span>";
2950
		$form .= "</td></tr>";
2951
		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
2952
		$form .= "<td></td>";
2953
                $form .= "<td><div id=\"showadvancedboxspr\">";
2954
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
2955
		$form .= " value=\"Show advanced options\"></input></a>";
2956
                $form .= "</div></td></tr>";
2957
		$form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
2958
		$form .= "<td valign=\"top\" class=\"vncellreq\">Weight</td>";
2959
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
2960
		$form .= "<input name=\"weight\" type=\"text\" id=\"weight\" size=\"5\" value=\"";
2961
		$form .= $this->GetWeight() . "\">";
2962
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">Hint: For queues under the same parent"; 
2963
		$form .= "this specifies the share that a queue gets(values range from 1 to 100, you can leave it blank otherwise)</span>";
2964
		$form .= "</td></tr>";
2965
		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
2966
		$form .= "<td valign=\"top\" class=\"vncellreq\">Packet loss rate</td>";
2967
		$form .= "<td valign=\"top\" class=\"vncellreq\">";
2968
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
2969
		$form .= $this->GetPlr() . "\">";
2970
		$form .= "&nbsp;<br> <span class=\"vexpl\">Hint: in most cases, you"; 
2971
        	$form .= "should specify 0 here (or leave the field empty).";
2972
		$form .= "A value of 0.001 means one packet in 1000 gets dropped</span>";
2973
		$form .= "</td></tr>";
2974
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
2975
		$form .= "<td valign=\"top\" class=\"vncellreq\">Queue Size</td>";
2976
		$form .= "<td class=\"vncellreq\">";
2977
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
2978
		$form .= $this->GetQlimit() . "\">";
2979
		$form .= "&nbsp;slots<br>";
2980
		$form .= "<span class=\"vexpl\">Hint: in most cases, you ";
2981
		$form .= "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first,";
2982
        $form .= "then they are delayed by value specified in the Delay field, and then they ";
2983
		$form .= "are delivered to their destination.</span>";
2984
		$form .= "</td></tr>";
2985
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
2986
                $form .= "<td valign=\"top\" class=\"vncellreq\">Bucket Size</td>";
2987
                $form .= "<td class=\"vncellreq\">";
2988
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
2989
                $form .= $this->GetBuckets() . "\">";
2990
                $form .= "&nbsp;slots<br>";
2991
                $form .= "<span class=\"vexpl\">Hint: in most cases, you ";
2992
                $form .= "should leave the field empty. It increases the hash size set.";
2993
                $form .= "</td></tr>";
2994

    
2995
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
2996
		$form .= " value=\"" . $this->GetPipe() . "\">";
2997

    
2998
		return $form;
2999
			
3000
	}
3001

    
3002
        function update_dn_data(&$data) { 
3003
		$this->ReadConfig($data);
3004
	}
3005

    
3006
	function wconfig() {
3007
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3008
            	if (!is_array($cflink))
3009
            		$cflink = array();
3010
		$cflink['name'] = $this->GetQname();
3011
		$cflink['number'] = $this->GetNumber();
3012
            	$cflink['qlimit'] = $this->GetQlimit();
3013
            	$cflink['description'] = $this->GetDescription();
3014
		$cflink['weight'] = $this->GetWeight();
3015
		$cflink['enabled'] = $this->GetEnabled();
3016
		$cflink['buckets'] = $this->GetBuckets();
3017
		$cflink['mask'] = $this->GetMask();
3018
	}
3019
}
3020

    
3021
// List of layer7 objects
3022
$layer7_rules_list = array();
3023

    
3024
class layer7 {
3025
    
3026
    var $rname; //alias
3027
    var $rdescription; //alias description
3028
    var $rport; //divert port
3029
    var $renabled; //rule enabled
3030
    var $rsets = array(); //array of l7 associations
3031
    
3032
    // Auxiliary functions
3033
    
3034
    function GetRName() {
3035
        return $this->rname;
3036
    }
3037
    function SetRName($rname) {
3038
        $this->rname = $rname;
3039
    }
3040
    function GetRDescription() {
3041
        return $this->rdescription;
3042
    }
3043
    function SetRDescription($rdescription) {
3044
        $this->rdescription = $rdescription;
3045
    }
3046
    function GetRPort() {
3047
        return $this->rport;
3048
    }
3049
    function SetRPort($rport) {
3050
        $this->rport = $rport;
3051
    }
3052
    function GetREnabled() {
3053
        return $this->renabled;
3054
    }
3055
    function SetREnabled($value) {
3056
        $this->renabled = $value;
3057
    }
3058
    function GetRl7() {
3059
        return $this->rsets;
3060
    }
3061
    function SetRl7($rsets) {
3062
        $this->rsets = $rsets;
3063
    }
3064
    
3065
    //Add a tuple (rule,sctructure,element) to the $rsets
3066
    
3067
    function add_rule($l7set) {
3068
        $this->rsets[] = $l7set;
3069
    }
3070
    
3071
    // Build the layer7 rules
3072
    function build_l7_rules() {
3073
        if($this->GetREnabled() == "") {
3074
            return;
3075
        }
3076
        //$l7rules = "#" . $this->rdescription . "\n";
3077
        foreach ($this->rsets as $rl7) {
3078
            $l7rules .= $rl7->build_rules();
3079
        }
3080
        return $l7rules;
3081
    }
3082
    
3083
    // Read the config from array
3084
    function ReadConfig(&$qname, &$q) {
3085
        $this->SetRName($qname);
3086
        $this->SetREnabled($q['enabled']);
3087
        $this->SetRPort($q['divert_port']);
3088
        if(isset($q['description']) && $q['description'] <> "")
3089
            $this->SetRDescription($q['description']);
3090
        $rsets = $q['l7rules'];
3091
        //Put individual rules in the array
3092
	if(is_array($rsets)) {
3093
	    foreach($rsets as $l7r) {
3094
	        $l7obj = new l7rule();
3095
	        $l7obj->SetRProtocol($l7r['protocol']);
3096
	        $l7obj->SetRStructure($l7r['structure']);
3097
	        $l7obj->SetRBehaviour($l7r['behaviour']);
3098
	        $this->add_rule($l7obj);
3099
	    }
3100
	}
3101
    }
3102
    
3103
    //Generate a random port for the divert socket
3104
    function gen_divert_port() {
3105
        $dports = get_divert_ports(); //array of used ports
3106
        $divert_port = rand(40000, 60000);
3107
        while(true) {
3108
            foreach($dports as $dport) {
3109
                $dupe = false;
3110
                if($dport == $divert_port) {
3111
                    $divert_port = rand(40000, 60000);
3112
                    $dupe = true;
3113
                    break;
3114
                }
3115
            }
3116
            if(!$dupe) {
3117
                break;
3118
            }
3119
        }
3120
        return $divert_port;
3121
    }
3122
    
3123
    //Helps building the left tree
3124
    function build_tree() {
3125
        $tree = " <li><a href=\"firewall_shaper_layer7.php?container=" . $this->GetRName() ."&action=show\">"; 
3126
        $tree .= $this->GetRName() . "</a>";
3127
	$tree .= "</li>";
3128
		
3129
	return $tree;
3130
    }
3131
    
3132
    function build_form() {
3133
        $form = "<tr><td valign=\"top\" class=\"vncellreq\"><br>";
3134
	$form .= "Enable/Disable";
3135
	$form .= "</td><td class=\"vncellreq\">";
3136
	$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\"";
3137
	if ($this->GetREnabled()) {
3138
       	    $form .=  "checked = \"CHECKED\"";
3139
	}
3140
	$form .= " ><span class=\"vexpl\"> Enable/Disable layer7 Container</span>";
3141
	$form .= "</td></tr>";
3142
        $form .= "<tr><td valign=\"top\" class=\"vncellreq\"><br><span class=\"vexpl\">Name</span></td>";
3143
	$form .= "<td class=\"vncellreq\">";
3144
	$form .= "<input type=\"text\" id=\"container\" name=\"container\" value=\"";
3145
	$form .= $this->GetRName()."\">";
3146
	$form .= "</td></tr>";
3147
	$form .= "<tr><td valign=\"top\" class=\"vncellreq\">Description</td>";
3148
	$form .= "<td class=\"vncellreq\">";
3149
	$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3150
	$form .= $this->GetRDescription();
3151
	$form .= "\">";
3152
	$form .= "<br> <span class=\"vexpl\">";
3153
	$form .= "You may enter a description here ";
3154
	$form .= "for your reference (not parsed).</span>";
3155
	$form .= "</td></tr>";
3156
	
3157
	return $form;
3158
    }
3159
    
3160
    //Write the setting to the $config array
3161
    function wconfig() {
3162
	global $config;
3163
	
3164
	if(!is_array($config['l7shaper']['container'])) {
3165
		$config['l7shaper']['container'] = array();
3166
	}
3167
        //
3168
        $cflink =& get_l7c_reference_to_me_in_config($this->GetRName());
3169
	// Test if this rule does exists already
3170
	if(!$cflink) {
3171
		$cflink =& $config['l7shaper']['container'][];
3172
	}
3173
	$cflink['name'] = $this->GetRName();
3174
        $cflink['enabled'] = $this->GetREnabled();
3175
        $cflink['description'] = $this->GetRDescription();
3176
        $cflink['divert_port'] = $this->GetRPort();
3177
        
3178
	//Destroy previously existent rules
3179
	if(is_array($cflink['rules'])) {
3180
		unset($cflink['l7rules']);
3181
	}
3182
	
3183
        $cflink['l7rules'] = array();
3184
	
3185
        $i = 0;
3186
        foreach($this->rsets as $rulel7) {
3187
            $cflink['l7rules'][$i]['protocol'] = $rulel7->GetRProtocol();
3188
            $cflink['l7rules'][$i]['structure'] = $rulel7->GetRStructure();
3189
            $cflink['l7rules'][$i]['behaviour'] = $rulel7->GetRBehaviour();
3190
            $i++;
3191
        }
3192
    }
3193
    
3194
    //This function is necessary to help producing the overload options for keep state
3195
    function get_unique_structures() {
3196
        
3197
        $unique_structures = array("action" => false, "dummynet" => false, "altq" => false);
3198
        foreach($this->rsets as $l7rule) {
3199
		if($l7rule->GetRStructure() == "action")
3200
			$unique_structures['action'] = true;
3201
		else if($l7rule->GetRStructure() == "limiter")
3202
			$unique_structures['dummynet'] = true;
3203
		else
3204
			$unique_structures['altq'] = true;
3205
        }
3206
	//Delete non used structures so we don't have to check this in filter.inc
3207
	foreach($unique_structures as $key => $value)
3208
		if(!$value)
3209
			unset($unique_structures[$key]);
3210
        return $unique_structures;
3211
    }
3212
    
3213
    function validate_input($data, &$input_errors) {
3214
	$reqdfields[] = "container";
3215
	$reqdfieldsn[] = "Name";
3216
		
3217
	shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
3218
        
3219
        if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['container']))
3220
            $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
3221
    }
3222
    
3223
    function delete_l7c() {
3224
	$l7pid = `/bin/ps -ax | /usr/bin/grep ipfw-classifyd | /usr/bin/grep ". $l7rules->GetRPort() . " | /usr/bin/grep -v grep | /usr/bin/awk '{ print $1 }'`;
3225
	mwexec("/bin/kill {$l7pid}");
3226
	unset_l7_object_by_reference($this->GetRName());
3227
	cleanup_l7_from_rules($this->GetRName());
3228
    }
3229
}
3230

    
3231
class l7rule {
3232
    
3233
    var $rprotocol; //protocol
3234
    var $rstructure; //action, limiter, queue
3235
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3236
    
3237
    //Auxiliary Functions
3238
    
3239
    function GetRProtocol() {
3240
        return $this->rprotocol;
3241
    }
3242
    function SetRProtocol($rprotocol) {
3243
        $this->rprotocol = $rprotocol;
3244
    }
3245
    function GetRStructure() {
3246
        return $this->rstructure;
3247
    }
3248
    function SetRStructure($rstructure) {
3249
        $this->rstructure = $rstructure;
3250
    }
3251
    function GetRBehaviour() {
3252
        return $this->rbehaviour;
3253
    }
3254
    function SetRBehaviour($rbehaviour) {
3255
        $this->rbehaviour = $rbehaviour;
3256
    }
3257
    
3258
    //XXX Do we need to test any particularity for AltQ queues?
3259
    function build_rules() {
3260
	global $dummynet_pipe_list;
3261
	switch ($this->GetRStructure()) {
3262
		case "limiter":
3263
			read_dummynet_config();
3264
			$dn_list =& get_unique_dnqueue_list();
3265
			$found = false;
3266
			if(is_array($dn_list)) {
3267
				foreach($dn_list as $key => $value) {
3268
					if($key == $this->GetRBehaviour()) {
3269
						if($value[0] == "?")
3270
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3271
						else
3272
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3273
						$found = true;
3274
					}
3275
					if($found)
3276
						break;
3277
				}
3278
			}
3279
			break;
3280
		default: //This is for action and for altq
3281
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3282
			break;
3283
	}
3284
        return $l7rule;
3285
    }
3286
}
3287

    
3288
/*
3289
 * This function allows to return an array with all the used divert socket ports
3290
 */
3291
function get_divert_ports() {
3292
    global $layer7_rules_list;
3293
    $dports = array();
3294
    
3295
    foreach($layer7_rules_list as $l7r)
3296
        $dports[] = $l7r->GetRPort();
3297
    
3298
    return $dports;
3299
}
3300

    
3301
function &get_l7c_reference_to_me_in_config(&$name) {
3302
	global $config;
3303
	
3304
	$ptr = NULL;
3305
	
3306
	if(is_array($config['l7shaper']['container'])) {
3307
		foreach($config['l7shaper']['container'] as $key => $value) {
3308
			if($value['name'] == $name)
3309
				$ptr =& $config['l7shaper']['container'][$key];
3310
		}
3311
	}	
3312
	return $ptr;
3313
// $ptr can be null. has to be checked later
3314
}
3315

    
3316
function unset_l7_object_by_reference(&$name) {
3317
	global $config;
3318
        
3319
	if(is_array($config['l7shaper']['container'])) {
3320
		foreach($config['l7shaper']['container'] as $key => $value) {
3321
			if($value['name'] == $name) {
3322
				unset($config['l7shaper']['container'][$key]['l7rules']);
3323
				unset($config['l7shaper']['container'][$key]);
3324
				break;
3325
			}
3326
		}
3327
	}
3328
}
3329

    
3330
function read_layer7_config() {
3331
    global $layer7_rules_list, $config;
3332
    
3333
    $l7cs = &$config['l7shaper']['container'];
3334
    
3335
    $layer7_rules_list = array();
3336
    
3337
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3338
	return;
3339
    
3340
    foreach ($l7cs as $conf) {
3341
	if (empty($conf['name']))
3342
		continue; /* XXX: grrrrrr at php */ 
3343
        $root =& new layer7();
3344
        $root->ReadConfig($conf['name'],$conf);
3345
        $layer7_rules_list[$root->GetRName()] = &$root;
3346
    }
3347
}
3348

    
3349
function generate_layer7_files() {
3350
    global $layer7_rules_list;
3351
    
3352
    read_layer7_config();
3353
    
3354
    if (!empty($layer7_rules_list)) {
3355
	if (!is_module_loaded("ipdivert.ko"))
3356
		mwexec("/sbin/kldload ipdivert.ko");
3357

    
3358
	mwexec("rm -f /tmp/*.l7");
3359
    }
3360
    
3361
    foreach($layer7_rules_list as $l7rules) {
3362
        if($l7rules->GetREnabled()) {
3363
            $filename = $l7rules->GetRName() . ".l7";
3364
            $path = "/tmp/" . $filename;
3365
        
3366
            $rules = $l7rules->build_l7_rules();
3367
        
3368
            $fp = fopen($path,'w');
3369
            fwrite($fp,$rules);
3370
            fclose($fp);
3371
        }
3372
    }
3373
}
3374

    
3375
function layer7_start_l7daemon() {
3376
    global $layer7_rules_list;
3377

    
3378
    /*
3379
     * XXX: ermal - Needed ?!
3380
     * read_layer7_config();
3381
     */
3382

    
3383
    foreach($layer7_rules_list as $l7rules) {
3384
        if($l7rules->GetREnabled()) {
3385
            $filename = $l7rules->GetRName() . ".l7";
3386
            $path = "/tmp/" . $filename;
3387

    
3388
	    unset($l7pid);
3389
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3390
	    exec("/bin/ps -ax | /usr/bin/grep ipfw-classifyd | /usr/bin/grep ". $l7rules->GetRPort() . " | /usr/bin/grep -v grep | /usr/bin/awk '{ print $1}'", $l7pid);
3391
	    if (count($l7pid) > 0) {
3392
		log_error("Sending HUP signal to {$l7pid[0]}");
3393
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3394
	    } else {
3395
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3396
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3397
		mwexec_bg($ipfw_classifyd_init);
3398
	    }
3399
        }
3400
    }
3401
}
3402

    
3403
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3404
function generate_protocols_array() {
3405
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3406
	if(is_array($protocols)) {
3407
		foreach($protocols as $key => $proto)
3408
			$protocols[$key] =& str_replace(".pat", "", $proto);
3409
		sort($protocols);
3410
	}		
3411
	return $protocols;
3412
}
3413

    
3414
function get_l7_unique_list() {
3415
	global $layer7_rules_list;
3416
	
3417
	$l7list = array();
3418
	if(is_array($layer7_rules_list)) 
3419
		foreach($layer7_rules_list as $l7c)
3420
			if($l7c->GetREnabled())
3421
				$l7list[] = $l7c->GetRName();
3422
	
3423
	return $l7list;
3424
}
3425

    
3426
// Disable a removed l7 container from the filter
3427
function cleanup_l7_from_rules(&$name) {
3428
	global $config;
3429

    
3430
	if(is_array($config['filter']['rule']))
3431
		foreach ($config['filter']['rule'] as $key => $rule) {
3432
			if ($rule['l7container'] == $name)
3433
				unset($config['filter']['rule'][$key]['l7container']);
3434
		}
3435
}
3436

    
3437
function get_dummynet_name_list() {
3438
	
3439
	$dn_name_list =& get_unique_dnqueue_list();
3440
	$dn_name = array();
3441
	if(is_array($dn_name_list))
3442
		foreach($dn_name_list as $key => $value)
3443
			$dn_name[] = $key;
3444
	
3445
	return $dn_name;
3446
	
3447
}
3448

    
3449
function get_altq_name_list() {
3450
	$altq_name_list =& get_unique_queue_list();
3451
	$altq_name = array();
3452
	if(is_array($altq_name_list))
3453
		foreach($altq_name_list as $key => $aqobj)
3454
			$altq_name[] = $key;
3455
		
3456
	return $altq_name;
3457
}
3458

    
3459
/*
3460
 * XXX: TODO Make a class shaper to hide all these function
3461
 * from the global namespace.
3462
 */
3463

    
3464
/* 
3465
 * This is a layer violation but for now there is no way 
3466
 * i can find to properly do this with PHP.
3467
 */
3468
function altq_set_default_queue($interface, $value) {
3469
	global $altq_list_queues;
3470
		
3471
	$altq_tmp =& $altq_list_queues[$interface];
3472
	if ($altq_tmp) {
3473
		if ($value) {
3474
			$altq_tmp->SetDefaultQueuePresent("true");
3475
		}
3476
		else {
3477
			$altq_tmp->SetDefaultQueuePresent("false");
3478
		}
3479
	}
3480
}
3481

    
3482
function altq_get_default_queue($interface) {
3483
	global $altq_list_queues;
3484

    
3485
	$altq_tmp = $altq_list_queues[$interface];
3486
	if ($altq_tmp)  
3487
		return $altq_tmp->GetDefaultQueuePresent(); 
3488
}
3489

    
3490
function altq_check_default_queues() {
3491
	global $altq_list_queues;
3492

    
3493
	$count = 0;
3494
	if (is_array($altq_list_queues)) {
3495
		foreach($altq_list_queues as $altq) {
3496
			if ($altq->GetDefaultQueuePresent())
3497
				$count++;
3498
		}
3499
	}
3500
	else  $count++;;
3501
	
3502
	return 0;
3503
}
3504

    
3505
function &get_unique_queue_list() {
3506
	global $altq_list_queues;
3507
	
3508
	$qlist = array();
3509
	if (is_array($altq_list_queues)) {
3510
		foreach ($altq_list_queues as $altq) {
3511
			$tmplist =& $altq->get_queue_list();
3512
			foreach ($tmplist as $qname => $link)
3513
				$qlist[$qname] = $link;	
3514
		}
3515
	}
3516
	return $qlist;
3517
}
3518

    
3519
function &get_unique_dnqueue_list() {
3520
	global $dummynet_pipe_list;
3521
	
3522
	$qlist = array();
3523
	if (is_array($dummynet_pipe_list)) {
3524
		foreach ($dummynet_pipe_list as $dn) {
3525
			$tmplist =& $dn->get_queue_list();
3526
			foreach ($tmplist as $qname => $link)
3527
				$qlist[$qname] = $link;	
3528
		}
3529
	}
3530
	return $qlist;
3531
}
3532

    
3533
function ref_on_altq_queue_list($parent, $qname) {
3534
	if (isset($GLOBALS['queue_list'][$qname]))
3535
		$GLOBALS['queue_list'][$qname]++;
3536
	else
3537
		$GLOBALS['queue_list'][$qname] = 1;
3538

    
3539
	unref_on_altq_queue_list($parent);
3540
}
3541

    
3542
function unref_on_altq_queue_list($qname) {
3543
	$GLOBALS['queue_list'][$qname]--;
3544
	if ($GLOBALS['queue_list'][$qname] <= 1)
3545
		unset($GLOBALS['queue_list'][$qname]);	
3546
}
3547

    
3548
function read_altq_config() {
3549
	global $altq_list_queues, $config;
3550
	$path = array();
3551
	
3552
	$a_int = &$config['shaper']['queue'];
3553

    
3554
	$altq_list_queues = array();
3555
	
3556
	if (!is_array($config['shaper']['queue']))
3557
		return;
3558

    
3559
	foreach ($a_int as $key => $conf) {
3560
				$int = $conf['interface'];
3561
				$root =& new altq_root_queue();
3562
				$root->SetInterface($int);
3563
				$altq_list_queues[$root->GetInterface()] = &$root;
3564
				$root->ReadConfig($conf);
3565
		array_push($path, $key);
3566
		$root->SetLink($path);
3567
		if (is_array($conf['queue'])) {
3568
			foreach ($conf['queue'] as $key1 => $q) {
3569
				array_push($path, $key1);
3570
				/* 
3571
				 * XXX: we compeletely ignore errors here but anyway we must have 
3572
				 *	checked them before so no harm should be come from this.
3573
				 */
3574
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3575
				array_pop($path);
3576
			} 	
3577
				}
3578
		array_pop($path);
3579
	}
3580
}
3581

    
3582
function read_dummynet_config() {
3583
	global $dummynet_pipe_list, $config;
3584
	$path = array();
3585
	$dnqueuenumber = 1;
3586
	$dnpipenumber = 1;
3587

    
3588
	$a_int = &$config['dnshaper']['queue'];
3589

    
3590
	$dummynet_pipe_list = array();
3591
	
3592
	if (!is_array($config['dnshaper']['queue'])
3593
		|| !count($config['dnshaper']['queue']))
3594
		return;
3595

    
3596
	foreach ($a_int as $key => $conf) {
3597
		if (empty($conf['name']))
3598
			continue; /* XXX: grrrrrr at php */ 
3599
		$root =& new dnpipe_class();
3600
		$root->ReadConfig($conf);
3601
		$root->SetNumber($dnpipenumber);	
3602
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3603
		array_push($path, $key);
3604
		$root->SetLink($path);
3605
		if (is_array($conf['queue'])) {
3606
			foreach ($conf['queue'] as $key1 => $q) {
3607
				array_push($path, $key1);
3608
				/* XXX: We cheat a little here till a better way is found. */
3609
				$q['number'] = $dnqueuenumber;
3610
				/* 
3611
				 * XXX: we compeletely ignore errors here but anyway we must have 
3612
				 *	checked them before so no harm should be come from this.
3613
				 */	
3614
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3615
				array_pop($path);
3616

    
3617
				$dnqueuenumber++;
3618
			} 	
3619
		}
3620
		array_pop($path);
3621
			
3622
		$dnpipenumber++;
3623
	}
3624
}
3625

    
3626
function get_interface_list_to_show() {
3627
	global $altq_list_queues, $config;
3628
	global $shaperIFlist;
3629

    
3630
	$tree = "";
3631
	foreach ($shaperIFlist as $shif => $shDescr) {
3632
		if ($altq_list_queues[$shif]) {
3633
			continue;
3634
		} else  {
3635
			if (!is_altq_capable(get_real_interface($shif)))
3636
				continue;
3637
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3638
		}
3639
	}
3640
	
3641
	return $tree;
3642
}
3643

    
3644
function filter_generate_altq_queues() {
3645
	global $altq_list_queues;
3646
	
3647
	read_altq_config();
3648

    
3649
	$altq_rules = "";
3650
	foreach ($altq_list_queues as $altq) 
3651
		$altq_rules .= $altq->build_rules();
3652

    
3653
	return $altq_rules;
3654
}
3655

    
3656
function filter_generate_dummynet_rules() {
3657
	global $dummynet_pipe_list;
3658
	
3659
	read_dummynet_config();
3660
	
3661
	if (!empty($dummynet_pipe_list)) {
3662
		if (!is_module_loaded("dummynet.ko"))
3663
			mwexec("/sbin/kldload dummynet");
3664
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
3665
		//mwexec("pfctl -F dummynet");
3666
	}
3667

    
3668
	$dn_rules = "";
3669
	foreach ($dummynet_pipe_list as $dn) 
3670
		$dn_rules .= $dn->build_rules();
3671

    
3672
	return $dn_rules;
3673
}
3674

    
3675
function build_iface_without_this_queue($iface, $qname) {
3676
	global $g, $altq_list_queues;
3677

    
3678
	$altq =& $altq_list_queues[$iface];
3679
				if ($altq)
3680
						$scheduler = ": " . $altq->GetScheduler();
3681
	$form = "<tr><td width=\"20%\" >";
3682
	$form .= "<a href=\"firewall_shaper.php?interface" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
3683
		$form .= "</td></tr>";
3684
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
3685
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
3686
		$form .= $iface . "&queue=". $qname . "&action=add\">";
3687
		$form .= "<img src=\"";
3688
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
3689
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
3690
		$form .= " Clone shaper/queue on this interface</a></td></tr>";
3691

    
3692
		return $form;
3693

    
3694
}
3695

    
3696

    
3697
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3698
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the pfSense Traffic Shaper.</b><br />";
3699
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3700
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3701
$default_shaper_msg .= " </p></strong></span>";
3702
$default_shaper_msg .= "</td></tr>";
3703

    
3704
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3705
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the pfSense Traffic Shaper.</b><br />";
3706
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3707
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3708
$dn_default_shaper_msg .= " </p></strong></span>";
3709
$dn_default_shaper_msg .= "</td></tr>";
3710

    
3711

    
3712

    
3713
?>
(31-31/42)