Project

General

Profile

Download (109 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
	foreach ($config['interfaces'] as $if => $ifdata) {
204
			if ($ifdata['ftpqueue'] == $queue) {
205
				unset($config['interfaces'][$if]['ftpqueue']);
206
				break;
207
			}
208
	}
209
}
210

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

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

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

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

    
333

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

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

    
378

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
588
			return $form;
589

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

    
669

    
670
		return $form;
671
	}
672

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

    
695
}
696

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

    
716
	/* This is here to help on form building and building rules/lists */
717
		var $subqueues = array();
718

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

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

    
839
		$javascript .= "function myResume() {\n";
840
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
841
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
842
		$javascript .= "else if (document.all)\n";
843
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
844
		$javascript .= "}\n";
845
		$javascript .= "</script>";
846
		
847
		return $javascript;
848
	}
849
	
850
	/* 
851
	 * Currently this will not be called unless we decide to clonce whole 
852
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
853
	 */
854
	 function copy_queue($interface, &$cflink) {
855

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

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

    
875
	 }
876

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

    
885

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

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

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

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

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

    
964
		}
965

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

    
983
			$tree .= "</li>"; 
984

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

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

    
1097
		return $form;
1098
		}
1099

    
1100
	function build_shortform() {
1101
		/* XXX: Hacks in site. Mostly layer violations!  */
1102
		global $g, $altq_list_queues;
1103

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

    
1134
	}
1135

    
1136
		function update_altq_queue_data(&$q) { 
1137
		$this->ReadConfig($q);
1138
	}
1139

    
1140
		function wconfig() {
1141
			$cflink =& get_reference_to_me_in_config($this->GetLink());
1142
		if (!is_array($cflink))
1143
			$cflink = array();
1144
		$cflink['name'] = $this->GetQname();
1145
				$cflink['interface'] = $this->GetInterface();
1146
				$cflink['qlimit'] = $this->GetQlimit();
1147
				$cflink['priority'] = $this->GetQpriority();
1148
		$cflink['description'] = $this->GetDescription();
1149
		$cflink['enabled'] = $this->GetEnabled();
1150
		$cflink['default'] = $this->GetDefault();
1151
		$cflink['red'] = $this->GetRed();
1152
		$cflink['rio'] = $this->GetRio();
1153
		$cflink['ecn'] = $this->GetEcn();
1154
	}
1155
}
1156

    
1157
class hfsc_queue extends priq_queue {
1158
		/* realtime */
1159
	var $realtime;
1160
		var $r_m1;
1161
		var $r_d;
1162
		var $r_m2;
1163
		/* linkshare */
1164
	var $linkshare;
1165
		var $l_m1;
1166
		var $l_d;
1167
		var $l_m2;
1168
		/* upperlimit */
1169
	var $upperlimit;
1170
		var $u_m1;
1171
		var $u_d;
1172
		var $u_m2;
1173

    
1174
		/*
1175
		 * HFSC can have nested queues.
1176
		 */
1177

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

    
1263

    
1264

    
1265
		function &add_queue($interface, &$qname, &$path, &$input_errors) {
1266

    
1267
			if (!is_array($this->subqueues))
1268
							$this->subqueues = array();
1269
			$q =& new hfsc_queue();
1270
			$q->SetInterface($this->GetInterface());
1271
			$q->SetParent(&$this);
1272
			$q->ReadConfig($qname);
1273
			$q->validate_input($qname, $input_errors);
1274
			if (count($input_errors)) {
1275
				return $q;
1276
			}
1277
			
1278
			$q->SetEnabled("on");
1279
			$q->SetLink($path);
1280
			switch ($q->GetBwscale()) {
1281
                        case "%":
1282
                                $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1283
                                break;
1284
                        default:
1285
                                $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1286
                                break;
1287
                	}
1288
                        $q->SetAvailableBandwidth($myBw);
1289
                        $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1290

    
1291
			$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1292
			ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1293
			if (is_array($qname['queue'])) {
1294
				foreach ($qname['queue'] as $key1 => $que) {
1295
					array_push($path, $key1);
1296
								$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1297
					array_pop($path);
1298
				}
1299
					}
1300
	
1301
			return $q;
1302
		}
1303

    
1304
 	        function copy_queue($interface, &$cflink) {
1305

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

    
1352
	                if (is_array($this->subqueues)) {
1353
        	                $cflinkp['queue'] = array();
1354
                	        foreach ($this->subqueues as $q) {
1355
                	                 $cflink['queue'][$q->GetQname()] = array();
1356
        	                        $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1357
				}
1358
                	}
1359

    
1360
         	}
1361

    
1362
		function delete_queue() { 
1363
			unref_on_altq_queue_list($this->GetQname());
1364
			if ($this->GetDefault()) 
1365
				altq_set_default_queue($this->GetInterface(), "false");
1366
			cleanup_queue_from_rules($this->GetQname());
1367
			$parent =& $this->GetParent();
1368
			foreach ($this->subqueues as $q)  {
1369
			$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1370
				$q->delete_queue();
1371
			}
1372
			unset_object_by_reference($this->GetLink());
1373
			}
1374
	
1375
			/*
1376
			 * Should search even its childs
1377
			 */
1378
			function &find_queue($interface, $qname) {
1379
					if ($qname == $this->GetQname()) 
1380
							return $this;
1381
		
1382
					foreach ($this->subqueues as $q) {
1383
							$result =& $q->find_queue("", $qname);
1384
				if ($result)
1385
									return $result;
1386
					}
1387
			}
1388

    
1389
	function &find_parentqueue($interface, $qname) {
1390
		if ($this->subqueues[$qname]) 
1391
			return $this;
1392
				foreach ($this->subqueues as $q) {
1393
					$result = $q->find_parentqueue("", $qname);
1394
			if ($result)
1395
				return $result;
1396
		}
1397
		}
1398
	
1399
	function validate_input($data, &$input_errors) {
1400
		parent::validate_input($data, $input_errors);
1401
		
1402
		$reqfields[] = "bandwidth";
1403
		$reqdfieldsn[] = "Bandwidth";
1404
		$reqfields[] = "bandwidthtype";
1405
		$reqdfieldsn[] = "Bandwidthtype";
1406

    
1407
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1408
		
1409
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1410
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1411
                        $input_errors[] = "Bandwidth must be an integer.";
1412

    
1413
                if ($data['bandwidth'] < 0)
1414
                        $input_errors[] = "Bandwidth cannot be negative.";
1415

    
1416
                if ($data['bandwidthtype'] == "%") {
1417
                 if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1418
                       $input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1419
                 }
1420
/*
1421
                $parent =& $this->GetParent();
1422
                switch ($data['bandwidthtype']) {
1423
                       case "%":
1424
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1425
                       default:
1426
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1427
                             break;
1428
                }
1429
                if ($parent->GetAvailableBandwidth() < $myBw)
1430
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
1431
*/
1432
                if ($data['priority'] > 7)
1433
                        $input_errors[] = "Priority must be an integer between 1 and 7.";
1434
		}
1435

    
1436
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1437
			$input_errors[] = ("upperlimit service curve defined but missing (d) value");
1438
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1439
			$input_errors[] = ("upperlimit service curve defined but missing initial bandwidth (m1) value");
1440
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1441
			$input_errors[] = ("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1442
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1443
			$input_errors[] = ("upperlimit d value needs to be numeric");
1444
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1445
			$input_errors[] = ("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1446
/*
1447

    
1448
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1449
		$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1450
		$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1451
		if (floatval($bw_1) < floatval($bw_2)) 
1452
			$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1453

    
1454
		
1455
		if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1456
			$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1457
		}
1458
*/
1459
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1460
			$input_errors[] = ("linkshare service curve defined but missing (d) value");
1461
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1462
			$input_errors[] = ("linkshare service curve defined but missing initial bandwidth (m1) value");
1463
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1464
			$input_errors[] = ("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1465
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1466
			$input_errors[] = ("linkshare d value needs to be numeric");
1467
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1468
			$input_errors[] = ("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1469
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1470
			$input_errors[] = ("realtime service curve defined but missing (d) value");
1471
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1472
			$input_errors[] = ("realtime service curve defined but missing initial bandwidth (m1) value");
1473

    
1474
/*
1475
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1476
		$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1477
                $bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1478
                if (floatval($bw_1) < floatval($bw_2))
1479
                        $input_errors[] = ("linkshare m1 cannot be smaller than m2");
1480

    
1481

    
1482
                if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1483
                        $input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1484
		}
1485
*/
1486

    
1487
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1488
			$input_errors[] = ("realtime m1 value needs to be Kb, Mb, Gb, or %");
1489
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1490
			$input_errors[] = ("realtime d value needs to be numeric");
1491
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1492
			$input_errors[] = ("realtime m2 value needs to be Kb, Mb, Gb, or %");
1493

    
1494
/*
1495
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1496
		$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1497
                $bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1498
                if (floatval($bw_1) < floatval($bw_2))
1499
                        $input_errors[] = ("realtime m1 cannot be smaller than m2");
1500

    
1501

    
1502
                if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1503
                        $input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1504
		}
1505
*/
1506

    
1507
	}
1508

    
1509
		function ReadConfig(&$cflink) {
1510
		if (isset($cflink['linkshare']) && $cflink['linkshare'] <> "") {
1511
			if (isset($cflink['linkshare1']) && $cflink['linkshare1'] <> "") {
1512
				$this->SetL_m1($cflink['linkshare1']);
1513
                                $this->SetL_d($cflink['linkshare2']);
1514
				$this->SetLinkshare();
1515
			}
1516
			if (isset($cflink['linkshare3']) && $cflink['linkshare3'] <> "") {
1517
                                $this->SetL_m2($cflink['linkshare3']);
1518
				$this->SetLinkshare();
1519
			}
1520
		} else $this->DisableLinkshare();
1521
		if (isset($cflink['realtime']) && $cflink['realtime'] <> "") {
1522
                        if (isset($cflink['realtime1']) && $cflink['realtime1'] <> "") {
1523
                                $this->SetR_m1($cflink['realtime1']);
1524
                                $this->SetR_d($cflink['realtime2']);
1525
				$this->SetRealtime();
1526
			}
1527
                        if (isset($cflink['realtime3']) && $cflink['realtime3'] <> "") {
1528
                                $this->SetR_m2($cflink['realtime3']);
1529
				$this->SetRealtime();
1530
			}
1531
		} else $this->DisableRealtime(); 
1532
		if (isset($cflink['upperlimit']) && $cflink['upperlimit'] <> "") {
1533
                        if (isset($cflink['upperlimit1']) && $cflink['upperlimit1'] <> "") {
1534
                                $this->SetU_m1($cflink['upperlimit1']);
1535
                                $this->SetU_d($cflink['upperlimit2']);
1536
				$this->SetUpperlimit();
1537
			}
1538
                        if (isset($cflink['upperlimit3']) && $cflink['upperlimit3'] <> "") {
1539
                                $this->SetU_m2($cflink['upperlimit3']);
1540
				$this->SetUpperlimit();
1541
			}
1542
		} else $this->DisableUpperlimit();
1543
		parent::ReadConfig($cflink);
1544

    
1545
		}
1546

    
1547
	function build_tree() {
1548
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1549
		$tree .= "\" ";
1550
		if ($this->GetDefault())
1551
								$tree .= " class=\"navlnk\"";
1552
		$tree .= " >" . $this->GetQname() . "</a>";
1553
		if (is_array($this->subqueues)) {
1554
			$tree .= "<ul>";
1555
			foreach ($this->subqueues as $q)  {
1556
				$tree .= $q->build_tree();
1557
			}	
1558
			$tree .= "</ul>";
1559
		}
1560
		$tree .= "</li>";
1561
		return $tree;
1562
	}
1563

    
1564
		/* Even this should take childs in consideration */
1565
		function build_rules() {
1566

    
1567
				$pfq_rule = " queue ". $this->qname;
1568
				if ($this->GetInterface())
1569
						$pfq_rule .= " on ".get_real_wan_interface($this->GetInterface());
1570
		if ($this->GetBandwidth() && $this->GetBwscale())
1571
						$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1572
					
1573
				if ($this->GetQpriority())
1574
						$pfq_rule .= " priority " . $this->GetQpriority();
1575
				if ($this->GetQlimit())
1576
						$pfq_rule .= " qlimit " . $this->GetQlimit();
1577
		  if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1578
						$pfq_rule .= " hfsc ( ";
1579
						if ($this->GetRed()) {
1580
								$comma = 1;
1581
								$pfq_rule .= " red ";
1582
						}
1583
						if ($this->GetRio()) {
1584
								if ($comma) 
1585
										$pfq_rule .= " ,";
1586
								$comma = 1;
1587
								$pfq_rule .= " rio ";
1588
						}
1589
						if ($this->GetEcn()) {
1590
								if ($comma) 
1591
										$pfq_rule .= " ,";
1592
								$comma = 1;
1593
								$pfq_rule .= " ecn ";
1594
						}
1595
						if ($this->GetDefault()) {
1596
								if ($comma)
1597
										$pfq_rule .= " ,";
1598
								$comma = 1;
1599
								$pfq_rule .= " default ";
1600
						}
1601

    
1602
						if ($this->GetRealtime() <> "")  {
1603
				if ($comma) 
1604
									$pfq_rule .= " , ";
1605
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1606
			$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1607
				else  if ($this->GetR_m2() <> "")
1608
					$pfq_rule .= " realtime " . $this->GetR_m2();
1609
				$comma = 1;
1610
			}
1611
						if ($this->GetLinkshare() <> "") {
1612
								if ($comma)
1613
					$pfq_rule .= " ,";
1614
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1615
			$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1616
				else if ($this->GetL_m2() <> "")
1617
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1618
				$comma = 1;
1619
			}
1620
						if ($this->GetUpperlimit() <> "") {
1621
				if ($comma)
1622
					$pfq_rule .= " ,";
1623
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1624
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1625
				else if ($this->GetU_m2() <> "")
1626
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1627
			}
1628
					$pfq_rule .= " ) ";
1629
					}
1630
					if (count($this->subqueues)) {
1631
						$i = count($this->subqueues);
1632
						$pfq_rule .= " { ";
1633
						foreach ($this->subqueues as $qkey => $qnone) {
1634
								if ($i > 1) {
1635
										$i--;
1636
										$pfq_rule .= " {$qkey}, ";
1637
								} else
1638
										$pfq_rule .= " {$qkey} ";
1639
						}
1640
								$pfq_rule .= " } \n";
1641
								foreach ($this->subqueues as $q)
1642
									$pfq_rule .= $q->build_rules();
1643
					}
1644

    
1645
				 $pfq_rule .= " \n";
1646
			
1647
				return $pfq_rule;
1648
		}
1649

    
1650
	function build_javascript() {
1651
		$javascript = parent::build_javascript();
1652
		$javascript .= "<script type=\"text/javascript\">";
1653
		$javascript .= "function enable_realtime(enable_over) { \n";
1654
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1655
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1656
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1657
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1658
		$javascript .= " } else { \n";
1659
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1660
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1661
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1662
		$javascript .= " } \n";
1663
		$javascript .= " } \n";
1664
		$javascript .= "function enable_linkshare(enable_over) { \n";
1665
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1666
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1667
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1668
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1669
		$javascript .= " } else { \n";
1670
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1671
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1672
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1673
		$javascript .= " } \n";
1674
		$javascript .= " } \n";
1675
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1676
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1677
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1678
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1679
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1680
		$javascript .= " } else { \n";
1681
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1682
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1683
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1684
		$javascript .= " } \n";
1685
			
1686
		$javascript .= "} \n";
1687
		$javascript .= "</script>";
1688

    
1689
		return $javascript;
1690
	}
1691

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

    
1784
				return $form;
1785
		}
1786

    
1787
	function update_altq_queue_data(&$data) { 
1788
		$this->ReadConfig($data);
1789
	}
1790

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

    
1843
class cbq_queue extends priq_queue {
1844
		var $qborrow;
1845

    
1846
	function GetBorrow() {
1847
		return $this->qborrow;
1848
	}
1849
	function SetBorrow($borrow) {
1850
		$this->qborrow = $borrow;
1851
	}
1852
	function CanHaveChilds() {
1853
			return true;
1854
	}
1855

    
1856
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1857

    
1858
		if (!is_array($this->subqueues))
1859
						$this->subqueues = array();
1860
		$q =& new cbq_queue();
1861
		$q->SetInterface($this->GetInterface());
1862
		$q->SetParent(&$this);
1863
		$q->ReadConfig($qname);
1864
                $q->validate_input($qname, $input_errors);
1865
                if (count($input_errors)) {
1866
                        return $q;
1867
                }
1868
                switch ($q->GetBwscale()) {
1869
                        case "%":
1870
                                $myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1871
                                break;
1872
                        default:
1873
                                $myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1874
                                break;
1875
                }
1876
                $q->SetAvailableBandwidth($myBw);
1877
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1878

    
1879
		$q->SetEnabled("on");
1880
		$q->SetLink($path);
1881
		$this->subqueues[$q->GetQName()] = &$q;
1882
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1883
		if (is_array($qname['queue'])) {
1884
				foreach ($qname['queue'] as $key1 => $que) {
1885
						array_push($path, $key1);
1886
						$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1887
						array_pop($path);
1888
				}
1889
		}
1890

    
1891
		return $q;
1892
		}
1893

    
1894
		function copy_queue($interface, &$cflink) {
1895

    
1896
                                $cflink['interface'] = $interface;
1897
                                $cflink['qlimit'] = $this->GetQlimit();
1898
                                $cflink['priority'] = $this->GetQpriority();
1899
                                $cflink['name'] = $this->GetQname();
1900
                                $cflink['description'] = $this->GetDescription();
1901
                                $cflink['bandwidth'] = $this->GetBandwidth();
1902
                                $cflink['bandwidthtype'] = $this->GetBwscale();
1903
                                $cflink['enabled'] = $this->GetEnabled();
1904
                                $cflink['default'] = $this->GetDefault();
1905
                                $cflink['red'] = $this->GetRed();
1906
                                $cflink['rio'] = $this->GetRio();
1907
                                $cflink['ecn'] = $this->GetEcn();
1908
                                $cflink['borrow'] = $this->GetBorrow();
1909
                		if (is_array($this->queues)) {
1910
 		                       $cflinkp['queue'] = array();
1911
                        		foreach ($this->subqueues as $q) {
1912
 		                                $cflink['queue'][$q->GetQname()] = array();
1913
                		                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1914
					}
1915
                		}
1916

    
1917
		}
1918
	
1919
		/*
1920
		 * Should search even its childs
1921
		 */
1922
		function &find_queue($interface, $qname) {
1923
				if ($qname == $this->GetQname())
1924
						return $this;
1925
				foreach ($this->subqueues as $q) {
1926
						$result =& $q->find_queue("", $qname);
1927
			if ($result)
1928
								return $result;
1929
				}
1930
		}
1931

    
1932
	function &find_parentqueue($interface, $qname) {
1933
				if ($this->subqueues[$qname])
1934
						return $this;
1935
				foreach ($this->subqueues as $q) {
1936
					$result = $q->find_parentqueue("", $qname);
1937
			if ($result)
1938
				return $result;
1939
		}
1940
		}
1941

    
1942
		function delete_queue() {
1943
			unref_on_altq_queue_list($this->GetQname());
1944
			if ($this->GetDefault())
1945
				altq_set_default_queue($this->GetInterface(), "false");
1946
			cleanup_queue_from_rules($this->GetQname());
1947
			foreach ($this->subqueues as $q) {
1948
			$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1949
				$q->delete_queue();
1950
			}
1951
			unset_object_by_reference($this->GetLink());
1952
		}
1953
	
1954
	function validate_input($data, &$input_errors) {
1955
		parent::validate_input($data, $input_errors);
1956
		
1957
		if ($data['priority'] > 7)
1958
				$input_errors[] = "Priority must be an integer between 1 and 7.";
1959
		$reqfields[] = "bandwidth";
1960
		$reqdfieldsn[] = "Bandwidth";
1961
		$reqfields[] = "bandwidthtype";
1962
		$reqdfieldsn[] = "Bandwidthtype";
1963

    
1964
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1965
		
1966
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
1967
                 $input_errors[] = "Bandwidth must be an integer.";
1968

    
1969

    
1970
           if ($data['bandwidth'] < 0)
1971
                       $input_errors[] = "Bandwidth cannot be negative.";
1972

    
1973

    
1974
           if ($data['bandwidthtype'] == "%") {
1975
                 if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1976
                       $input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
1977
           }
1978

    
1979
/*
1980
           $parent =& $this->GetParent();
1981
           switch ($data['bandwidthtype']) {
1982
                       case "%":
1983
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1984
                       default:
1985
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1986
                             break;
1987
           }
1988
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
1989
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
1990
*/
1991
	}
1992
		function ReadConfig(&$q) {
1993
				parent::ReadConfig($q);
1994
		if ($q['borrow'])
1995
			$this->SetBorrow("on");
1996
		}
1997
		
1998
	function build_javascript() {
1999
		return parent::build_javascript();
2000
	}
2001

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

    
2076
			$pfq_rule .= " \n";
2077
			return $pfq_rule;
2078
	}
2079

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

    
2118
		return $form;
2119
	}
2120

    
2121
	function update_altq_queue_data(&$data) { 
2122
		$this->ReadConfig($data);
2123
	}
2124

    
2125
	function wconfig() {
2126
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2127
				if (!is_array($cflink))
2128
						$cflink = array();
2129
				$cflink['interface'] = $this->GetInterface();
2130
				$cflink['qlimit'] = $this->GetQlimit();
2131
				$cflink['priority'] = $this->GetQpriority();
2132
				$cflink['name'] = $this->GetQname();
2133
				$cflink['description'] = $this->GetDescription();
2134
				$cflink['bandwidth'] = $this->GetBandwidth();
2135
				$cflink['bandwidthtype'] = $this->GetBwscale();
2136
				$cflink['enabled'] = $this->GetEnabled();
2137
				$cflink['default'] = $this->GetDefault();
2138
				$cflink['red'] = $this->GetRed();
2139
				$cflink['rio'] = $this->GetRio();
2140
				$cflink['ecn'] = $this->GetEcn();
2141
				$cflink['borrow'] = $this->GetBorrow();
2142
		}
2143
}
2144

    
2145
class fairq_queue extends priq_queue {
2146
		var $hogs;
2147
		var $buckets;
2148

    
2149
	function GetBuckets() {
2150
		return $this->buckets;
2151
	}
2152
	function SetBuckets($buckets) {
2153
		$this->buckets = $buckets;
2154
	}
2155
	function GetHogs() {
2156
		return $this->hogs;
2157
	}
2158
	function SetHogs($hogs) {
2159
		$this->hogs = $hogs;
2160
	}
2161
	function CanHaveChilds() {
2162
		return false;
2163
	}
2164

    
2165

    
2166
	function copy_queue($interface, &$cflink) {
2167
                $cflink['interface'] = $interface;
2168
                $cflink['qlimit'] = $this->GetQlimit();
2169
                $cflink['priority'] = $this->GetQpriority();
2170
                $cflink['name'] = $this->GetQname();
2171
                $cflink['description'] = $this->GetDescription();
2172
                $cflink['bandwidth'] = $this->GetBandwidth();
2173
                $cflink['bandwidthtype'] = $this->GetBwscale();
2174
                $cflink['enabled'] = $this->GetEnabled();
2175
                $cflink['default'] = $this->GetDefault();
2176
                $cflink['red'] = $this->GetRed();
2177
                $cflink['rio'] = $this->GetRio();
2178
                $cflink['ecn'] = $this->GetEcn();
2179
                $cflink['buckets'] = $this->GetBuckets();
2180
		$cflink['hogs'] = $this->GetHogs();
2181
	}
2182
	
2183
	/*
2184
	 * Should search even its childs
2185
	 */
2186
	function &find_queue($interface, $qname) {
2187
		if ($qname == $this->GetQname())
2188
			return $this;
2189
	}
2190

    
2191
	function find_parentqueue($interface, $qname) { return; }
2192

    
2193
	function delete_queue() {
2194
		unref_on_altq_queue_list($this->GetQname());
2195
		if ($this->GetDefault())
2196
			altq_set_default_queue($this->GetInterface(), "false");
2197
		cleanup_queue_from_rules($this->GetQname());
2198
		unset_object_by_reference($this->GetLink());
2199
	}
2200
	
2201
	function validate_input($data, &$input_errors) {
2202
		parent::validate_input($data, $input_errors);
2203
		
2204
		if ($data['priority'] > 255)
2205
				$input_errors[] = "Priority must be an integer between 1 and 255.";
2206
		$reqfields[] = "bandwidth";
2207
		$reqdfieldsn[] = "Bandwidth";
2208
		$reqfields[] = "bandwidthtype";
2209
		$reqdfieldsn[] = "Bandwidthtype";
2210

    
2211
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2212
		
2213
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2214
	                 $input_errors[] = "Bandwidth must be an integer.";
2215

    
2216

    
2217
	        if ($data['bandwidth'] < 0)
2218
                       $input_errors[] = "Bandwidth cannot be negative.";
2219

    
2220

    
2221
        	if ($data['bandwidthtype'] == "%") {
2222
                	if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2223
                       		$input_errors[] = "Bandwidth in percentage should be between 1 and 100 bounds.";
2224
           	}
2225

    
2226
/*
2227
           	$parent =& $this->GetParent();
2228
           	switch ($data['bandwidthtype']) {
2229
                       case "%":
2230
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2231
                       default:
2232
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2233
                             break;
2234
           	}
2235
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2236
                        $input_errors[] = "The sum of child bandwidths exceeds that of the parent.";
2237
*/
2238
	}
2239
	
2240
	function ReadConfig(&$q) {
2241
		parent::ReadConfig($q);
2242
		if ($q['buckets'])
2243
			$this->SetBuckets($q['buckets']);
2244
		if ($q['hogs'] && is_valid_shaperbw($q['hogs']))
2245
			$this->SetHogs($q['hogs']);
2246
	}
2247
		
2248
	function build_javascript() {
2249
		return parent::build_javascript();
2250
	}
2251

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

    
2312
		$pfq_rule .= " \n";
2313
		return $pfq_rule;
2314
	}
2315

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

    
2362
	function update_altq_queue_data(&$data) { 
2363
		$this->ReadConfig($data);
2364
	}
2365

    
2366
	function wconfig() {
2367
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2368
		if (!is_array($cflink))
2369
			$cflink = array();
2370
		$cflink['interface'] = $this->GetInterface();
2371
		$cflink['qlimit'] = $this->GetQlimit();
2372
		$cflink['priority'] = $this->GetQpriority();
2373
		$cflink['name'] = $this->GetQname();
2374
		$cflink['description'] = $this->GetDescription();
2375
		$cflink['bandwidth'] = $this->GetBandwidth();
2376
		$cflink['bandwidthtype'] = $this->GetBwscale();
2377
		$cflink['enabled'] = $this->GetEnabled();
2378
		$cflink['default'] = $this->GetDefault();
2379
		$cflink['red'] = $this->GetRed();
2380
		$cflink['rio'] = $this->GetRio();
2381
		$cflink['ecn'] = $this->GetEcn();
2382
		$cflink['buckets'] = $this->GetBuckets();
2383
		$cflink['hogs'] = $this->GetHogs();
2384
	}
2385
}
2386

    
2387

    
2388
/*
2389
 * XXX: TODO Link dummynet(4) in the system. 
2390
 */
2391

    
2392

    
2393
/*
2394
 * List of respective objects!
2395
 */
2396
$dummynet_pipe_list = array();
2397

    
2398
class dummynet_class {
2399
        var $qname;
2400
		var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2401
        var $qlimit;
2402
        var $description;
2403
		var $qenabled;
2404
		var $link;
2405
		var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2406
        var $plr;
2407

    
2408
        var $buckets;
2409
        /* mask parameters */
2410
        var $mask;
2411
        var $noerror;
2412

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

    
2487
		function build_javascript() { return; } /* Do not remove */
2488

    
2489
		function validate_input($data, &$input_errors) {
2490
			$reqfields[] = "bandwidth";
2491
			$reqdfieldsn[] = "Bandwidth";
2492
			$reqfields[] = "bandwidthtype";
2493
			$reqdfieldsn[] = "Bandwidthtype";
2494
			$reqfields[] = "name";
2495
			$reqfieldsn[] = "Name";
2496
		
2497
			shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2498

    
2499
			if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2500
					($data['plr'] <= 0 && $data['plr'] > 1))) 
2501
            	$input_errors[] = "Plr must be an integer between 1 and 100.";
2502
			if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2503
					($data['buckets'] < 1 && $data['buckets'] > 100)) 
2504
            	$input_errors[] = "Buckets must be an integer between 16 and 65535.";
2505
			if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2506
            	$input_errors[] = "Queue limit must be an integer";
2507
        	if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2508
               	 $input_errors[] = "Queue names must be alphanumeric and _ or - only.";
2509
		}
2510
}
2511

    
2512
class dnpipe_class extends dummynet_class {
2513
        var $pipe_nr;
2514
        var $delay;
2515
	var $qbandwidth;
2516
	var $qbandwidthtype;
2517

    
2518
		/* This is here to help on form building and building rules/lists */
2519
        var $subqueues = array();
2520

    
2521
	function CanHaveChilds() {
2522
	        return true;
2523
        }
2524
	function SetDelay($delay) {
2525
		$this->delay = $delay;
2526
	}
2527
	function GetDelay() {
2528
		return $this->delay;
2529
	}
2530
	function GetBwscale() {
2531
                return $this->qbandwidthtype;
2532
        }
2533
        function SetBwscale($scale) {
2534
               	$this->qbandwidthtype = $scale;
2535
        }		
2536
	function delete_queue() {
2537
		cleanup_dnqueue_from_rules($this->GetQname());
2538
		foreach ($this->subqueues as $q)
2539
			$q->delete_queue();
2540
		unset_dn_object_by_reference($this->GetLink());
2541
        }
2542
        function GetBandwidth() {
2543
                return $this->qbandwidth;
2544
        }
2545
        function SetBandwidth($bandwidth) {
2546
                $this->qbandwidth = $bandwidth;
2547
        }
2548

    
2549
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2550

    
2551
		if (!is_array($this->subqueues))
2552
			$this->subqueues = array();
2553
			
2554
		$q =& new dnqueue_class();
2555
		$q->SetLink($path);
2556
		$q->SetEnabled("on");
2557
		$q->SetPipe($this->GetQname());
2558
		$q->SetParent(&$this);
2559
		$q->ReadConfig($queue);
2560
		$q->validate_input($queue, $input_errors);
2561
		if (count($input_errors))
2562
			return $q;
2563
		$this->subqueues[$q->GetQname()] = &$q;
2564
            
2565
		return $q;
2566
	}
2567

    
2568
	function &get_queue_list($q = null) {
2569
		$qlist = array();
2570

    
2571
		$qlist[$this->GetQname()] = $this->GetNumber();
2572
		if (is_array($this->subqueues)) {
2573
			foreach ($this->subqueues as $queue)
2574
				$queue->get_queue_list(&$qlist);
2575
		}
2576
		return $qlist;
2577
	}
2578
		
2579
        /*
2580
         * Should search even its childs
2581
         */
2582
        function &find_queue($pipe, $qname) {
2583
                if ($qname == $this->GetQname()) 
2584
                        return $this;
2585
               	foreach ($this->subqueues as $q) {
2586
                       	$result =& $q->find_queue("", $qname);
2587
						if ($result)
2588
                       	        return $result;
2589
               	}
2590
        }
2591

    
2592
	function &find_parentqueue($pipe, $qname) {
2593
		return NULL;
2594
       	}
2595

    
2596
	function validate_input($data, &$input_errors) {
2597
		parent::validate_input($data, $input_errors);
2598

    
2599
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2600
       		     	$input_errors[] = "Bandwidth must be an integer.";
2601
		if ($data['delay'] && (!is_numeric($data['delay'])))
2602
            		$input_errors[] = "Delay must be an integer.";
2603
		}
2604

    
2605
	function ReadConfig(&$q) {
2606
           	$this->SetQname($q['name']);
2607
		$this->SetNumber($q['number']);
2608
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2609
			$this->SetBandwidth($q['bandwidth']);
2610
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2611
				$this->SetBwscale($q['bandwidthtype']);
2612
		}
2613
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2614
              		$this->SetQlimit($q['qlimit']);
2615
		if (isset($q['mask']) && $q['mask'] <> "")
2616
              		$this->SetMask($q['mask']);
2617
		if (isset($q['buckets']) && $q['buckets'] <> "")
2618
              		$this->SetBuckets($q['buckets']);
2619
            	if (isset($q['plr']) && $q['plr'] <> "")
2620
            		$this->SetPlr($q['plr']);
2621
		if (isset($q['delay']) && $q['delay'] <> "")
2622
            		$this->SetDelay($q['delay']);
2623
            	if (isset($q['description']) && $q['description'] <> "")
2624
			$this->SetDescription($q['description']);
2625
		$this->SetEnabled($q['enabled']);
2626

    
2627
        }
2628

    
2629
	function build_tree() {
2630
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2631
		$tree .= $this->GetQname() . "</a>";
2632
		if (is_array($this->subqueues)) {
2633
			$tree .= "<ul>";
2634
			foreach ($this->subqueues as $q)  {
2635
				$tree .= $q->build_tree();
2636
			}	
2637
			$tree .= "</ul>";
2638
		}
2639
		$tree .= "</li>";
2640
		
2641
		return $tree;
2642
	}
2643

    
2644
        function build_rules() {
2645
		if ($this->GetEnabled() == "")
2646
			return;
2647

    
2648
       		$pfq_rule = "\ndnpipe ". $this->GetNumber();
2649
		if ($this->GetBandwidth() && $this->GetBwscale())
2650
                    	$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2651
		if ($this->GetQlimit())
2652
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2653
		if ($this->GetPlr())
2654
			$pfq_rule .= " plr " . $this->GetPlr();
2655
		if ($this->GetBuckets())
2656
			$pfq_rule .= " buckets " . $this->GetBuckets();
2657
		if ($this->GetDelay())
2658
			$pfq_rule .= " delay " . $this->GetDelay();
2659

    
2660
		$mask = $this->GetMask();
2661
		if (!empty($mask)) {
2662
			/* XXX TODO extend this to support more complicated masks */
2663
			switch ($mask) {
2664
			case 'srcaddress':
2665
				$pfq_rule .= " mask src-ip 0xffffffff ";
2666
				break;
2667
			case 'dstaddress':
2668
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2669
				break;
2670
			default:
2671
				break;
2672
			}
2673
			$pfq_rule .= "\n";
2674

    
2675
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2676
       			        foreach ($this->subqueues as $q)
2677
				$pfq_rule .= $q->build_rules();
2678
               		}
2679
    		}            
2680
		$pfq_rule .= " \n";
2681

    
2682
		return $pfq_rule;
2683
        }
2684

    
2685
	function update_dn_data(&$data) { 
2686
		$this->ReadConfig($data);
2687
	}
2688

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

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

    
2795
		return $form;
2796
			
2797
		}
2798

    
2799
	function wconfig() {
2800
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
2801
            	if (!is_array($cflink))
2802
            		$cflink = array();
2803
		$cflink['name'] = $this->GetQname();
2804
		$cflink['number'] = $this->GetNumber();
2805
            	$cflink['qlimit'] = $this->GetQlimit();
2806
            	$cflink['plr'] = $this->GetPlr();
2807
            	$cflink['description'] = $this->GetDescription();
2808
		$cflink['bandwidth'] = $this->GetBandwidth();
2809
            	$cflink['bandwidthtype'] = $this->GetBwscale();
2810
		$cflink['enabled'] = $this->GetEnabled();
2811
		$cflink['buckets'] = $this->GetBuckets();
2812
		$cflink['mask'] = $this->GetMask();
2813
		$cflink['delay'] = $this->GetDelay();
2814
	}
2815

    
2816
}
2817

    
2818
class dnqueue_class extends dummynet_class {
2819
        var $pipeparent;
2820
        var $weight;
2821

    
2822
        function GetWeight() {
2823
                return $this->weight;
2824
        }
2825
        function SetWeight($weight) {
2826
                $this->weight = $weight;
2827
        }
2828
	function GetPipe() {
2829
		return $this->pipeparent;
2830
	}
2831
	function SetPipe($pipe) {
2832
		$this->pipeparent = $pipe;
2833
	}
2834

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

    
2838
	function delete_queue() {
2839
		cleanup_dnqueue_from_rules($this->GetQname());
2840
		unset_dn_object_by_reference($this->GetLink());
2841
        }
2842

    
2843
	function validate_input($data, &$input_errors) {
2844
		parent::validate_input($data, $input_errors);
2845

    
2846
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
2847
			($data['weight'] < 1 && $data['weight'] > 100))) 
2848
       		     	$input_errors[] = "Weight must be an integer between 1 and 100.";
2849
	}
2850

    
2851
        /*
2852
         * Should search even its childs
2853
         */
2854
        function &find_queue($pipe, $qname) {
2855
                if ($qname == $this->GetQname()) 
2856
                	return $this;
2857
		else
2858
			return NULL;
2859
        }
2860

    
2861
	function &find_parentqueue($pipe, $qname) {
2862
		return $this->qparent;
2863
        }
2864

    
2865
        function &get_queue_list(&$qlist) {
2866
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
2867
        }		
2868

    
2869
	function ReadConfig(&$q) {
2870
          	$this->SetQname($q['name']);
2871
		$this->SetNumber($q['number']);
2872
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2873
       		       	$this->SetQlimit($q['qlimit']);
2874
		if (isset($q['mask']) && $q['mask'] <> "")
2875
              		$this->SetMask($q['mask']);
2876
       		if (isset($q['weight']) && $q['weight'] <> "")
2877
            		$this->SetWeight($q['weight']);
2878
            	if (isset($q['descritption']) && $q['description'] <> "")
2879
			$this->SetDescription($q['description']);
2880
		$this->SetEnabled($q['enabled']);
2881
        }
2882

    
2883
	function build_tree() {
2884
		$parent =& $this->GetParent();
2885
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
2886
		$tree .= $this->GetQname() . "</a>";
2887
		$tree .= "</li>";
2888
		
2889
		return $tree;
2890
	}
2891

    
2892
        function build_rules() {
2893
		if ($this->GetEnabled() == "")
2894
			return; 
2895

    
2896
		$parent =& $this->GetParent();
2897
            	$pfq_rule = "dnqueue ". $this->GetNumber() . " dnpipe " . $parent->GetNumber();
2898
		if ($this->GetQlimit())
2899
                    	$pfq_rule .= " queue " . $this->GetQimit();
2900
		if ($this->GetWeight())
2901
			$pfq_rule .= " weight " . $this->GetWeight();
2902
		if ($this->GetBuckets())
2903
			$pfq_rule .= " buckets " . $this->GetBuckets();
2904
		$mask = $this->GetMask();
2905
		if (!empty($mask)) {
2906
			/* XXX TODO extend this to support more complicated masks */
2907
			switch ($mask) {
2908
			case 'srcaddress':
2909
				$pfq_rule .= " mask src-ip 0xffffffff ";
2910
				break;
2911
			case 'dstaddress':
2912
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2913
				break;
2914
			default:
2915
				break;
2916
			}
2917
			$pfq_rule .= "\n";
2918
		}
2919

    
2920
		return $pfq_rule;
2921
	}
2922

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

    
3005
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3006
		$form .= " value=\"" . $this->GetPipe() . "\">";
3007

    
3008
		return $form;
3009
			
3010
	}
3011

    
3012
        function update_dn_data(&$data) { 
3013
		$this->ReadConfig($data);
3014
	}
3015

    
3016
	function wconfig() {
3017
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3018
            	if (!is_array($cflink))
3019
            		$cflink = array();
3020
		$cflink['name'] = $this->GetQname();
3021
		$cflink['number'] = $this->GetNumber();
3022
            	$cflink['qlimit'] = $this->GetQlimit();
3023
            	$cflink['description'] = $this->GetDescription();
3024
		$cflink['weight'] = $this->GetWeight();
3025
		$cflink['enabled'] = $this->GetEnabled();
3026
		$cflink['buckets'] = $this->GetBuckets();
3027
		$cflink['mask'] = $this->GetMask();
3028
	}
3029
}
3030

    
3031

    
3032
/*
3033
 * XXX: TODO Make a class shaper to hide all these function
3034
 * from the global namespace.
3035
 */
3036

    
3037
/* 
3038
 * This is a layer violation but for now there is no way 
3039
 * i can find to properly do this with PHP.
3040
 */
3041
function altq_set_default_queue($interface, $value) {
3042
	global $altq_list_queues;
3043
		
3044
	$altq_tmp =& $altq_list_queues[$interface];
3045
	if ($altq_tmp) {
3046
		if ($value) {
3047
			$altq_tmp->SetDefaultQueuePresent("true");
3048
		}
3049
		else {
3050
			$altq_tmp->SetDefaultQueuePresent("false");
3051
		}
3052
	}
3053
}
3054

    
3055
function altq_get_default_queue($interface) {
3056
	global $altq_list_queues;
3057

    
3058
	$altq_tmp = $altq_list_queues[$interface];
3059
	if ($altq_tmp)  
3060
		return $altq_tmp->GetDefaultQueuePresent(); 
3061
}
3062

    
3063
function altq_check_default_queues() {
3064
	global $altq_list_queues;
3065

    
3066
	$count = 0;
3067
	if (is_array($altq_list_queues)) {
3068
		foreach($altq_list_queues as $altq) {
3069
			if ($altq->GetDefaultQueuePresent())
3070
				$count++;
3071
		}
3072
	}
3073
	else  $count++;;
3074
	
3075
	return 0;
3076
}
3077

    
3078
function &get_unique_queue_list() {
3079
	global $altq_list_queues;
3080
	
3081
	$qlist = array();
3082
	if (is_array($altq_list_queues)) {
3083
		foreach ($altq_list_queues as $altq) {
3084
			$tmplist =& $altq->get_queue_list();
3085
			foreach ($tmplist as $qname => $link)
3086
				$qlist[$qname] = $link;	
3087
		}
3088
	}
3089
	return $qlist;
3090
}
3091

    
3092
function &get_unique_dnqueue_list() {
3093
	global $dummynet_pipe_list;
3094
	
3095
	$qlist = array();
3096
	if (is_array($dummynet_pipe_list)) {
3097
		foreach ($dummynet_pipe_list as $dn) {
3098
			$tmplist =& $dn->get_queue_list();
3099
			foreach ($tmplist as $qname => $link)
3100
				$qlist[$qname] = $link;	
3101
		}
3102
	}
3103
	return $qlist;
3104
}
3105

    
3106
function get_is_ftp_queue($interface, $qname) {
3107
	global $config;
3108

    
3109
	if (isset($config['interfaces'][$interface]['ftpqueue']) &&
3110
		$config['interfaces'][$interface]['ftpqueue'] == $qname)
3111
		return true;
3112
	return false;
3113
}
3114

    
3115
function set_is_ftp_queue($interface, $qname) {
3116
	global $config;
3117

    
3118
	if (!is_array($config['interfaces'][$interface]['ftpqueue']))
3119
		$config['interfaces'][$interface]['ftpqueue'] = array();
3120
	$config['interfaces'][$interface]['ftpqueue'] = $qname;
3121
}
3122

    
3123
function ref_on_altq_queue_list($parent, $qname) {
3124
	if (isset($GLOBALS['queue_list'][$qname]))
3125
		$GLOBALS['queue_list'][$qname]++;
3126
	else
3127
		$GLOBALS['queue_list'][$qname] = 1;
3128

    
3129
	unref_on_altq_queue_list($parent);
3130
}
3131

    
3132
function unref_on_altq_queue_list($qname) {
3133
	$GLOBALS['queue_list'][$qname]--;
3134
	if ($GLOBALS['queue_list'][$qname] <= 1)
3135
		unset($GLOBALS['queue_list'][$qname]);	
3136
}
3137

    
3138
function read_altq_config() {
3139
	global $altq_list_queues, $config;
3140
	$path = array();
3141
	
3142
	$a_int = &$config['shaper']['queue'];
3143

    
3144
	$altq_list_queues = array();
3145
	
3146
	if (!is_array($config['shaper']['queue']))
3147
		return;
3148

    
3149
	foreach ($a_int as $key => $conf) {
3150
				$int = $conf['interface'];
3151
				$root =& new altq_root_queue();
3152
				$root->SetInterface($int);
3153
				$altq_list_queues[$root->GetInterface()] = &$root;
3154
				$root->ReadConfig($conf);
3155
		array_push($path, $key);
3156
		$root->SetLink($path);
3157
		if (is_array($conf['queue'])) {
3158
			foreach ($conf['queue'] as $key1 => $q) {
3159
				array_push($path, $key1);
3160
				/* 
3161
				 * XXX: we compeletely ignore errors here but anyway we must have 
3162
				 *	checked them before so no harm should be come from this.
3163
				 */
3164
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3165
				array_pop($path);
3166
			} 	
3167
				}
3168
		array_pop($path);
3169
	}
3170
}
3171

    
3172
function read_dummynet_config() {
3173
	global $dummynet_pipe_list, $config;
3174
	$path = array();
3175
	$dnqueuenumber = 1;
3176
	$dnpipenumber = 1;
3177

    
3178
	$a_int = &$config['dnshaper']['queue'];
3179

    
3180
	$dummynet_pipe_list = array();
3181
	
3182
	if (!is_array($config['dnshaper']['queue'])
3183
		|| !count($config['dnshaper']['queue']))
3184
		return;
3185

    
3186
	foreach ($a_int as $key => $conf) {
3187
		if (empty($conf['name']))
3188
			continue; /* XXX: grrrrrr at php */ 
3189
		$root =& new dnpipe_class();
3190
		$root->ReadConfig($conf);
3191
		$root->SetNumber($dnpipenumber);	
3192
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3193
		array_push($path, $key);
3194
		$root->SetLink($path);
3195
		if (is_array($conf['queue'])) {
3196
			foreach ($conf['queue'] as $key1 => $q) {
3197
				array_push($path, $key1);
3198
				/* XXX: We cheat a little here till a better way is found. */
3199
				$q['number'] = $dnqueuenumber;
3200
				/* 
3201
				 * XXX: we compeletely ignore errors here but anyway we must have 
3202
				 *	checked them before so no harm should be come from this.
3203
				 */	
3204
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3205
				array_pop($path);
3206

    
3207
				$dnqueuenumber++;
3208
			} 	
3209
		}
3210
		array_pop($path);
3211
			
3212
		$dnpipenumber++;
3213
	}
3214
}
3215

    
3216
function get_interface_list_to_show() {
3217
	global $altq_list_queues, $config;
3218
		
3219
	$tree = "";
3220
	foreach ($config['interfaces'] as $if => $ifdesc) {
3221
		if ($altq_list_queues[$if]) {
3222
			continue;
3223
		} else  {
3224
			if (!is_altq_capable($ifdesc['if']))
3225
				continue;
3226
			if (!isset($ifdesc['enable']) && $if != "lan" && $if != "wan") 
3227
				continue;
3228
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$if."&action=add\">".$if."</a></li>";
3229
		}
3230
	}
3231
	
3232
	return $tree;
3233
}
3234

    
3235
function filter_generate_altq_queues() {
3236
	global $altq_list_queues;
3237
	
3238
	read_altq_config();
3239

    
3240
	$altq_rules = "";
3241
	foreach ($altq_list_queues as $altq) 
3242
		$altq_rules .= $altq->build_rules();
3243

    
3244
	return $altq_rules;
3245
}
3246

    
3247
function filter_generate_dummynet_rules() {
3248
	global $dummynet_pipe_list;
3249
	
3250
	read_dummynet_config();
3251
	
3252
	if (!empty($dummynet_pipe_list)) {
3253
		mwexec("kldload dummynet");
3254
		mwexec("pfctl -F dummynet");
3255
	}
3256

    
3257
	$dn_rules = "";
3258
	foreach ($dummynet_pipe_list as $dn) 
3259
		$dn_rules .= $dn->build_rules();
3260

    
3261
	return $dn_rules;
3262
}
3263

    
3264
function build_iface_without_this_queue($iface, $qname) {
3265
	global $g, $altq_list_queues;
3266

    
3267
	$altq =& $altq_list_queues[$iface];
3268
				if ($altq)
3269
						$scheduler = ": " . $altq->GetScheduler();
3270
	$form = "<tr><td width=\"20%\" >";
3271
	$form .= "<a href=\"firewall_shaper.php?interface" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
3272
		$form .= "</td></tr>";
3273
		$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
3274
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
3275
		$form .= $iface . "&queue=". $qname . "&action=add\">";
3276
		$form .= "<img src=\"";
3277
		$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
3278
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Clone shaper/queue on this interface\">";
3279
		$form .= " Clone shaper/queue on this interface</a></td></tr>";
3280

    
3281
		return $form;
3282

    
3283
}
3284

    
3285

    
3286
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3287
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the pfSense Traffic Shaper.</b><br />";
3288
$default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3289
$default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3290
$default_shaper_ms .= " </p></strong></span>";
3291
$default_shaper_msg .= "</td></tr>";
3292

    
3293
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3294
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>Welcome to the pfSense Traffic Shaper.</b><br />";
3295
$dn_default_shaper_msg .= "The tree on the left helps you navigate through the queues <br />";
3296
$dn_default_shaper_msg .= "buttons at the bottom represent queue actions and are activated accordingly.";
3297
$dn_default_shaper_ms .= " </p></strong></span>";
3298
$dn_default_shaper_msg .= "</td></tr>";
3299

    
3300

    
3301

    
3302
?>
(25-25/34)