Project

General

Profile

Download (127 KB) Statistics
| Branch: | Tag: | Revision:
1 061f78b1 Bill Marquette
<?php
2
/*
3 f5881023 Ermal Lu?i
	Copyright (C) 2008 Ermal Lu?i
4
	All rights reserved.
5
6
	Redistribution and use in source and binary forms, with or without
7
	modification, are permitted provided that the following conditions are met:
8
9
	1. Redistributions of source code must retain the above copyright notice,
10
	   this list of conditions and the following disclaimer.
11
12
	2. Redistributions in binary form must reproduce the above copyright
13
	   notice, this list of conditions and the following disclaimer in the
14
	   documentation and/or other materials provided with the distribution.
15
16
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
20
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
	POSSIBILITY OF SUCH DAMAGE.
26
27
	pfSense_BUILDER_BINARIES:	/bin/kill	/sbin/kldload	/bin/rm	/bin/ps
28
	pfSense_MODULE:	shaper
29 061f78b1 Bill Marquette
*/
30
31 f5881023 Ermal Lu?i
/* XXX: needs some reducing on include. */
32
/* include all configuration functions. */
33 061f78b1 Bill Marquette
require_once("functions.inc");
34
35 197bfe96 Ermal Luçi
/*
36
 * I admit :) this is derived from xmplparse.inc StartElement()
37
 */
38 d62ba478 Ermal Luçi
function &get_reference_to_me_in_config(&$mypath) 
39
{
40 197bfe96 Ermal Luçi
	global $config;
41
42 f5881023 Ermal Lu?i
	 $ptr =& $config['shaper'];
43 197bfe96 Ermal Luçi
	foreach ($mypath as $indeks) {
44 f5881023 Ermal Lu?i
		$ptr =& $ptr['queue'][$indeks];
45
	}
46 061f78b1 Bill Marquette
47 197bfe96 Ermal Luçi
	return $ptr;
48 061f78b1 Bill Marquette
}
49 d62ba478 Ermal Luçi
50
function unset_object_by_reference(&$mypath) 
51
{
52 197bfe96 Ermal Luçi
	global $config;
53 061f78b1 Bill Marquette
54 f5881023 Ermal Lu?i
	$ptr =& $config['shaper'];
55
	for ($i = 0; $i < count($mypath) - 1; $i++) {
56
		$ptr =& $ptr['queue'][$mypath[$i]];
57
	}
58 197bfe96 Ermal Luçi
	unset($ptr['queue'][$mypath[$i]]);
59
}
60 d62ba478 Ermal Luçi
61
function &get_dn_reference_to_me_in_config(&$mypath) 
62
{
63 c25a6b6a Ermal Luçi
	global $config;
64
65 f5881023 Ermal Lu?i
	$ptr =& $config['dnshaper'];
66 c25a6b6a Ermal Luçi
	foreach ($mypath as $indeks) {
67 f5881023 Ermal Lu?i
		$ptr =& $ptr['queue'][$indeks];
68
	}
69 c25a6b6a Ermal Luçi
70
	return $ptr;
71
}
72 d62ba478 Ermal Luçi
73
function unset_dn_object_by_reference(&$mypath) 
74
{
75 c25a6b6a Ermal Luçi
	global $config;
76
77 f5881023 Ermal Lu?i
	$ptr =& $config['dnshaper'];
78
	for ($i = 0; $i < count($mypath) - 1; $i++) {
79
		$ptr =& $ptr['queue'][$mypath[$i]];
80
	}
81 c25a6b6a Ermal Luçi
	unset($ptr['queue'][$mypath[$i]]);
82
}
83
84 d62ba478 Ermal Luçi
function clean_child_queues($type, $mypath) 
85
{
86 197bfe96 Ermal Luçi
	$ref = &get_reference_to_me_in_config($mypath);
87
88
	switch ($type) {
89
	case 'HFSC':
90 2b5caa0e Ermal Luçi
		if (isset($ref['borrow'])) unset($ref['borrow']);		
91
		if (isset($ref['hogs'])) unset($ref['hogs']);
92
		if (isset($ref['buckets'])) unset($ref['buckets']);
93 197bfe96 Ermal Luçi
		break;
94
	case 'PRIQ':
95
		if (isset($ref['borrow'])) unset($ref['borrow']);		
96
		if (isset($ref['bandwidth'])) unset($ref['bandwidth']);
97
		if (isset($ref['bandwidthtype'])) unset($ref['bandwidthtype']);
98
		/* fall through */
99 2b5caa0e Ermal Luçi
	case 'FAIRQ':
100
		if (isset($ref['borrow'])) unset($ref['borrow']);		
101
		/* fall through */
102 197bfe96 Ermal Luçi
	case 'CBQ':
103
		if (isset($ref['realtime'])) unset($ref['realtime']);	
104
		if (isset($ref['realtime1'])) unset($ref['realtime1']);
105
		if (isset($ref['realtime2'])) unset($ref['realtime2']);
106
		if (isset($ref['realtime3'])) unset($ref['realtime3']);
107
		if (isset($ref['upperlimit'])) unset($ref['upperlimit']);
108 2b5caa0e Ermal Luçi
		if (isset($ref['upperlimit1'])) unset($ref['upperlimit1']);
109
		if (isset($ref['upperlimit2'])) unset($ref['upperlimit2']);
110
		if (isset($ref['upperlimit3'])) unset($ref['upperlimit3']);
111 197bfe96 Ermal Luçi
		if (isset($ref['linkshare'])) unset($ref['linkshare']);
112 2b5caa0e Ermal Luçi
		if (isset($ref['linkshare1'])) unset($ref['linkshare1']);
113
		if (isset($ref['linkshare2'])) unset($ref['linkshare2']);
114
		if (isset($ref['linkshare3'])) unset($ref['linkshare3']);	
115
		if (isset($ref['hogs'])) unset($ref['hogs']);
116
		if (isset($ref['buckets'])) unset($ref['buckets']);
117 197bfe96 Ermal Luçi
		break;
118
	}
119
}
120 061f78b1 Bill Marquette
121 d62ba478 Ermal Luçi
function get_bandwidthtype_scale($type) 
122
{
123 40de74f5 Ermal Luçi
        switch ($type) {
124
        case "Gb":
125
                $factor = 1000 * 1000 * 1000;
126 f5881023 Ermal Lu?i
        	break;
127 40de74f5 Ermal Luçi
        case "Mb":
128 56f9c164 Ermal Luçi
                $factor = 1000 * 1000;
129 f5881023 Ermal Lu?i
        	break;
130 40de74f5 Ermal Luçi
        case "Kb":
131
                $factor = 1000;
132 f5881023 Ermal Lu?i
        	break;
133 40de74f5 Ermal Luçi
        case "b":
134
        default:
135
                $factor = 1;
136 f5881023 Ermal Lu?i
        	break;
137 40de74f5 Ermal Luçi
        }
138 3a54efed Ermal Luçi
        return floatval($factor);
139 40de74f5 Ermal Luçi
}
140
141 d62ba478 Ermal Luçi
function get_hfsc_bandwidth($object, $bw) 
142
{
143 40de74f5 Ermal Luçi
	$pattern= "/[0-9]+/";
144
        if (preg_match($pattern, $bw, $match))
145 07971200 Ermal Luçi
                $bw_1 = $match[1];
146 40de74f5 Ermal Luçi
        else
147
                return 0;
148 56f9c164 Ermal Luçi
        $pattern= "/(b|Kb|Mb|Gb|%)/";
149 40de74f5 Ermal Luçi
        if (preg_match($pattern, $bw, $match)) {
150 07971200 Ermal Luçi
                switch ($match[1]) {
151 40de74f5 Ermal Luçi
                case '%':
152
                        $bw_1 = $bw_1 / 100 * get_interface_bandwidth($object);
153
                        break;
154
                default:
155
                        $bw_1 = $bw_1 * get_bandwidthtype_scale($match[0]);
156
                        break;
157
                }
158 3a54efed Ermal Luçi
		return floatval($bw_1);
159 40de74f5 Ermal Luçi
        } else
160
                return 0;
161
}
162
163 d62ba478 Ermal Luçi
function get_interface_bandwidth($object) 
164
{
165 40de74f5 Ermal Luçi
	global $altq_list_queues;
166
167
        $int = $object->GetInterface();
168
        $altq =& $altq_list_queues[$int];
169
        if ($altq) {
170
                $bw_3 = $altq->GetBandwidth();
171
                $bw_3 = $bw_3 *  get_bandwidthtype_scale($altq->GetBwscale());
172 3a54efed Ermal Luçi
		return floatval($bw_3);
173 f5881023 Ermal Lu?i
        } else
174
		return 0;
175 40de74f5 Ermal Luçi
}
176
177
/*
178
 * This is duplicated here since we cannot include guiconfig.inc.
179
 * Including it makes all stuff break.
180
 */
181 d62ba478 Ermal Luçi
function shaper_do_input_validation($postdata, $reqdfields, $reqdfieldsn, $input_errors) 
182
{
183 40de74f5 Ermal Luçi
184
        /* check for bad control characters */
185
        foreach ($postdata as $pn => $pd) {
186
                if (is_string($pd) && preg_match("/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/", $pd)) {
187 dbaf21d4 Renato Botelho
                        $input_errors[] = sprintf(gettext("The field '%s' contains invalid characters."), $pn);
188 40de74f5 Ermal Luçi
                }
189
        }
190
191
        for ($i = 0; $i < count($reqdfields); $i++) {
192 56f9c164 Ermal Luçi
                if ($postdata[$reqdfields[$i]] == "") {
193 dbaf21d4 Renato Botelho
                        $input_errors[] = sprintf(gettext("The field '%s' is required."), $reqdfieldsn[$i]);
194 40de74f5 Ermal Luçi
                }
195
        }
196
}
197
198 d62ba478 Ermal Luçi
function cleanup_queue_from_rules($queue) 
199
{
200 197bfe96 Ermal Luçi
	global $config;
201 061f78b1 Bill Marquette
202 197bfe96 Ermal Luçi
	foreach ($config['filter']['rule'] as $rule) {
203
		if ($rule['defaultqueue'] == $queue)
204
			unset($rule['defaultqueue']);
205
		if ($rule['ackqueue'] == $queue)
206
			unset($rule['ackqueue']);
207
	}
208 061f78b1 Bill Marquette
}
209
210 d62ba478 Ermal Luçi
function cleanup_dnqueue_from_rules($queue) 
211
{
212 c25a6b6a Ermal Luçi
	global $config;
213
214
	foreach ($config['filter']['rule'] as $rule) {
215
		if ($rule['dnpipe'] == $queue)
216
			unset($rule['dnpipe']);
217
		if ($rule['pdnpipe'] == $queue)
218
			unset($rule['pdnpipe']);
219
	}
220
}
221
222 197bfe96 Ermal Luçi
class altq_root_queue {
223 f5881023 Ermal Lu?i
	var $interface;
224
	var $tbrconfig ;
225
	var $bandwidth;
226
	var $bandwidthtype; /* b, Kb, Mb */
227
	var $scheduler;
228
	var $qlimit;
229
	var $queues = array();
230
	var $qenabled = false;
231
	var $link;
232
	var $default_present; /* if we have a default queue set */
233
	var $available_bw; /* in b/s */
234
235
	/* Accesor functions */
236 92125c97 Ermal Luçi
	function GetAvailableBandwidth() {
237
		return $this->available_bw;
238
	}
239
	function SetAvailableBandwidth($bw) {
240
		$this->available_bw = $bw;
241
	}
242 197bfe96 Ermal Luçi
	function SetDefaultQueuePresent($value) {
243
		$this->default_present = $value;
244
	}
245
	function GetDefaultQueuePresent() {
246
		return trim($this->default_present);
247
	}
248
	function SetLink($link) {
249
		$this->link = $link;
250
	}
251
	function GetLink() {
252
		return $this->link;
253
	}	
254
	function GetEnabled() {
255
		return $this->qenabled;
256
	}
257 92125c97 Ermal Luçi
	function SetEnabled($value) {
258 197bfe96 Ermal Luçi
		$this->qenabled = $value;
259
	}
260 70b139a3 Chris Buechler
	function CanHaveChildren() {
261 197bfe96 Ermal Luçi
		return true;
262
	}
263
	function CanBeDeleted() {
264
		return false;
265
	}
266
	function GetQname() {
267
		return $this->interface;
268
	}
269
	function SetQname($name) {
270
		$this->interface = trim($name);
271
	}
272 92125c97 Ermal Luçi
	function GetInterface() {
273 f5881023 Ermal Lu?i
		return $this->interface;
274 92125c97 Ermal Luçi
	}
275
	function SetInterface($name) {
276 f5881023 Ermal Lu?i
		$this->interface = trim($name);
277 92125c97 Ermal Luçi
	}
278
	function GetTbrConfig() {
279 f5881023 Ermal Lu?i
		return $this->tbrconfig;
280 92125c97 Ermal Luçi
	}
281
	function SetTbrConfig($tbrconfig) {
282 f5881023 Ermal Lu?i
		$this->tbrconfig = $tbrconfig;
283 92125c97 Ermal Luçi
	}
284
	function GetBandwidth() {
285 f5881023 Ermal Lu?i
		return $this->bandwidth;
286 92125c97 Ermal Luçi
	}
287
	function SetBandwidth($bw) {
288 f5881023 Ermal Lu?i
		$this->bandwidth = $bw;
289 92125c97 Ermal Luçi
	}
290
	function GetBwscale() {
291 f5881023 Ermal Lu?i
		return $this->bandwidthtype;
292 92125c97 Ermal Luçi
	}
293
	function SetBwscale($bwscale) {
294 f5881023 Ermal Lu?i
		$this->bandwidthtype = $bwscale;
295 92125c97 Ermal Luçi
	}
296
	function GetScheduler() {
297 f5881023 Ermal Lu?i
		return $this->scheduler;
298 92125c97 Ermal Luçi
	}
299
	function SetScheduler($scheduler) {
300 f5881023 Ermal Lu?i
		$this->scheduler = trim($scheduler);
301 92125c97 Ermal Luçi
	}
302 197bfe96 Ermal Luçi
	function GetQlimit() {
303
		return $this->qlimit;
304
	}
305
	function SetQlimit($limit) {
306
		$this->qlimit = $limit;
307
	}
308 f5881023 Ermal Lu?i
309 197bfe96 Ermal Luçi
	function validate_input($data, &$input_errors) {
310 92125c97 Ermal Luçi
		
311 2c072899 jim-p
		$reqdfields[] = "bandwidth";
312 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidth");
313 2c072899 jim-p
		$reqdfields[] = "bandwidthtype";
314 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidthtype");
315 92125c97 Ermal Luçi
		
316 40de74f5 Ermal Luçi
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
317 92125c97 Ermal Luçi
		
318 40de74f5 Ermal Luçi
                if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
319 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Bandwidth must be an integer.");
320 40de74f5 Ermal Luçi
                if ($data['bandwidth'] < 0)
321 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Bandwidth cannot be negative.");
322 40de74f5 Ermal Luçi
                if ($data['qlimit'] && (!is_numeric($data['qlimit'])))
323 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Qlimit must be an integer.");
324 40de74f5 Ermal Luçi
	 	if ($data['qlimit'] < 0)
325 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Qlimit must be an positive.");
326 40de74f5 Ermal Luçi
                if ($data['tbrconfig'] && (!is_numeric($data['tbrconfig'])))
327 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Tbrsize must be an integer.");
328 40de74f5 Ermal Luçi
                if ($data['tbrconfig'] < 0)
329 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Tbrsize must be an positive.");
330 92125c97 Ermal Luçi
	}
331 197bfe96 Ermal Luçi
332
	/* Implement this to shorten some code on the frontend page */
333 f5881023 Ermal Lu?i
	function ReadConfig(&$conf) {
334
		if (isset($conf['tbrconfig']))
335
			$this->SetTbrConfig($conf['tbrconfig']);
336 06f3e447 Ermal
		else
337
			$this->SetTbrConfig($conf['tbrconfig']);
338 1941345c Ermal
		$this->SetBandwidth($conf['bandwidth']);
339
		if ($conf['bandwidthtype'] <> "")
340
			$this->SetBwscale($conf['bandwidthtype']);
341 197bfe96 Ermal Luçi
		if (isset($conf['scheduler'])) {
342 f5881023 Ermal Lu?i
			if ($this->GetScheduler() != $conf['scheduler']) {
343
				foreach ($this->queues as $q) {
344
					clean_child_queues($conf['scheduler'], $this->GetLink());
345
					$q->clean_queue($conf['scheduler']);
346 061f78b1 Bill Marquette
				}
347
			}
348 f5881023 Ermal Lu?i
			$this->SetScheduler($conf['scheduler']);
349
		}
350 92125c97 Ermal Luçi
		if (isset($conf['qlimit']) && $conf['qlimit'] <> "")
351 197bfe96 Ermal Luçi
			$this->SetQlimit($conf['qlimit']);
352 06f3e447 Ermal
		else
353
			$this->SetQlimit("");
354 197bfe96 Ermal Luçi
		if (isset($conf['name']))
355
			$this->SetQname($conf['name']);		
356 cf222376 Ermal Lu?i
		if (!empty($conf['enabled']))
357 f5881023 Ermal Lu?i
			$this->SetEnabled($conf['enabled']);
358 ea25d26d Ermal Lu?i
		else
359
			$this->SetEnabled("");
360 197bfe96 Ermal Luçi
	}
361 f5881023 Ermal Lu?i
362 a843b04f Ermal Luçi
	function copy_queue($interface, &$cflink) {
363
                $cflink['interface'] = $interface;
364
                $cflink['name'] = $interface;
365
                $cflink['scheduler'] = $this->GetScheduler();
366
                $cflink['bandwidth'] = $this->GetBandwidth();
367
                $cflink['bandwidthtype'] = $this->GetBwscale();
368
                $cflink['qlimit'] = $this->GetQlimit();
369
                $cflink['tbrconfig'] = $this->GetTbrConfig();
370
                $cflink['enabled'] = $this->GetEnabled();
371
		if (is_array($this->queues)) {
372
			$cflink['queue'] = array();
373
			foreach ($this->queues as $q) {
374
				$cflink['queue'][$q->GetQname()] = array();
375
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
376
			}
377 92125c97 Ermal Luçi
		}
378 061f78b1 Bill Marquette
	}
379
380 f5881023 Ermal Lu?i
	function &get_queue_list($q = null) {
381
		$qlist = array();
382 b7ff5e40 Scott Ullrich
383 f5881023 Ermal Lu?i
		$qlist[$this->GetQname()] = & $this;
384
		if (is_array($this->queues)) {
385
			foreach ($this->queues as $queue)
386
				$queue->get_queue_list(&$qlist);
387 fe93b17b Ermal Luçi
		}
388 f5881023 Ermal Lu?i
		return $qlist;
389
	}
390 fe93b17b Ermal Luçi
391 f5881023 Ermal Lu?i
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
392 92125c97 Ermal Luçi
393 f5881023 Ermal Lu?i
		if (!is_array($this->queues))
394
			$this->queues = array();
395
396
		switch ($this->GetScheduler()) {
397
		case "PRIQ":
398 62150088 Ermal Lu?i
			$q =& new priq_queue();
399 f5881023 Ermal Lu?i
			break;
400
		case "HFSC":
401 62150088 Ermal Lu?i
			$q =& new hfsc_queue();
402 f5881023 Ermal Lu?i
			break;
403
		case "CBQ":
404 62150088 Ermal Lu?i
			$q =& new cbq_queue();
405 f5881023 Ermal Lu?i
			break;
406
		case "FAIRQ":
407 62150088 Ermal Lu?i
			$q =& new fairq_queue();
408 f5881023 Ermal Lu?i
			break;
409
		default:
410
			/* XXX: but should not happen anyway */ 
411
			return;
412
			break;
413
		}
414
		$q->SetLink($path);
415
		$q->SetInterface($this->GetInterface());
416
		$q->SetEnabled("on");
417
		$q->SetParent(&$this);
418
		$q->ReadConfig($queue);
419
		$q->validate_input($queue, $input_errors);
420
		if (count($input_errors)) {
421 92125c97 Ermal Luçi
			return $q;
422 197bfe96 Ermal Luçi
		}
423
424 f5881023 Ermal Lu?i
		if (isset($queue['bandwidth'])) {
425
			switch ($queue['bandwidthtype']) {
426
			case "%":
427
				$myBw = $this->GetAvailableBandwidth() * $queue['bandwidth'] / 100;
428
				break;
429
			default:
430
				$myBw = $queue['bandwidth'] * get_bandwidthtype_scale($queue['bandwdithtype']);
431
				break;
432 92125c97 Ermal Luçi
			}
433
		}
434 f5881023 Ermal Lu?i
		$q->SetAvailableBandwidth($myBw);
435
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
436
		$this->queues[$q->GetQname()] = &$q; 
437
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
438
		if (is_array($queue['queue'])) {
439
			foreach ($queue['queue'] as $key1 => $que) {
440
				array_push($path, $key1);
441
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
442
				array_pop($path);
443
			}
444
		}
445
446
		return $q;
447
	}
448
449
	/* interface here might be optional */
450
	function &find_queue($interface, $qname) {
451
		if ($qname == $this->GetQname()) {
452
			return $this;
453
		} 
454
		foreach ($this->queues as $q) {
455
			$result =& $q->find_queue("", $qname);
456
			if ($result)
457
				return $result;
458
		}
459
	}
460 197bfe96 Ermal Luçi
461
	function &find_parentqueue($interface, $qname) {
462
		if ($qname == $interface) {
463
			$result =  NULL;
464 92125c97 Ermal Luçi
		} else if ($this->queues[$qname])	 {
465 197bfe96 Ermal Luçi
			$result = $this;
466
		} else if ($this->GetScheduler() <> "PRIQ") {
467
			foreach ($this->queues as $q) {
468
				$result = $q->find_parentqueue("", $qname);
469
				if ($result)
470
					return $result;
471 b7ff5e40 Scott Ullrich
			}
472 061f78b1 Bill Marquette
		}
473
	}
474
475 197bfe96 Ermal Luçi
	function build_tree() {
476 057399e4 Ermal Luçi
		global $shaperIFlist;
477
478 197bfe96 Ermal Luçi
		$tree = " <li><a href=\"firewall_shaper.php?interface=".$this->GetInterface()."&queue=". $this->GetInterface()."&action=show"; 
479 057399e4 Ermal Luçi
		$tree .= "\">" . $shaperIFlist[$this->GetInterface()] . "</a>";
480 197bfe96 Ermal Luçi
		if (is_array($this->queues)) {
481
			$tree .= "<ul>";
482
			foreach ($this->queues as $q)  {
483
				$tree .= $q->build_tree();
484
			}
485
		$tree .= "</ul>";
486
		}
487
		$tree .= "</li>";
488
		return $tree;
489
	}
490
	
491 92125c97 Ermal Luçi
	function delete_queue() { 
492 fce82460 Ermal Luçi
		foreach ($this->queues as $q) {
493 cedae3d3 Ermal Luçi
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
494 fce82460 Ermal Luçi
			$q->delete_queue();			
495
		}
496 197bfe96 Ermal Luçi
		unset_object_by_reference($this->GetLink());
497 92125c97 Ermal Luçi
	 }
498
499 b0262cb2 Ermal Luçi
	function delete_all() {
500
                if (count($this->queues)) {
501
                        foreach ($this->queues as $q) {
502
                        	$q->delete_all();
503
                        	unset_object_by_reference($q->GetLink());
504
                                unset($q);
505
               		}
506
        	        unset($this->queues);
507
                }
508
        }
509
510 92125c97 Ermal Luçi
	/*
511
	 * First it spits:
512
	 * altq on $interface ..............
513
	 *      then it goes like
514
	 *      foreach ($queues as $qkey => $queue)
515
	 *              this->queues[$qkey]->build_rule();
516
	 */
517
	function build_rules() {
518 34a3694b Ermal
		if (count($this->queues) > 0 && $this->GetEnabled() == "on") {
519 85a5da13 Ermal Luçi
			$rules = " altq on  " . get_real_interface($this->GetInterface());
520 92125c97 Ermal Luçi
			if ($this->GetScheduler())
521 f5881023 Ermal Lu?i
				$rules .= " ".strtolower($this->GetScheduler());
522 1941345c Ermal
			if ($this->GetBandwidth()) {
523 f5881023 Ermal Lu?i
				$rules .= " bandwidth ".trim($this->GetBandwidth());
524 1941345c Ermal
				if ($this->GetBwscale())
525
					$rules .= $this->GetBwscale();
526
			}
527 92125c97 Ermal Luçi
			if ($this->GetTbrConfig())
528 f5881023 Ermal Lu?i
				$rules .= " tbrsize ".$this->GetTbrConfig();
529 92125c97 Ermal Luçi
			if (count($this->queues)) {
530 f5881023 Ermal Lu?i
				$i = count($this->queues);
531
				$rules .= " queue { ";
532
				foreach ($this->queues as $qkey => $qnone) {
533
					if ($i > 1) {
534
						$i--;
535
						$rules .= " {$qkey}, ";
536
					} else
537
						$rules .= " {$qkey} ";
538
				}
539
				$rules .= " } \n";
540
				foreach ($this->queues as $q) {
541
					$rules .= $q->build_rules();
542
				}
543 92125c97 Ermal Luçi
			}
544 197bfe96 Ermal Luçi
		}
545
		$rules .= " \n";
546 92125c97 Ermal Luçi
		return $rules;
547
	}
548 197bfe96 Ermal Luçi
549
	function build_javascript() {
550 f5881023 Ermal Lu?i
		$javascript = "<script type=\"text/javascript\">";
551
		$javascript .= "function mySuspend() {";
552
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);";
553
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';";
554
		$javascript .= "else if (document.all)";
555
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';";
556
		$javascript .= "}";
557
558
		$javascript .= "function myResume() {";
559
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)";
560
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';";
561
		$javascript .= "else if (document.all)";
562
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';";
563
		$javascript .= "}";
564
		$javascript .= "</script>";
565
566
		return $javascript;
567 92125c97 Ermal Luçi
	}
568 197bfe96 Ermal Luçi
	
569 92125c97 Ermal Luçi
	function build_shortform() {
570 f5881023 Ermal Lu?i
		global $g;
571
572
		$altq =& $this;
573
		if ($altq)
574
			$scheduler = ": " . $altq->GetScheduler();
575
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
576
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=". $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
577
		$form .= "</td></tr>";
578
		$form .= "<tr>";
579
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
580
		$form .= "Bandwidth: " . $this->GetBandwidth().$this->GetBwscale();
581
		$form .= "</td><td width=\"50%\"></td></tr>";
582
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
583
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
584
		$form .= $this->GetInterface() . "&queue=";
585
		$form .= $this->GetQname() . "&action=delete\">";
586
		$form .= "<img src=\"";
587
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
588
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"Disable shaper on interface\">";
589
		$form .= "<span>Disable shaper on interface</span></a></td></tr>";
590
591
		return $form;
592 92125c97 Ermal Luçi
593
	}
594 f5881023 Ermal Lu?i
	/*
595
	 * For requesting the parameters of the root queue
596
	 * to the user like the traffic wizard does.
597
	 */
598 92125c97 Ermal Luçi
	function build_form() { 
599 f5e511d3 Ermal
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
600 dbaf21d4 Renato Botelho
		$form .= gettext("Enable/Disable");
601 f5e511d3 Ermal
		$form .= "<br/></td><td class=\"vncellreq\">";
602 34a3694b Ermal
		$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
603
                if ($this->GetEnabled() == "on")
604
                        $form .=  " CHECKED";
605 dbaf21d4 Renato Botelho
		$form .= " ><span class=\"vexpl\"> " . gettext("Enable/disable discipline and its children") . "</span>";
606 34a3694b Ermal
		$form .= "</td></tr>";
607 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
608 197bfe96 Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
609
		$form .= "<strong>".$this->GetQname()."</strong>";
610
		$form .= "</td></tr>";
611 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Scheduler Type ");
612 197bfe96 Ermal Luçi
		$form .= "</td>";
613
		$form .= "<td class=\"vncellreq\">";
614
		$form .= "<select id=\"scheduler\" name=\"scheduler\" class=\"formselect\">";
615 0876822d Ermal Luçi
		$form .= "<option value=\"HFSC\"";
616 197bfe96 Ermal Luçi
		if ($this->GetScheduler() == "HFSC")
617
			$form .= " selected=\"yes\"";
618
		$form .= ">HFSC</option>";
619 0876822d Ermal Luçi
		$form .= "<option value=\"CBQ\"";
620 197bfe96 Ermal Luçi
		if ($this->GetScheduler() == "CBQ")
621 0876822d Ermal Luçi
			$form .= " selected=\"yes\"";
622 197bfe96 Ermal Luçi
		$form .= ">CBQ</option>";
623 0876822d Ermal Luçi
		$form .= "<option value=\"FAIRQ\"";
624
                if ($this->GetScheduler() == "FAIRQ")
625
                	$form .= " selected=\"yes\"";
626
                $form .= ">FAIRQ</option>";
627
		$form .= "<option value=\"PRIQ\"";
628 197bfe96 Ermal Luçi
		if ($this->GetScheduler() == "PRIQ")
629 0876822d Ermal Luçi
			$form .= " selected=\"yes\"";
630 197bfe96 Ermal Luçi
		$form .= ">PRIQ</option>";
631 0876822d Ermal Luçi
		$form .= "</select>";
632 197bfe96 Ermal Luçi
		$form .= "<br> <span class=\"vexpl\">";
633 dbaf21d4 Renato Botelho
		$form .= gettext("NOTE: Changing this changes all child queues!");
634
		$form .= gettext(" Beware you can lose information.");
635 197bfe96 Ermal Luçi
		$form .= "</span>";
636
		$form .= "</td></tr>";
637 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth");
638 197bfe96 Ermal Luçi
		$form .= "</td><td class=\"vncellreq\">";
639
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
640
		$form .= $this->GetBandwidth() . "\">"; 
641 92125c97 Ermal Luçi
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
642
		$form .= "<option value=\"Kb\"";
643 197bfe96 Ermal Luçi
		if ($this->GetBwscale() == "Kb")
644 92125c97 Ermal Luçi
			$form .= " selected=\"yes\"";
645 197bfe96 Ermal Luçi
		$form .= ">Kbit/s</option>";
646 92125c97 Ermal Luçi
		$form .= "<option value=\"Mb\"";
647 197bfe96 Ermal Luçi
		if ($this->GetBwscale() == "Mb")
648 92125c97 Ermal Luçi
			$form .= " selected=\"yes\"";
649
		$form .= ">Mbit/s</option>";
650
		$form .= "<option value=\"Gb\"";
651
		if ($this->GetBwscale() == "Gb")
652
			$form .= " selected=\"yes\"";
653
		$form .= ">Gbit/s</option>";		
654 197bfe96 Ermal Luçi
		$form .= "<option value=\"\"";
655 92125c97 Ermal Luçi
		if ($this->GetBwscale() == "b")
656
			$form .= " selected=\"yes\"";
657
		$form .= ">Bit/s</option>";
658
		$form .= "</select>";
659
		$form .= "</td></tr>";
660 f5e511d3 Ermal
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Queue Limit</td>";
661 92125c97 Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
662
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
663
		$form .= $this->GetQlimit();
664
		$form .= "\">";
665 197bfe96 Ermal Luçi
		$form .= "</td></tr>";
666 f5e511d3 Ermal
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">TBR Size</td>";
667 197bfe96 Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
668 f5e511d3 Ermal
		$form .= "<br /><input type=\"text\" id=\"tbrconfig\" name=\"tbrconfig\" value=\"";
669 197bfe96 Ermal Luçi
		$form .= $this->GetTbrConfig();
670
		$form .= "\">";
671
		$form .= "<br> <span class=\"vexpl\">";
672 dbaf21d4 Renato Botelho
		$form .= gettext("Adjusts the size, in bytes, of the token bucket regulator. "
673
		      .  "If not specified, heuristics based on the interface "
674
		      .  "bandwidth are used to determine the size.");
675 f5881023 Ermal Lu?i
		$form .= "</span></td></tr>";
676 197bfe96 Ermal Luçi
		$form .= "<input type=\"hidden\" id=\"interface\" name=\"interface\"";
677
		$form .= " value=\"" . $this->GetInterface() . "\">";
678
		$form .= "<input type=\"hidden\" id=\"name\" name=\"name\" value=\"".$this->GetQname()."\" >";
679
680
681
		return $form;
682
	}
683 061f78b1 Bill Marquette
684 f5881023 Ermal Lu?i
	function update_altq_queue_data(&$data) { 
685 197bfe96 Ermal Luçi
		$this->ReadConfig($data);
686 061f78b1 Bill Marquette
	}
687 197bfe96 Ermal Luçi
	
688 92125c97 Ermal Luçi
	/*
689
	 * Should call on each of it queues and subqueues
690
	 * the same function much like build_rules();
691
	 */
692
	function wconfig() { 
693
		$cflink = &get_reference_to_me_in_config($this->GetLink());
694
		if (!is_array($cflink))
695
			$cflink = array();
696
		$cflink['interface'] = $this->GetInterface();	
697
		$cflink['name'] = $this->GetQname();
698
		$cflink['scheduler'] = $this->GetScheduler();
699
		$cflink['bandwidth'] = $this->GetBandwidth();
700
		$cflink['bandwidthtype'] = $this->GetBwscale();
701 f5881023 Ermal Lu?i
		$cflink['qlimit'] = trim($this->GetQlimit());
702
		if (empty($cflink['qlimit']))
703
			unset($cflink['qlimit']);
704
		$cflink['tbrconfig'] = trim($this->GetTbrConfig());
705
		if (empty($cflink['tbrconfig']))
706
			unset($cflink['tbrconfig']);
707 92125c97 Ermal Luçi
		$cflink['enabled'] = $this->GetEnabled();
708 f5881023 Ermal Lu?i
		if (empty($cflink['enabled']))
709
			unset($cflink['enabled']);
710 92125c97 Ermal Luçi
	}
711 061f78b1 Bill Marquette
712 197bfe96 Ermal Luçi
}
713 061f78b1 Bill Marquette
714 197bfe96 Ermal Luçi
class priq_queue {
715 92125c97 Ermal Luçi
	var $qname;
716
	var $qinterface; 
717
	var $qlimit;
718
	var $qpriority;
719
	var $description;
720
	var $isparent;
721 197bfe96 Ermal Luçi
	var $qbandwidth;
722
	var $qbandwidthtype;
723 f5881023 Ermal Lu?i
	var $qdefault = "";
724
	var $qrio = "";
725
	var $qred = "";
726
	var $qecn = "";
727 197bfe96 Ermal Luçi
	var $qack;
728 f5881023 Ermal Lu?i
	var $qenabled = "";
729 197bfe96 Ermal Luçi
	var $qparent;
730
	var $link;
731 92125c97 Ermal Luçi
	var $available_bw; /* in b/s */
732
733 70b139a3 Chris Buechler
	/* This is here to help with form building and building rules/lists */
734 92125c97 Ermal Luçi
		var $subqueues = array();
735
736
	/* Accesor functions */
737
	function GetAvailableBandwidth() {
738
		return $this->available_bw;
739
	}
740
	function SetAvailableBandwidth($bw) {
741
		$this->available_bw = $bw;
742
	}
743
	function SetLink($link) {
744 f5881023 Ermal Lu?i
		$this->link = $link;
745 92125c97 Ermal Luçi
	}
746
	function GetLink() {
747 f5881023 Ermal Lu?i
		return $this->link;
748 92125c97 Ermal Luçi
	}
749 197bfe96 Ermal Luçi
	function &GetParent() {
750
		return $this->qparent;
751
	}
752
	function SetParent(&$parent) {
753
		$this->qparent = &$parent;
754
	}
755 92125c97 Ermal Luçi
	function GetEnabled() {
756 f5881023 Ermal Lu?i
		return $this->qenabled;
757 92125c97 Ermal Luçi
	}
758
	function SetEnabled($value) {
759 f5881023 Ermal Lu?i
		$this->qenabled = $value;
760 92125c97 Ermal Luçi
	}
761 70b139a3 Chris Buechler
	function CanHaveChildren() {
762 f5881023 Ermal Lu?i
		return false;
763 92125c97 Ermal Luçi
	}
764 197bfe96 Ermal Luçi
	function CanBeDeleted() {
765 f5881023 Ermal Lu?i
		return true;
766 92125c97 Ermal Luçi
	}
767
	function GetQname() {
768 f5881023 Ermal Lu?i
		return $this->qname;
769 92125c97 Ermal Luçi
	}
770
	function SetQname($name) {
771 f5881023 Ermal Lu?i
		$this->qname = trim($name);
772 92125c97 Ermal Luçi
	}
773
	function GetBandwidth() {
774 f5881023 Ermal Lu?i
		return $this->qbandwidth;
775 92125c97 Ermal Luçi
	}
776
	function SetBandwidth($bandwidth) {
777 f5881023 Ermal Lu?i
		$this->qbandwidth = $bandwidth;
778 92125c97 Ermal Luçi
	}
779
	function GetInterface() {
780 f5881023 Ermal Lu?i
		return $this->qinterface;
781 92125c97 Ermal Luçi
	}
782
	function SetInterface($name) {
783 f5881023 Ermal Lu?i
		$this->qinterface = trim($name);
784 92125c97 Ermal Luçi
	}
785
	function GetQlimit() {
786 f5881023 Ermal Lu?i
		return $this->qlimit;
787 92125c97 Ermal Luçi
	}
788
	function SetQlimit($limit) {
789 f5881023 Ermal Lu?i
		$this->qlimit = $limit;
790 92125c97 Ermal Luçi
	}
791
	function GetQpriority() {
792 f5881023 Ermal Lu?i
		return $this->qpriority;
793 92125c97 Ermal Luçi
	}
794
	function SetQpriority($priority) {
795 f5881023 Ermal Lu?i
		$this->qpriority = $priority;
796 92125c97 Ermal Luçi
	}
797
	function GetDescription() {
798 f5881023 Ermal Lu?i
		return $this->description;
799 92125c97 Ermal Luçi
	}
800
	function SetDescription($str) {
801 f5881023 Ermal Lu?i
		$this->description = trim($str);
802 92125c97 Ermal Luçi
	}
803
	function GetFirstime() {
804 f5881023 Ermal Lu?i
		return $this->firsttime;
805 92125c97 Ermal Luçi
	}
806
	function SetFirsttime($number) {
807 f5881023 Ermal Lu?i
		$this->firsttime = $number;
808 92125c97 Ermal Luçi
	}
809
	function GetBwscale() {
810 f5881023 Ermal Lu?i
		return $this->qbandwidthtype;
811 92125c97 Ermal Luçi
	}
812
	function SetBwscale($scale) {
813 f5881023 Ermal Lu?i
		$this->qbandwidthtype = $scale;
814 92125c97 Ermal Luçi
	}
815 197bfe96 Ermal Luçi
	function GetDefault() {
816 f5881023 Ermal Lu?i
		return $this->qdefault;
817 92125c97 Ermal Luçi
	}
818
	function SetDefault($value = false) {
819 f5881023 Ermal Lu?i
		$this->qdefault = $value;
820
		altq_set_default_queue($this->GetInterface(), "true");
821 92125c97 Ermal Luçi
	}
822 197bfe96 Ermal Luçi
	function GetRed() {
823 f5881023 Ermal Lu?i
		return $this->qred;
824 92125c97 Ermal Luçi
	}
825
	function SetRed($red = false) {
826 f5881023 Ermal Lu?i
		$this->qred = $red;
827 92125c97 Ermal Luçi
	}
828 197bfe96 Ermal Luçi
	function GetRio() {
829 f5881023 Ermal Lu?i
		return $this->qrio;
830 92125c97 Ermal Luçi
	}
831
	function SetRio($rio = false) {
832 f5881023 Ermal Lu?i
		$this->qrio = $rio;
833 92125c97 Ermal Luçi
	}
834 f5881023 Ermal Lu?i
	function GetEcn() {
835
		return $this->qecn;
836 92125c97 Ermal Luçi
	}
837
	function SetEcn($ecn = false) {
838 f5881023 Ermal Lu?i
		$this->qecn = $ecn;
839 92125c97 Ermal Luçi
	}
840 197bfe96 Ermal Luçi
	function GetAck() {
841 f5881023 Ermal Lu?i
		return $this->qack;
842 92125c97 Ermal Luçi
	}
843
	function SetAck($ack = false) {
844 f5881023 Ermal Lu?i
		$this->qack = $ack;
845 92125c97 Ermal Luçi
	}
846 197bfe96 Ermal Luçi
847
	function build_javascript() {
848
		$javascript = "<script type=\"text/javascript\">";
849
		$javascript .= "function mySuspend() { \n";
850 92125c97 Ermal Luçi
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null);\n";
851
		$javascript .= "document.layers['shaperarea'].visibility = 'hidden';\n";
852
		$javascript .= "else if (document.all)\n";
853
		$javascript .= "document.all['shaperarea'].style.visibility = 'hidden';\n";
854
		$javascript .= "}\n";
855
856
		$javascript .= "function myResume() {\n";
857
		$javascript .= "if (document.layers && document.layers['shaperarea'] != null)\n";
858
		$javascript .= "document.layers['shaperarea'].visibility = 'visible';\n";
859
		$javascript .= "else if (document.all)\n";
860
		$javascript .= "document.all['shaperarea'].style.visibility = 'visible';\n";
861
		$javascript .= "}\n";
862
		$javascript .= "</script>";
863 197bfe96 Ermal Luçi
		
864
		return $javascript;
865
	}
866
	
867 6f627d41 Ermal Luçi
	function &add_queue($interface, &$qname, &$path, &$input_errors) { return; }
868
869 197bfe96 Ermal Luçi
	/* 
870 70b139a3 Chris Buechler
	 * Currently this will not be called unless we decide to clone a whole 
871 197bfe96 Ermal Luçi
	 * queue tree on the 'By Queues' view or support drag&drop on the tree/list
872
	 */
873 a843b04f Ermal Luçi
	 function copy_queue($interface, &$cflink) {
874
875
 		$cflink['name'] = $this->GetQname();
876
                $cflink['interface'] = $interface;
877
                $cflink['qlimit'] = $this->GetQlimit();
878
                $cflink['priority'] = $this->GetQpriority();
879
                $cflink['description'] = $this->GetDescription();
880
                $cflink['enabled'] = $this->GetEnabled();
881
                $cflink['default'] = $this->GetDefault();
882
                $cflink['red'] = $this->GetRed();
883
                $cflink['rio'] = $this->GetRio();
884
                $cflink['ecn'] = $this->GetEcn();
885
886
                if (is_array($this->subqueues)) {
887
                        $cflinkp['queue'] = array();
888
                        foreach ($this->subqueues as $q) {
889
				 $cflink['queue'][$q->GetQname()] = array();
890
                                $q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
891
			}
892
                }
893 197bfe96 Ermal Luçi
894
	 }
895
896
	function clean_queue($sched) {
897 92125c97 Ermal Luçi
		clean_child_queues($sched, $this->GetLink());
898
		if (is_array($this->subqueues)) {
899 f5881023 Ermal Lu?i
			foreach ($this->subqueues as $q)
900
				$q->clean_queue($sched);
901 92125c97 Ermal Luçi
		}
902 f5881023 Ermal Lu?i
	}
903 197bfe96 Ermal Luçi
904 fe93b17b Ermal Luçi
        function &get_queue_list(&$qlist) {
905 f5881023 Ermal Lu?i
		$qlist[$this->GetQname()] = & $this;
906
		if (is_array($this->subqueues)) {
907
			foreach ($this->subqueues as $queue)
908
				$queue->get_queue_list($qlist);
909
		}
910
	}
911 fe93b17b Ermal Luçi
912 197bfe96 Ermal Luçi
	function delete_queue() {
913 92125c97 Ermal Luçi
		unref_on_altq_queue_list($this->GetQname());
914
		if ($this->GetDefault())
915
				altq_set_default_queue($this->GetInterface(), "false");
916
		cleanup_queue_from_rules($this->GetQname());
917
		unset_object_by_reference($this->GetLink());
918
	}
919 b0262cb2 Ermal Luçi
	
920
	function delete_all() {
921
                if (count($this->subqueues)) {
922
                        foreach ($this->subqueues as $q) {
923
                                $q->delete_all();
924
                                unset_object_by_reference($q->GetLink());
925
                                unset($q);
926
                        }
927
                        unset($this->subqueues);
928
                }
929
        }
930 197bfe96 Ermal Luçi
931
	 function &find_queue($interface, $qname) { 
932
		if ($qname == $this->GetQname())
933
			return $this; 
934
	}
935 92125c97 Ermal Luçi
	
936 62150088 Ermal Lu?i
	function find_parentqueue($interface, $qname) { return; }
937 197bfe96 Ermal Luçi
		
938 92125c97 Ermal Luçi
	function validate_input($data, &$input_errors) {
939
	
940 2c072899 jim-p
		$reqdfields[] = "name";
941 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Name");
942 40de74f5 Ermal Luçi
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
943 197bfe96 Ermal Luçi
944
		if ($data['priority'] && (!is_numeric($data['priority'])
945 92125c97 Ermal Luçi
						|| ($data['priority'] < 1) || ($data['priority'] > 15))) {
946 dbaf21d4 Renato Botelho
					$input_errors[] = gettext("The priority must be an integer between 1 and 15.");
947 92125c97 Ermal Luçi
		}
948 197bfe96 Ermal Luçi
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
949 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Queue limit must be an integer");
950 92125c97 Ermal Luçi
		if ($data['qlimit'] < 0)
951 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Queue limit must be positive");
952 92125c97 Ermal Luçi
		if (!preg_match("/^[a-zA-Z0-9_-]*$/", $data['name']))
953 dbaf21d4 Renato Botelho
			 $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
954 197bfe96 Ermal Luçi
		
955 061f78b1 Bill Marquette
	}
956
957 92125c97 Ermal Luçi
	function ReadConfig(&$q) {
958
		if (isset($q['name']))
959
				$this->SetQname($q['name']);
960
		if (isset($q['interface']))
961
				$this->SetInterface($q['interface']);
962 0b13e3f9 Ermal
		$this->SetBandwidth($q['bandwidth']);
963
		if ($q['bandwidthtype'] <> "")
964
			$this->SetBwscale($q['bandwidthtype']);
965 f5881023 Ermal Lu?i
		if (!empty($q['qlimit']))
966
			$this->SetQlimit($q['qlimit']);
967 ea25d26d Ermal Lu?i
		else
968
			$this->SetQlimit(""); // Default
969 f5881023 Ermal Lu?i
		if (!empty($q['priority']))
970
			$this->SetQPriority($q['priority']);
971 ea25d26d Ermal Lu?i
		else
972
			$this->SetQpriority("");
973 f5881023 Ermal Lu?i
		if (!empty($q['description']))
974
			$this->SetDescription($q['description']);
975 ea25d26d Ermal Lu?i
		else
976 da0ce7ee Chris Buechler
			$this->SetDescription("");
977 cf222376 Ermal Lu?i
		if (!empty($q['red']))
978 f5881023 Ermal Lu?i
			$this->SetRed($q['red']);
979 ea25d26d Ermal Lu?i
		else
980
			$this->SetRed();
981 cf222376 Ermal Lu?i
		if (!empty($q['rio']))
982 f5881023 Ermal Lu?i
			$this->SetRio($q['rio']);
983 ea25d26d Ermal Lu?i
		else
984
			$this->SetRio();
985 cf222376 Ermal Lu?i
		if (!empty($q['ecn']))
986 f5881023 Ermal Lu?i
			$this->SetEcn($q['ecn']);
987 ea25d26d Ermal Lu?i
		else
988
			$this->SetEcn();
989 cf222376 Ermal Lu?i
		if (!empty($q['default']))
990 f5881023 Ermal Lu?i
			$this->SetDefault($q['default']);
991 ea25d26d Ermal Lu?i
		else
992
			$this->SetDefault();
993 cf222376 Ermal Lu?i
		if (!empty($q['enabled']))
994 f5881023 Ermal Lu?i
			$this->SetEnabled($q['enabled']);
995 ea25d26d Ermal Lu?i
		else
996
			$this->SetEnabled("");
997 197bfe96 Ermal Luçi
998 f5881023 Ermal Lu?i
	}
999 197bfe96 Ermal Luçi
1000
	function build_tree() {
1001 f5881023 Ermal Lu?i
		$tree = " <li><a href=\"firewall_shaper.php?interface=". $this->GetInterface()."&queue=". $this->GetQname()."&action=show"; 
1002
		$tree .= "\" ";
1003
		$tmpvalue = $this->GetDefault();
1004
		if (!empty($tmpvalue))
1005
			$tree .= " class=\"navlnk\"";
1006
		$tree .= " >" . $this->GetQname() . "</a>";
1007
		/* 
1008
		 * Not needed here!
1009
		 * if (is_array($queues) {
1010
		 *	  $tree .= "<ul>";
1011
		 *	  foreach ($q as $queues) 
1012
		 *		  $tree .= $queues['$q->GetName()']->build_tree();
1013
		 *	  endforeach	
1014
		 *	  $tree .= "</ul>";
1015
		 * }
1016 92125c97 Ermal Luçi
		 */
1017 f5881023 Ermal Lu?i
1018
		$tree .= "</li>"; 
1019
1020
		return $tree;
1021
	}
1022 92125c97 Ermal Luçi
		
1023 f5881023 Ermal Lu?i
	/* Should return something like:
1024
	 * queue $qname on $qinterface bandwidth ....
1025
	 */
1026
	function build_rules() {
1027
		$pfq_rule = " queue ". $this->qname;
1028
		if ($this->GetInterface())
1029
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1030
		$tmpvalue = $this->GetQpriority();
1031
		if (!empty($tmpvalue))
1032
			$pfq_rule .= " priority ".$this->GetQpriority();
1033
		$tmpvalue = $this->GetQlimit();
1034
		if (!empty($tmpvalue))
1035
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1036
		if ($this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetDefault()) {
1037
			$pfq_rule .= " priq ( ";
1038
			$tmpvalue = $this->GetRed();
1039
			if (!empty($tmpvalue)) {
1040
				$comma = 1;
1041
				$pfq_rule .= " red ";
1042
			}
1043
			$tmpvalue = $this->GetRio();
1044
			if (!empty($tmpvalue)) {
1045
				if ($comma) 
1046
					$pfq_rule .= " ,";
1047
				$comma = 1;
1048
				$pfq_rule .= " rio ";
1049
			}
1050
			$tmpvalue = $this->GetEcn();
1051
			if (!empty($tmpvalue)) {
1052
				if ($comma) 
1053
					$pfq_rule .= " ,";
1054
				$comma = 1;
1055
				$pfq_rule .= " ecn ";
1056
			}
1057
			$tmpvalue = $this->GetDefault();
1058
			if (!empty($tmpvalue)) {
1059
				if ($comma)
1060
					$pfq_rule .= " ,";
1061
				$pfq_rule .= " default ";
1062
			}
1063
			$pfq_rule .= " ) ";
1064 92125c97 Ermal Luçi
		}
1065
1066 f5881023 Ermal Lu?i
		$pfq_rule .= " \n";
1067
1068
		return $pfq_rule;
1069
	}
1070
1071
	/*
1072
	 * To return the html form to show to user
1073
	 * for getting the parameters.
1074
	 * Should do even for first time when the
1075
	 * object is created and later when we may
1076
	 * need to update it.
1077
	 */
1078
	function build_form() {
1079 f5e511d3 Ermal
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
1080 dbaf21d4 Renato Botelho
                $form .= gettext("Enable/Disable");
1081 f5e511d3 Ermal
                $form .= "<br/></td><td class=\"vncellreq\">";
1082 34a3694b Ermal
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
1083
                if ($this->GetEnabled() == "on")
1084
                        $form .=  " CHECKED";
1085 dbaf21d4 Renato Botelho
                $form .= " ><span class=\"vexpl\"> " . gettext("Enable/Disable queue and its children") . "</span>";
1086 34a3694b Ermal
                $form .= "</td></tr>";
1087 f5881023 Ermal Lu?i
		$form .= "<tr>";
1088 f5e511d3 Ermal
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">";
1089 197bfe96 Ermal Luçi
		$form .= "Queue Name</td><td width=\"78%\" class=\"vtable\">";
1090 e2e54400 Ermal Luçi
		$form .= "<input name=\"name\" type=\"text\" id=\"name\" class=\"formfld unknown\" size=\"15\" maxlength=\"15\" value=\"";
1091 197bfe96 Ermal Luçi
		$form .= htmlspecialchars($this->GetQname());
1092
		$form .= "\">";
1093 dbaf21d4 Renato Botelho
		$form .= "<br /> <span class=\"vexpl\">" . gettext("Enter the name of the queue here.  Do not use spaces and limit the size to 15 characters.");
1094 f5e511d3 Ermal
		$form .= "</span><br /></td>";
1095 197bfe96 Ermal Luçi
		$form .= "</tr><tr>";
1096 f5e511d3 Ermal
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">Priority</td>";
1097 f5881023 Ermal Lu?i
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"priority\" type=\"text\" id=\"priority\" size=\"5\" value=\"";
1098
		$form .= htmlspecialchars($this->GetQpriority());
1099
		$form .= "\">";
1100 dbaf21d4 Renato Botelho
		$form .= "<br> <span class=\"vexpl\">" . gettext("For hfsc, the range is 0 to 7. The default is 1.  Hfsc queues with a higher priority are preferred in the case of overload.") . "</span></td>";
1101 f5881023 Ermal Lu?i
		$form .= "</tr>";
1102 f5e511d3 Ermal
		$form .= "<tr>";
1103 dbaf21d4 Renato Botelho
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">" . gettext("Queue limit") . "</td>";
1104 f5e511d3 Ermal
		$form .= "<td width=\"78%\" class=\"vtable\"> <input name=\"qlimit\" type=\"text\" id=\"qlimit\" size=\"8\" value=\"";
1105 f5881023 Ermal Lu?i
		$form .= htmlspecialchars($this->GetQlimit());
1106
		$form .= "\">";
1107 dbaf21d4 Renato Botelho
		$form .= "<br> <span class=\"vexpl\">" . gettext("Queue limit in packets per second."); 
1108 f5881023 Ermal Lu?i
		$form .= "</span></td>";
1109
		$form .= "<tr>";
1110 dbaf21d4 Renato Botelho
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncell\">" . gettext("Scheduler options") . "</td>";
1111 f5881023 Ermal Lu?i
		$form .= "<td width=\"78%\" class=\"vtable\">";
1112
		$tmpvalue = $this->GetDefault();	
1113
		if (!empty($tmpvalue)) { 
1114
			$form .= "<input type=\"checkbox\" id=\"default\" CHECKED name=\"default\" value=\"default\"";
1115 dbaf21d4 Renato Botelho
			$form .= "> " . gettext("Default queue") . "<br>";
1116 cedae3d3 Ermal Luçi
		} else {
1117 f5881023 Ermal Lu?i
			$form .= "<input type=\"checkbox\" id=\"default\" name=\"default\" value=\"default\"";
1118 dbaf21d4 Renato Botelho
			$form .= "> " . gettext("Default queue") . "<br>";
1119 197bfe96 Ermal Luçi
		}
1120 f5881023 Ermal Lu?i
		$form .= "<input type=\"checkbox\" id=\"red\" name=\"red\" value=\"red\" ";
1121
		$tmpvalue = $this->GetRed();
1122
		if(!empty($tmpvalue)) 
1123 197bfe96 Ermal Luçi
			$form .=  " CHECKED";
1124 dbaf21d4 Renato Botelho
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#red\">" . gettext("Random Early Detection") . "</a><br>";
1125 f5881023 Ermal Lu?i
		$form .= "<input type=\"checkbox\" id=\"rio\" name=\"rio\" value=\"rio\"";
1126
		$tmpvalue = $this->GetRio();
1127
		if(!empty($tmpvalue)) 
1128 197bfe96 Ermal Luçi
			$form .=  " CHECKED";
1129 dbaf21d4 Renato Botelho
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#rio\">" . gettext("Random Early Detection In and Out") . "</a><br>";
1130 f5881023 Ermal Lu?i
		$form .= "<input type=\"checkbox\" id=\"ecn\" name=\"ecn\" value=\"ecn\"";
1131
		$tmpvalue = $this->GetEcn();
1132
		if(!empty($tmpvalue)) 
1133 197bfe96 Ermal Luçi
			$form .=  " CHECKED";
1134 dbaf21d4 Renato Botelho
		$form .= "> <a target=\"_new\" href=\"http://www.openbsd.org/faq/pf/queueing.html#ecn\">" . gettext("Explicit Congestion Notification") . "</a><br>";
1135
		$form .= "<span class=\"vexpl\"><br>" . gettext("Select options for this queue");
1136 f5881023 Ermal Lu?i
		$form .= "</tr><tr>";
1137 dbaf21d4 Renato Botelho
		$form .= "<td width=\"22%\" class=\"vncellreq\">" . gettext("Description") . "</td>";
1138 197bfe96 Ermal Luçi
		$form .= "<td width=\"78%\" class=\"vtable\">";
1139
		$form .= "<input type=\"text\" name=\"description\" size=\"50%\" class=\"formfld unknown\" value=\"" . $this->GetDescription() . "\"  >";
1140
		$form .= "</td></tr>";
1141
		$form .= "<input type=\"hidden\" name=\"interface\" id=\"interface\"";
1142 f5881023 Ermal Lu?i
		$form .= " value=\"".$this->GetInterface()."\">";
1143 197bfe96 Ermal Luçi
1144
		return $form;
1145 f5881023 Ermal Lu?i
	}
1146 197bfe96 Ermal Luçi
1147
	function build_shortform() {
1148
		/* XXX: Hacks in site. Mostly layer violations!  */
1149
		global $g, $altq_list_queues;
1150
1151
		$altq =& $altq_list_queues[$this->GetInterface()];
1152
		if ($altq)
1153
			$scheduler = ": " . $altq->GetScheduler();
1154 f5881023 Ermal Lu?i
		$form = "<tr><td width=\"20%\" class=\"vtable\">";
1155 92125c97 Ermal Luçi
		$form .= "<a href=\"firewall_shaper.php?interface" . $this->GetInterface() . "&queue=" . $this->GetInterface()."&action=show\">".$this->GetInterface().": ".$scheduler."</a>";
1156
		$form .= "</td></tr>";
1157 197bfe96 Ermal Luçi
		/* 
1158
		 * XXX: Hack in sight maybe fix with a class that wraps all
1159 92125c97 Ermal Luçi
		 * of this layer violations
1160 197bfe96 Ermal Luçi
		 */
1161
		$form .= "<tr>";
1162
		$form .= "<td width=\"50%\" class=\"vncellreq\">";
1163 dbaf21d4 Renato Botelho
		$form .= gettext("Bandwidth:") . " " . $this->GetBandwidth().$this->GetBwscale();
1164 197bfe96 Ermal Luçi
		$form .= "</td><td width=\"50%\"></td></tr>";
1165
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1166 f5881023 Ermal Lu?i
		$tmpvalue = $this->GetQpriority();
1167
		if (!empty($tmpvalue))
1168 dbaf21d4 Renato Botelho
			$form .= gettext("Priority: on") . " </td></tr>";
1169 f5881023 Ermal Lu?i
		$tmpvalue = $this->GetDefault();
1170
		if (!empty($tmpvalue))
1171 dbaf21d4 Renato Botelho
			$form .= "<tr><td class=\"vncellreq\">" . gettext("Default: on") . " </td></tr>";
1172 197bfe96 Ermal Luçi
		$form .= "<tr><td width=\"20%\" class=\"vncellreq\">";
1173
		$form .= "<a href=\"firewall_shaper_queues.php?interface=";
1174 f5881023 Ermal Lu?i
		$form .= $this->GetInterface() . "&queue=";
1175
		$form .= $this->GetQname() . "&action=delete\">";
1176
		$form .= "<img src=\"";
1177
		$form .= "./themes/".$g['theme']."/images/icons/icon_x.gif\"";
1178 dbaf21d4 Renato Botelho
		$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("Delete queue from interface") . "\">";
1179
		$form .= "<span>" . gettext("Delete queue from interface") . "</span></a></td></tr>";
1180 197bfe96 Ermal Luçi
		
1181
		return $form;
1182 061f78b1 Bill Marquette
1183 197bfe96 Ermal Luçi
	}
1184 061f78b1 Bill Marquette
1185 92125c97 Ermal Luçi
		function update_altq_queue_data(&$q) { 
1186 197bfe96 Ermal Luçi
		$this->ReadConfig($q);
1187
	}
1188 061f78b1 Bill Marquette
1189 f5881023 Ermal Lu?i
	function wconfig() {
1190
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1191 197bfe96 Ermal Luçi
		if (!is_array($cflink))
1192
			$cflink = array();
1193
		$cflink['name'] = $this->GetQname();
1194 f5881023 Ermal Lu?i
		$cflink['interface'] = $this->GetInterface();
1195
		$cflink['qlimit'] = trim($this->GetQlimit());
1196
		if (empty($cflink['qlimit']))
1197
			unset($cflink['qlimit']);
1198
		$cflink['priority'] = trim($this->GetQpriority());
1199
		if (empty($cflink['priority']))
1200
			unset($cflink['priority']);
1201
		$cflink['description'] = trim($this->GetDescription());
1202
		if (empty($cflink['description']))
1203
			unset($cflink['description']);
1204
		$cflink['enabled'] = trim($this->GetEnabled());
1205
		if (empty($cflink['enabled']))
1206
			unset($cflink['enabled']);
1207
		$cflink['default'] = trim($this->GetDefault());
1208
		if (empty($cflink['default']))
1209
			unset($cflink['default']);
1210
		$cflink['red'] = trim($this->GetRed());
1211
		if (empty($cflink['red']))
1212
			unset($cflink['red']);
1213
		$cflink['rio'] = trim($this->GetRio());
1214
		if (empty($cflink['rio']))
1215
			unset($cflink['rio']);
1216
		$cflink['ecn'] = trim($this->GetEcn());
1217
		if (empty($cflink['ecn']))
1218
			unset($cflink['ecn']);
1219 061f78b1 Bill Marquette
	}
1220
}
1221
1222 197bfe96 Ermal Luçi
class hfsc_queue extends priq_queue {
1223 f5881023 Ermal Lu?i
	/* realtime */
1224 197bfe96 Ermal Luçi
	var $realtime;
1225 f5881023 Ermal Lu?i
	var $r_m1;
1226
	var $r_d;
1227
	var $r_m2;
1228
	/* linkshare */
1229 197bfe96 Ermal Luçi
	var $linkshare;
1230 f5881023 Ermal Lu?i
	var $l_m1;
1231
	var $l_d;
1232
	var $l_m2;
1233
	/* upperlimit */
1234 197bfe96 Ermal Luçi
	var $upperlimit;
1235 f5881023 Ermal Lu?i
	var $u_m1;
1236
	var $u_d;
1237
	var $u_m2;
1238 197bfe96 Ermal Luçi
1239 f5881023 Ermal Lu?i
	/*
1240
	 * HFSC can have nested queues.
1241
	 */
1242 70b139a3 Chris Buechler
	function CanHaveChildren() {
1243 f5881023 Ermal Lu?i
		return true;
1244
	}
1245 197bfe96 Ermal Luçi
	function GetRealtime() {
1246 92125c97 Ermal Luçi
           return $this->realtime;
1247 f5881023 Ermal Lu?i
	}
1248
	function GetR_m1() {
1249
		return $this->r_m1;
1250
	}
1251
	function GetR_d() {
1252
		return $this->r_d;
1253
	}
1254
	function GetR_m2() {
1255
		return $this->r_m2;
1256
	}
1257
	function SetRealtime() {
1258
		$this->realtime = "on";
1259
	}
1260
	function DisableRealtime() {
1261
		$this->realtime = "";
1262
	}
1263
	function SetR_m1($value) {
1264
		$this->r_m1 = $value;
1265
	}
1266
	function SetR_d($value) {
1267
		$this->r_d = $value;
1268
	}
1269
	function SetR_m2($value) {
1270
		$this->r_m2 = $value;
1271
	}
1272
	function GetLinkshare() {
1273
		return $this->linkshare;
1274
	}
1275
	function DisableLinkshare() {
1276
		$this->linkshare = "";
1277
	}
1278
	function GetL_m1() {
1279
		return $this->l_m1;
1280
	}
1281
	function GetL_d() {
1282
		return $this->l_d;
1283
	}
1284
	function GetL_m2() {
1285
		return $this->l_m2;
1286
	}
1287
	function SetLinkshare() {
1288
		$this->linkshare = "on";
1289
	}
1290
	function SetL_m1($value) {
1291
		$this->l_m1 = $value;
1292
	}
1293
	function SetL_d($value) {
1294
		$this->l_d = $value;
1295
	}
1296
	function SetL_m2($value) {
1297
		$this->l_m2 = $value;
1298
	}
1299
	function GetUpperlimit() {
1300
		return $this->upperlimit;
1301
	}
1302
	function GetU_m1() {
1303
		return $this->u_m1;
1304
	}
1305
	function GetU_d() {
1306
		return $this->u_d;
1307
	}
1308
	function GetU_m2() {
1309
		return $this->u_m2;
1310
	}
1311
	function SetUpperlimit() {
1312
		$this->upperlimit = "on";
1313
	}
1314
	function DisableUpperlimit() {
1315
		$this->upperlimit = "";
1316
	}
1317
	function SetU_m1($value) {
1318
		$this->u_m1 = $value;
1319
	}
1320
	function SetU_d($value) {
1321
		$this->u_d = $value;
1322
	}
1323
	function SetU_m2($value) {
1324
		$this->u_m2 = $value;
1325
	}
1326
1327
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
1328
1329
		if (!is_array($this->subqueues))
1330
			$this->subqueues = array();
1331 62150088 Ermal Lu?i
		$q =& new hfsc_queue();
1332 f5881023 Ermal Lu?i
		$q->SetInterface($this->GetInterface());
1333
		$q->SetParent(&$this);
1334
		$q->ReadConfig($qname);
1335
		$q->validate_input($qname, $input_errors);
1336
		if (count($input_errors)) {
1337 92125c97 Ermal Luçi
			return $q;
1338
		}
1339 197bfe96 Ermal Luçi
1340 f5881023 Ermal Lu?i
		$q->SetEnabled("on");
1341
		$q->SetLink($path);
1342
		switch ($q->GetBwscale()) {
1343
		case "%":
1344
			$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
1345
			break;
1346
		default:
1347
			$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
1348
			break;
1349
		}
1350
		$q->SetAvailableBandwidth($myBw);
1351
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
1352
1353
		$this->subqueues[$q->GetQname()] =& $q; //new hfsc_queue()
1354
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
1355
		if (is_array($qname['queue'])) {
1356
			foreach ($qname['queue'] as $key1 => $que) {
1357
				array_push($path, $key1);
1358
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
1359
				array_pop($path);
1360
			}
1361
		}
1362
	
1363
		return $q;
1364
	}
1365 a843b04f Ermal Luçi
1366 f5881023 Ermal Lu?i
        function copy_queue($interface, &$cflink) {
1367 a843b04f Ermal Luçi
1368 f5881023 Ermal Lu?i
		$cflink['name'] = $this->GetQname();
1369
		$cflink['interface'] = $interface;
1370
		$cflink['qlimit'] = trim($this->GetQlimit());
1371
		if (empty($cflink['qlimit']))
1372
			unset($cflink['qlimit']);
1373
		$cflink['priority'] = trim($this->GetQpriority());
1374
		if (empty($cflink['priority']))
1375
			unset($cflink['priority']);
1376
		$cflink['description'] = trim($this->GetDescription());
1377
		if (empty($cflink['description']))
1378
			unset($cflink['description']);
1379
		$cflink['bandwidth'] = $this->GetBandwidth();
1380
		$cflink['bandwidthtype'] = $this->GetBwscale();
1381
		$cflink['enabled'] = trim($this->GetEnabled());
1382
		if (empty($cflink['enabled']))
1383
			unset($cflink['enabled']);
1384
		$cflink['default'] = trim($this->GetDefault());
1385
		if (empty($cflink['default']))
1386
			unset($cflink['default']);
1387
		$cflink['red'] = trim($this->GetRed());
1388
		if (empty($cflink['red']))
1389
			unset($cflink['red']);
1390
		$cflink['rio'] = trim($this->GetRio());
1391
		if (empty($cflink['rio']))
1392
			unset($cflink['rio']);
1393
		$cflink['ecn'] = trim($this->GetEcn());
1394
		if (empty($cflink['ecn']))
1395
			unset($cflink['ecn']);
1396
		if ($this->GetLinkshare() <> "") {
1397
			if ($this->GetL_m1() <> "") {
1398
				$cflink['linkshare1'] = $this->GetL_m1();
1399
				$cflink['linkshare2'] = $this->GetL_d();
1400
				$cflink['linkshare'] = "on";
1401
			} else {
1402
				unset($cflink['linkshare1']);
1403
				unset($cflink['linkshare2']);
1404
				unset($cflink['linkshare']);
1405 fce82460 Ermal Luçi
			}
1406 f5881023 Ermal Lu?i
			if ($this->GetL_m2() <> "") {
1407
				$cflink['linkshare3'] = $this->GetL_m2();
1408
				$cflink['linkshare'] = "on";
1409
			} else {
1410
				unset($cflink['linkshare3']);
1411
				unset($cflink['linkshare']);
1412 92125c97 Ermal Luçi
			}
1413 f5881023 Ermal Lu?i
		}
1414
		if ($this->GetRealtime() <> "") {
1415
			if ($this->GetR_m1() <> "") {
1416
				$cflink['realtime1'] = $this->GetR_m1();
1417
				$cflink['realtime2'] = $this->GetR_d();
1418
				$cflink['realtime'] = "on";
1419
			} else {
1420
				unset($cflink['realtime1']);
1421
                                unset($cflink['realtime2']);
1422
                                unset($cflink['realtime']);
1423
			}
1424
			if ($this->GetR_m2() <> "") {
1425
				$cflink['realtime3'] = $this->GetR_m2();
1426
				$cflink['realtime'] = "on";
1427
			} else {
1428
				unset($cflink['realtime3']);
1429
				unset($cflink['realtime']);
1430 92125c97 Ermal Luçi
			}
1431 b7ff5e40 Scott Ullrich
		}
1432 f5881023 Ermal Lu?i
		if ($this->GetUpperlimit() <> "") {
1433
			if ($this->GetU_m1() <> "") {
1434
				$cflink['upperlimit1'] = $this->GetU_m1();
1435
				$cflink['upperlimit2'] = $this->GetU_d();
1436
				$cflink['upperlimit'] = "on";
1437
			} else {
1438
				unset($cflink['upperlimit']);
1439
				unset($cflink['upperlimit1']);
1440
				unset($cflink['upperlimit2']);
1441
			}
1442
			if ($this->GetU_m2() <> "") {
1443
				$cflink['upperlimit3'] = $this->GetU_m2();
1444
				$cflink['upperlimit'] = "on";
1445
			} else {
1446
				unset($cflink['upperlimit3']);
1447
				unset($cflink['upperlimit']);
1448
			}
1449 92125c97 Ermal Luçi
		}
1450 40de74f5 Ermal Luçi
1451 f5881023 Ermal Lu?i
		if (is_array($this->subqueues)) {
1452
			$cflinkp['queue'] = array();
1453
			foreach ($this->subqueues as $q) {
1454
				$cflink['queue'][$q->GetQname()] = array();
1455
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
1456
			}
1457
		}
1458
	}
1459
1460
	function delete_queue() { 
1461
		unref_on_altq_queue_list($this->GetQname());
1462
		$tmpvalue = $this->GetDefault();
1463
		if (!empty($tmpvalue)) 
1464
			altq_set_default_queue($this->GetInterface(), "false");
1465
		cleanup_queue_from_rules($this->GetQname());
1466
		$parent =& $this->GetParent();
1467
		foreach ($this->subqueues as $q)  {
1468
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
1469
			$q->delete_queue();
1470
		}
1471
		unset_object_by_reference($this->GetLink());
1472
	}
1473
1474
	/*
1475
	 * Should search even its children
1476
	 */
1477
	function &find_queue($interface, $qname) {
1478
		if ($qname == $this->GetQname()) 
1479
			return $this;
1480
1481
		foreach ($this->subqueues as $q) {
1482
			$result =& $q->find_queue("", $qname);
1483
			if ($result)
1484
				return $result;
1485
		}
1486
	}
1487
1488
	function &find_parentqueue($interface, $qname) {
1489
		if ($this->subqueues[$qname]) 
1490
			return $this;
1491
		foreach ($this->subqueues as $q) {
1492
			$result = $q->find_parentqueue("", $qname);
1493
			if ($result)
1494
				return $result;
1495
		}
1496
	}
1497
	
1498
	function validate_input($data, &$input_errors) {
1499
		parent::validate_input($data, $input_errors);
1500
		
1501
		$reqdfields[] = "bandwidth";
1502 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidth");
1503 f5881023 Ermal Lu?i
		$reqdfields[] = "bandwidthtype";
1504 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidthtype");
1505 f5881023 Ermal Lu?i
1506
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
1507
		
1508
		if (isset($data['linkshare3']) && $data['linkshare3'] <> "") {
1509
			if ($data['bandwidth'] && (!is_numeric($data['bandwidth'])))
1510 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Bandwidth must be an integer.");
1511 f5881023 Ermal Lu?i
1512 dbaf21d4 Renato Botelho
			if ($data['bandwidth'] < 0)
1513
				$input_errors[] = gettext("Bandwidth cannot be negative.");
1514 f5881023 Ermal Lu?i
1515
			if ($data['bandwidthtype'] == "%") {
1516
				if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
1517 dbaf21d4 Renato Botelho
					$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
1518 f5881023 Ermal Lu?i
			}
1519
		/*
1520
			$parent =& $this->GetParent();
1521
			switch ($data['bandwidthtype']) {
1522
			case "%":
1523
				$myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
1524
			default:
1525
				$mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
1526
				break;
1527
			}
1528
			if ($parent->GetAvailableBandwidth() < $myBw)
1529
				$input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
1530
		*/
1531 92125c97 Ermal Luçi
		}
1532
1533 197bfe96 Ermal Luçi
		if ($data['upperlimit1'] <> "" &&  $data['upperlimit2'] == "")
1534 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("upperlimit service curve defined but missing (d) value");
1535 40de74f5 Ermal Luçi
		if ($data['upperlimit2'] <> "" &&  $data['upperlimit1'] == "")
1536 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("upperlimit service curve defined but missing initial bandwidth (m1) value");
1537 40de74f5 Ermal Luçi
		if ($data['upperlimit1'] <> "" && !is_valid_shaperbw($data['upperlimit1']))
1538 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("upperlimit m1 value needs to be Kb, Mb, Gb, or %");
1539 40de74f5 Ermal Luçi
		if ($data['upperlimit2'] <> "" && !is_numeric($data['upperlimit2']))
1540 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("upperlimit d value needs to be numeric");
1541 40de74f5 Ermal Luçi
		if ($data['upperlimit3'] <> "" && !is_valid_shaperbw($data['upperlimit3']))
1542 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("upperlimit m2 value needs to be Kb, Mb, Gb, or %");
1543 a843b04f Ermal Luçi
1544 f5881023 Ermal Lu?i
		/*
1545 40de74f5 Ermal Luçi
		if (isset($data['upperlimit']) && $data['upperlimit3'] <> "" && $data['upperlimit1'] <> "") {
1546 f5881023 Ermal Lu?i
			$bw_1 = get_hfsc_bandwidth($this, $data['upperlimit1']);
1547
			$bw_2 = get_hfsc_bandwidth($this, $data['upperlimit3']);
1548
			if (floatval($bw_1) < floatval($bw_2)) 
1549
				$input_errors[] = ("upperlimit m1 cannot be smaller than m2");
1550 40de74f5 Ermal Luçi
1551 f5881023 Ermal Lu?i
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1552
				$input_errors[] = ("upperlimit specification excedd 80% of allowable allocation.");
1553 40de74f5 Ermal Luçi
		}
1554 f5881023 Ermal Lu?i
		*/
1555 40de74f5 Ermal Luçi
		if ($data['linkshare1'] <> "" &&  $data['linkshare2'] == "")
1556 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("linkshare service curve defined but missing (d) value");
1557 40de74f5 Ermal Luçi
		if ($data['linkshare2'] <> "" &&  $data['linkshare1'] == "")
1558 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("linkshare service curve defined but missing initial bandwidth (m1) value");
1559 40de74f5 Ermal Luçi
		if ($data['linkshare1'] <> "" && !is_valid_shaperbw($data['linkshare1']))
1560 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("linkshare m1 value needs to be Kb, Mb, Gb, or %");
1561 40de74f5 Ermal Luçi
		if ($data['linkshare2'] <> "" && !is_numeric($data['linkshare2']))
1562 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("linkshare d value needs to be numeric");
1563 40de74f5 Ermal Luçi
		if ($data['linkshare3'] <> "" && !is_valid_shaperbw($data['linkshare3']))
1564 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("linkshare m2 value needs to be Kb, Mb, Gb, or %");
1565 40de74f5 Ermal Luçi
		if ($data['realtime1'] <> "" &&  $data['realtime2'] == "")
1566 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("realtime service curve defined but missing (d) value");
1567 40de74f5 Ermal Luçi
		if ($data['realtime2'] <> "" &&  $data['realtime1'] == "")
1568 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("realtime service curve defined but missing initial bandwidth (m1) value");
1569 40de74f5 Ermal Luçi
1570 f5881023 Ermal Lu?i
		/*
1571 a843b04f Ermal Luçi
		if (isset($data['linkshare']) && $data['linkshare3'] <> "" && $data['linkshare1'] <> "" && 0) {
1572 f5881023 Ermal Lu?i
			$bw_1 = get_hfsc_bandwidth($this, $data['linkshare1']);
1573
                	$bw_2 = get_hfsc_bandwidth($this, $data['linkshare3']);
1574
                	if (floatval($bw_1) < floatval($bw_2))
1575
                        	$input_errors[] = ("linkshare m1 cannot be smaller than m2");
1576 40de74f5 Ermal Luçi
1577 f5881023 Ermal Lu?i
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1578
                        	$input_errors[] = ("linkshare specification excedd 80% of allowable allocation.");
1579 40de74f5 Ermal Luçi
		}
1580 f5881023 Ermal Lu?i
		*/
1581 a2f70da3 Ermal Luçi
1582 40de74f5 Ermal Luçi
		if ($data['realtime1'] <> "" && !is_valid_shaperbw($data['realtime1']))
1583 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("realtime m1 value needs to be Kb, Mb, Gb, or %");
1584 40de74f5 Ermal Luçi
		if ($data['realtime2'] <> "" && !is_numeric($data['realtime2']))
1585 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("realtime d value needs to be numeric");
1586 40de74f5 Ermal Luçi
		if ($data['realtime3'] <> "" && !is_valid_shaperbw($data['realtime3']))
1587 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("realtime m2 value needs to be Kb, Mb, Gb, or %");
1588 40de74f5 Ermal Luçi
1589 f5881023 Ermal Lu?i
		/*
1590 a843b04f Ermal Luçi
		if (isset($data['realtime']) && $data['realtime3'] <> "" && $data['realtime1'] <> "" && 0) {
1591 f5881023 Ermal Lu?i
			$bw_1 = get_hfsc_bandwidth($this, $data['realtime1']);
1592
                	$bw_2 = get_hfsc_bandwidth($this, $data['realtime3']);
1593
                	if (floatval($bw_1) < floatval($bw_2))
1594
                        	$input_errors[] = ("realtime m1 cannot be smaller than m2");
1595 40de74f5 Ermal Luçi
1596 f5881023 Ermal Lu?i
			if (get_interface_bandwidth($this) < (0.8 * (floatval($bw_1) + floatval($bw_2))))
1597
				$input_errors[] = ("realtime specification excedd 80% of allowable allocation.");
1598 40de74f5 Ermal Luçi
		}
1599 f5881023 Ermal Lu?i
		*/
1600 f1227b84 Scott Ullrich
1601 061f78b1 Bill Marquette
	}
1602
1603 f5881023 Ermal Lu?i
	function ReadConfig(&$cflink) {
1604
		if (!empty($cflink['linkshare'])) {
1605
			if (!empty($cflink['linkshare1'])) {
1606 92125c97 Ermal Luçi
				$this->SetL_m1($cflink['linkshare1']);
1607
                                $this->SetL_d($cflink['linkshare2']);
1608
				$this->SetLinkshare();
1609 7ed9c6ac Ermal
			} else {
1610
				$this->SetL_m1("");
1611
                                $this->SetL_d("");
1612
				$this->DisableLinkshare();
1613 92125c97 Ermal Luçi
			}
1614 f5881023 Ermal Lu?i
			if (!empty($cflink['linkshare3'])) {
1615 92125c97 Ermal Luçi
                                $this->SetL_m2($cflink['linkshare3']);
1616
				$this->SetLinkshare();
1617
			}
1618 f5881023 Ermal Lu?i
		} else
1619
			$this->DisableLinkshare();
1620
		if (!empty($cflink['realtime'])) {
1621
                        if (!empty($cflink['realtime1'])) {
1622 92125c97 Ermal Luçi
                                $this->SetR_m1($cflink['realtime1']);
1623
                                $this->SetR_d($cflink['realtime2']);
1624
				$this->SetRealtime();
1625 7ed9c6ac Ermal
			} else {
1626
                                $this->SetR_m1("");
1627
                                $this->SetR_d("");
1628
				$this->DisableRealtime();
1629 92125c97 Ermal Luçi
			}
1630 f5881023 Ermal Lu?i
                        if (!empty($cflink['realtime3'])) {
1631 92125c97 Ermal Luçi
                                $this->SetR_m2($cflink['realtime3']);
1632
				$this->SetRealtime();
1633
			}
1634 f5881023 Ermal Lu?i
		} else
1635
			$this->DisableRealtime(); 
1636
		if (!empty($cflink['upperlimit'])) {
1637
                        if (!empty($cflink['upperlimit1'])) {
1638 92125c97 Ermal Luçi
                                $this->SetU_m1($cflink['upperlimit1']);
1639
                                $this->SetU_d($cflink['upperlimit2']);
1640
				$this->SetUpperlimit();
1641 7ed9c6ac Ermal
			} else {
1642
                                $this->SetU_m1("");
1643
                                $this->SetU_d("");
1644
				$this->DisableUpperlimit();
1645 92125c97 Ermal Luçi
			}
1646 f5881023 Ermal Lu?i
                        if (!empty($cflink['upperlimit3'])) {
1647 92125c97 Ermal Luçi
                                $this->SetU_m2($cflink['upperlimit3']);
1648
				$this->SetUpperlimit();
1649
			}
1650 f5881023 Ermal Lu?i
		} else
1651
			$this->DisableUpperlimit();
1652 92125c97 Ermal Luçi
		parent::ReadConfig($cflink);
1653 f5881023 Ermal Lu?i
	}
1654 197bfe96 Ermal Luçi
1655
	function build_tree() {
1656
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface() ."&queue=" . $this->GetQname()."&action=show"; 
1657
		$tree .= "\" ";
1658 f5881023 Ermal Lu?i
		$tmpvalue = $this->GetDefault();
1659
		if (!empty($tmpvalue))
1660
			$tree .= " class=\"navlnk\"";
1661 197bfe96 Ermal Luçi
		$tree .= " >" . $this->GetQname() . "</a>";
1662
		if (is_array($this->subqueues)) {
1663
			$tree .= "<ul>";
1664
			foreach ($this->subqueues as $q)  {
1665
				$tree .= $q->build_tree();
1666
			}	
1667
			$tree .= "</ul>";
1668
		}
1669
		$tree .= "</li>";
1670
		return $tree;
1671 061f78b1 Bill Marquette
	}
1672
1673 f5881023 Ermal Lu?i
	/* Even this should take children into consideration */
1674
	function build_rules() {
1675 197bfe96 Ermal Luçi
1676 f5881023 Ermal Lu?i
		$pfq_rule = " queue ". $this->qname;
1677
		if ($this->GetInterface())
1678
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
1679 197bfe96 Ermal Luçi
		if ($this->GetBandwidth() && $this->GetBwscale())
1680 f5881023 Ermal Lu?i
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
1681
				
1682
		$tmpvalue = $this->GetQlimit();
1683
		if (!empty($tmpvalue))
1684
			$pfq_rule .= " qlimit " . $this->GetQlimit();
1685
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetRealtime() <> "" || $this->GetLinkshare() <> "" || $this->GetUpperlimit() <> "") {
1686
			$pfq_rule .= " hfsc ( ";
1687
			$tmpvalue = $this->GetRed();
1688
			if (!empty($tmpvalue)) {
1689
				$comma = 1;
1690
				$pfq_rule .= " red ";
1691
			}
1692
			
1693
			$tmpvalue = $this->GetRio();
1694
			if (!empty($tmpvalue)) {
1695 197bfe96 Ermal Luçi
				if ($comma) 
1696 f5881023 Ermal Lu?i
					$pfq_rule .= " ,";
1697
				$comma = 1;
1698
				$pfq_rule .= " rio ";
1699
			}
1700
			$tmpvalue = $this->GetEcn();
1701
			if (!empty($tmpvalue)) {
1702
				if ($comma) 
1703
					$pfq_rule .= " ,";
1704
				$comma = 1;
1705
				$pfq_rule .= " ecn ";
1706
			}
1707
			$tmpvalue = $this->GetDefault();
1708
			if (!empty($tmpvalue)) {
1709
				if ($comma)
1710
					$pfq_rule .= " ,";
1711
				$comma = 1;
1712
				$pfq_rule .= " default ";
1713
			}
1714
1715
			if ($this->GetRealtime() <> "")  {
1716
				if ($comma) 
1717
					$pfq_rule .= " , ";
1718 92125c97 Ermal Luçi
				if ($this->GetR_m1()  <> "" && $this->GetR_d() <> "" && $this->GetR_m2() <> "")
1719 f5881023 Ermal Lu?i
					$pfq_rule .= " realtime (".$this->GetR_m1() . ", " . $this->GetR_d().", ". $this->GetR_m2() .") ";
1720 92125c97 Ermal Luçi
				else  if ($this->GetR_m2() <> "")
1721
					$pfq_rule .= " realtime " . $this->GetR_m2();
1722 197bfe96 Ermal Luçi
				$comma = 1;
1723
			}
1724 f5881023 Ermal Lu?i
			if ($this->GetLinkshare() <> "") {
1725
				if ($comma)
1726 197bfe96 Ermal Luçi
					$pfq_rule .= " ,";
1727 92125c97 Ermal Luçi
				if ($this->GetL_m1() <> "" && $this->GetL_d() <> "" && $this->GetL_m2() <> "")
1728 f5881023 Ermal Lu?i
					$pfq_rule .= " linkshare (".$this->GetL_m1(). ", ". $this->GetL_d(). ", ". $this->GetL_m2(). ") ";
1729 92125c97 Ermal Luçi
				else if ($this->GetL_m2() <> "")
1730
					$pfq_rule .= " linkshare " . $this->GetL_m2() . " ";
1731 197bfe96 Ermal Luçi
				$comma = 1;
1732
			}
1733 f5881023 Ermal Lu?i
			if ($this->GetUpperlimit() <> "") {
1734 197bfe96 Ermal Luçi
				if ($comma)
1735
					$pfq_rule .= " ,";
1736 92125c97 Ermal Luçi
				if ($this->GetU_m1() <> "" && $this->GetU_d() <> "" && $this->GetU_m2() <> "")
1737
							$pfq_rule .= " upperlimit (".$this->GetU_m1().", ". $this->GetU_d().", ". $this->GetU_m2(). ") ";
1738
				else if ($this->GetU_m2() <> "")
1739
					$pfq_rule .= " upperlimit " . $this->GetU_m2() . " ";
1740 197bfe96 Ermal Luçi
			}
1741 f5881023 Ermal Lu?i
			$pfq_rule .= " ) ";
1742
		}
1743
		if (count($this->subqueues)) {
1744
			$i = count($this->subqueues);
1745
			$pfq_rule .= " { ";
1746
			foreach ($this->subqueues as $qkey => $qnone) {
1747
				if ($i > 1) {
1748
					$i--;
1749
					$pfq_rule .= " {$qkey}, ";
1750
				} else
1751
					$pfq_rule .= " {$qkey} ";
1752
			}
1753
			$pfq_rule .= " } \n";
1754
			foreach ($this->subqueues as $q)
1755
				$pfq_rule .= $q->build_rules();
1756 92125c97 Ermal Luçi
		}
1757 197bfe96 Ermal Luçi
1758 f5881023 Ermal Lu?i
		 $pfq_rule .= " \n";
1759
			
1760
		return $pfq_rule;
1761
	}
1762
1763 197bfe96 Ermal Luçi
	function build_javascript() {
1764
		$javascript = parent::build_javascript();
1765
		$javascript .= "<script type=\"text/javascript\">";
1766
		$javascript .= "function enable_realtime(enable_over) { \n";
1767 92125c97 Ermal Luçi
		$javascript .= "if (document.iform.realtime.checked || enable_over) { \n";
1768
		$javascript .= "document.iform.realtime1.disabled = 0;\n";
1769
		$javascript .= "document.iform.realtime2.disabled = 0;\n";
1770
		$javascript .= "document.iform.realtime3.disabled = 0;\n";
1771
		$javascript .= " } else { \n";
1772
		$javascript .= "document.iform.realtime1.disabled = 1;\n";
1773
		$javascript .= "document.iform.realtime2.disabled = 1;\n";
1774
		$javascript .= "document.iform.realtime3.disabled = 1;\n";
1775
		$javascript .= " } \n";
1776 197bfe96 Ermal Luçi
		$javascript .= " } \n";
1777
		$javascript .= "function enable_linkshare(enable_over) { \n";
1778 92125c97 Ermal Luçi
		$javascript .= "if (document.iform.linkshare.checked || enable_over) { \n";
1779
		$javascript .= "document.iform.linkshare1.disabled = 0;\n";
1780
		$javascript .= "document.iform.linkshare2.disabled = 0;\n";
1781
		$javascript .= "document.iform.linkshare3.disabled = 0;\n";
1782
		$javascript .= " } else { \n";
1783
		$javascript .= "document.iform.linkshare1.disabled = 1;\n";
1784
		$javascript .= "document.iform.linkshare2.disabled = 1;\n";
1785
		$javascript .= "document.iform.linkshare3.disabled = 1;\n";
1786
		$javascript .= " } \n";
1787 197bfe96 Ermal Luçi
		$javascript .= " } \n";
1788
		$javascript .= "function enable_upperlimit(enable_over) { \n";
1789 92125c97 Ermal Luçi
		$javascript .= "if (document.iform.upperlimit.checked || enable_over) { \n";
1790
		$javascript .= "document.iform.upperlimit1.disabled = 0;\n";
1791
		$javascript .= "document.iform.upperlimit2.disabled = 0;\n";
1792
		$javascript .= "document.iform.upperlimit3.disabled = 0;\n";
1793
		$javascript .= " } else { \n";
1794
		$javascript .= "document.iform.upperlimit1.disabled = 1;\n";
1795
		$javascript .= "document.iform.upperlimit2.disabled = 1;\n";
1796
		$javascript .= "document.iform.upperlimit3.disabled = 1;\n";
1797
		$javascript .= " } \n";
1798 197bfe96 Ermal Luçi
			
1799 92125c97 Ermal Luçi
		$javascript .= "} \n";
1800 197bfe96 Ermal Luçi
		$javascript .= "</script>";
1801 92125c97 Ermal Luçi
1802 197bfe96 Ermal Luçi
		return $javascript;
1803
	}
1804 061f78b1 Bill Marquette
1805 f5881023 Ermal Lu?i
	function build_form() {
1806 42621465 Ermal
		$form = parent::build_form();
1807
		$form .= "<tr>";
1808 dbaf21d4 Renato Botelho
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
1809 f5881023 Ermal Lu?i
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
1810
		$form .= htmlspecialchars($this->GetBandwidth());
1811
		$form .= "\">";
1812
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
1813
		$form .= "<option value=\"Gb\"";
1814
		if ($this->GetBwscale() == "Gb")
1815
			$form .= " selected=\"yes\"";
1816
		$form .= ">Gbit/s</option>";
1817
		$form .= "<option value=\"Mb\"";
1818
		if ($this->GetBwscale() == "Mb")
1819
			$form .= " selected=\"yes\"";
1820
		$form .= ">Mbit/s</option>";
1821
		$form .= "<option value=\"Kb\"";
1822
		if ($this->GetBwscale() == "Kb")
1823
			$form .= " selected=\"yes\"";
1824
		$form .= ">Kbit/s</option>";
1825
		$form .= "<option value=\"\"";
1826
		if ($this->GetBwscale() == "b")
1827
			$form .= " selected=\"yes\"";
1828
		$form .= ">Bit/s</option>";
1829
		$form .= "<option value=\"%\"";
1830
		if ($this->GetBwscale() == "%")
1831
			$form .= " selected=\"yes\"";
1832
		$form .= ">%</option>";
1833
		$form .= "</select> <br>";
1834 dbaf21d4 Renato Botelho
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
1835 42621465 Ermal
		$form .= "</span></td></tr>";
1836 f5881023 Ermal Lu?i
		$form .= "<tr>";
1837 dbaf21d4 Renato Botelho
		$form .= "<td width=\"22%\" valign=\"center\" class=\"vncellreq\">" . gettext("Service Curve (sc)") . "</td>";
1838 f5881023 Ermal Lu?i
		$form .= "<td width=\"78%\" class=\"vtable\">";
1839
		$form .= "<table>";
1840
		$form .= "<tr><td>&nbsp;</td><td><center>m1</center></td><td><center>d</center></td><td><center><b>m2</b></center></td></tr>";
1841
		$form .= "<tr><td><input type=\"checkbox\" id=\"upperlimit\" name=\"upperlimit\"";
1842
		if($this->GetUpperlimit()<> "") 
1843
			$form .=  " CHECKED ";
1844
		$form .= "onChange=\"enable_upperlimit()\"> Upperlimit:</td><td><input size=\"6\" value=\"";
1845
		$form .= htmlspecialchars($this->GetU_m1());
1846
		$form .= "\" id=\"upperlimit1\" name=\"upperlimit1\" ";
1847
		if ($this->GetUpperlimit() == "")
1848
			$form .= " disabled";
1849
		$form .= "></td><td><input size=\"6\" value=\"";
1850
		$form .= htmlspecialchars($this->GetU_d());
1851
		$form .= "\" id=\"upperlimi2\" name=\"upperlimit2\" ";
1852
		if ($this->GetUpperlimit() == "")
1853
			$form .= " disabled";
1854 197bfe96 Ermal Luçi
		$form .= "></td><td><input size=\"6\" value=\"";
1855 f5881023 Ermal Lu?i
		$form .= htmlspecialchars($this->GetU_m2());
1856
		$form .= "\" id=\"upperlimit3\" name=\"upperlimit3\" ";
1857
		if ($this->GetUpperlimit() == "")
1858
			$form .= " disabled";
1859 dbaf21d4 Renato Botelho
		$form .= "></td><td>" . gettext("The maximum allowed bandwidth for the queue.") . "</td></tr>";
1860 f5881023 Ermal Lu?i
		$form .= "<tr><td><input type=\"checkbox\" id=\"realtime\" name=\"realtime\"";
1861
		if($this->GetRealtime() <> "") 
1862 197bfe96 Ermal Luçi
			$form .=  " CHECKED ";
1863 f5881023 Ermal Lu?i
		$form .= "onChange=\"enable_realtime()\"> Real time:</td><td><input size=\"6\" value=\"";
1864
		$form .= htmlspecialchars($this->GetR_m1());
1865
		$form .= "\" id=\"realtime1\" name=\"realtime1\" ";
1866
		if ($this->GetRealtime() == "")
1867
			$form .= " disabled";
1868 197bfe96 Ermal Luçi
		$form .= "></td><td><input size=\"6\" value=\"";
1869 f5881023 Ermal Lu?i
		$form .= htmlspecialchars($this->GetR_d());
1870
		$form .= "\" id=\"realtime2\" name=\"realtime2\" ";
1871
		if ($this->GetRealtime() == "")
1872
			$form .= " disabled";
1873 197bfe96 Ermal Luçi
		$form .= "></td><td><input size=\"6\" value=\"";
1874 f5881023 Ermal Lu?i
		$form .= htmlspecialchars($this->GetR_m2());
1875
		$form .= "\" id=\"realtime3\" name=\"realtime3\" ";
1876
		if ($this->GetRealtime() == "")
1877
			$form .= " disabled";
1878 dbaf21d4 Renato Botelho
		$form .= "></td><td>" . gettext("The minimum required bandwidth for the queue.") . "</td></tr>";
1879 f5881023 Ermal Lu?i
		$form .= "<tr><td><input type=\"checkbox\" id=\"linkshare\" id=\"linkshare\" name=\"linkshare\"";
1880
		if($this->GetLinkshare() <> "") 
1881 197bfe96 Ermal Luçi
			$form .=  " CHECKED ";
1882 dbaf21d4 Renato Botelho
		$form .= "onChange=\"enable_linkshare()\"> " . gettext("Link share:") . "</td><td><input size=\"6\" value=\"";
1883 f5881023 Ermal Lu?i
		$form .= htmlspecialchars($this->GetL_m1());
1884
		$form .= "\" id=\"linkshare1\" name=\"linkshare1\" ";
1885
		if ($this->GetLinkshare() == "")
1886
			$form .= " disabled";
1887 197bfe96 Ermal Luçi
		$form .= "></td><td><input size=\"6\" value=\"";
1888 f5881023 Ermal Lu?i
		$form .= htmlspecialchars($this->GetL_d());
1889
		$form .= "\" id=\"linkshare2\" name=\"linkshare2\" ";
1890
		if ($this->GetLinkshare() == "")
1891
			$form .= " disabled";
1892 197bfe96 Ermal Luçi
		$form .= "></td><td><input size=\"6\" value=\"";
1893 f5881023 Ermal Lu?i
		$form .= htmlspecialchars($this->GetL_m2());
1894
		$form .= "\" id=\"linkshare3\" name=\"linkshare3\" ";
1895
		if ($this->GetLinkshare() == "")
1896
			$form .= " disabled";
1897 dbaf21d4 Renato Botelho
		$form .= "></td><td>" . gettext("The bandwidth share of a backlogged queue - this overrides priority.") . "</td></tr>";
1898 f5881023 Ermal Lu?i
		$form .= "</table><br>";
1899 dbaf21d4 Renato Botelho
		$form .= gettext("The format for service curve specifications is (m1, d, m2).  m2 controls "
1900
		      .  "the bandwidth assigned to the queue.  m1 and d are optional and can be "
1901
		      .  "used to control the initial bandwidth assignment.  For the first d milliseconds the queue gets the bandwidth given as m1, afterwards the value "
1902
		      .  "given in m2.");
1903 f5881023 Ermal Lu?i
		$form .= "</span></td>";
1904
		$form .= "</tr>";
1905
1906
		return $form;
1907
	}
1908 197bfe96 Ermal Luçi
1909
	function update_altq_queue_data(&$data) { 
1910
		$this->ReadConfig($data);
1911 061f78b1 Bill Marquette
	}
1912
1913 92125c97 Ermal Luçi
	function wconfig() {
1914 197bfe96 Ermal Luçi
		$cflink =& get_reference_to_me_in_config($this->GetLink());
1915 92125c97 Ermal Luçi
		if (!is_array($cflink))
1916
			$cflink = array();
1917 f5881023 Ermal Lu?i
		$cflink['name'] = $this->GetQname();
1918
		$cflink['interface'] = $this->GetInterface();
1919
		$cflink['qlimit'] = trim($this->GetQlimit());
1920
		if (empty($cflink['qlimit']))
1921
			unset($cflink['qlimit']);
1922
		$cflink['priority'] = $this->GetQpriority();
1923
		if (empty($cflink['priority']))
1924
			unset($cflink['priority']);
1925
		$cflink['description'] = $this->GetDescription();
1926
		if (empty($cflink['description']))
1927
			unset($cflink['description']);
1928
		$cflink['bandwidth'] = $this->GetBandwidth();
1929
		$cflink['bandwidthtype'] = $this->GetBwscale();
1930
		$cflink['enabled'] = $this->GetEnabled();
1931
		if (empty($cflink['enabled']))
1932
			unset($cflink['enabled']);
1933
		$cflink['default'] = $this->GetDefault();
1934
		if (empty($cflink['default']))
1935
			unset($cflink['default']);
1936
		$cflink['red'] = trim($this->GetRed());
1937
		if (empty($cflink['red']))
1938
			unset($cflink['red']);
1939
		$cflink['rio'] = $this->GetRio();
1940
		if (empty($cflink['rio']))
1941
			unset($cflink['rio']);
1942
		$cflink['ecn'] = trim($this->GetEcn());
1943
		if (empty($cflink['ecn']))
1944
			unset($cflink['ecn']);
1945
		if ($this->GetLinkshare() <> "") {
1946
			if ($this->GetL_m1() <> "") {
1947
				$cflink['linkshare1'] = $this->GetL_m1();
1948
				$cflink['linkshare2'] = $this->GetL_d();
1949
				$cflink['linkshare'] = "on";
1950
			} else {
1951
				unset($cflink['linkshare']);
1952
				unset($cflink['linkshare1']);
1953
				unset($cflink['linkshare2']);
1954
			}
1955
			if ($this->GetL_m2() <> "") {
1956
				$cflink['linkshare3'] = $this->GetL_m2();
1957
				$cflink['linkshare'] = "on";
1958
			} else {
1959
				unset($cflink['linkshare']);
1960
				unset($cflink['linkshare3']);
1961
			}
1962
		} else {
1963
			unset($cflink['linkshare']);
1964
			unset($cflink['linkshare1']);
1965
			unset($cflink['linkshare2']);
1966
			unset($cflink['linkshare3']);
1967
		}
1968
		if ($this->GetRealtime() <> "") {
1969
			if ($this->GetR_m1() <> "") {
1970
				$cflink['realtime1'] = $this->GetR_m1();
1971
				$cflink['realtime2'] = $this->GetR_d();
1972
				$cflink['realtime'] = "on";
1973
			} else {
1974
				unset($cflink['realtime']);
1975
				unset($cflink['realtime1']);
1976
				unset($cflink['realtime2']);
1977
			}
1978
			if ($this->GetR_m2() <> "") {
1979
				$cflink['realtime3'] = $this->GetR_m2();
1980
				$cflink['realtime'] = "on";
1981
			} else {
1982
				unset($cflink['realtime']);
1983
				unset($cflink['realtime3']);
1984
			}
1985
		} else {
1986
			unset($cflink['realtime']);
1987
			unset($cflink['realtime1']);
1988
			unset($cflink['realtime2']);
1989
			unset($cflink['realtime3']);
1990
		}
1991
		if ($this->GetUpperlimit() <> "") {
1992
			if ($this->GetU_m1() <> "") {
1993
				$cflink['upperlimit1'] = $this->GetU_m1();
1994
				$cflink['upperlimit2'] = $this->GetU_d();
1995
				$cflink['upperlimit'] = "on";
1996
			} else {
1997
				unset($cflink['upperlimit']);
1998
				unset($cflink['upperlimit1']);
1999
				unset($cflink['upperlimit2']);
2000
			}
2001
			if ($this->GetU_m2() <> "") {
2002
				$cflink['upperlimit3'] = $this->GetU_m2();
2003
				$cflink['upperlimit'] = "on";
2004
			} else {
2005
				unset($cflink['upperlimit']);
2006
				unset($cflink['upperlimit3']);
2007
			}
2008
		} else {
2009
			unset($cflink['upperlimit']);
2010
			unset($cflink['upperlimit1']);
2011
			unset($cflink['upperlimit2']);
2012
			unset($cflink['upperlimit3']);
2013 197bfe96 Ermal Luçi
		}
2014
	}
2015 f5881023 Ermal Lu?i
}
2016 061f78b1 Bill Marquette
2017 197bfe96 Ermal Luçi
class cbq_queue extends priq_queue {
2018 f5881023 Ermal Lu?i
	var $qborrow = "";
2019 061f78b1 Bill Marquette
2020 197bfe96 Ermal Luçi
	function GetBorrow() {
2021
		return $this->qborrow;
2022 061f78b1 Bill Marquette
	}
2023 197bfe96 Ermal Luçi
	function SetBorrow($borrow) {
2024
		$this->qborrow = $borrow;
2025
	}
2026 70b139a3 Chris Buechler
	function CanHaveChildren() {
2027 f5881023 Ermal Lu?i
		return true;
2028 92125c97 Ermal Luçi
	}
2029 197bfe96 Ermal Luçi
2030 92125c97 Ermal Luçi
	function &add_queue($interface, &$qname, &$path, &$input_errors) {
2031 197bfe96 Ermal Luçi
2032
		if (!is_array($this->subqueues))
2033 f5881023 Ermal Lu?i
			$this->subqueues = array();
2034 62150088 Ermal Lu?i
		$q =& new cbq_queue();
2035 197bfe96 Ermal Luçi
		$q->SetInterface($this->GetInterface());
2036
		$q->SetParent(&$this);
2037 92125c97 Ermal Luçi
		$q->ReadConfig($qname);
2038 40de74f5 Ermal Luçi
                $q->validate_input($qname, $input_errors);
2039
                if (count($input_errors)) {
2040
                        return $q;
2041
                }
2042
                switch ($q->GetBwscale()) {
2043 f5881023 Ermal Lu?i
                case "%":
2044
                	$myBw = $this->GetAvailableBandwidth() * $qname['bandwidth'] / 100;
2045
                        break;
2046
                default:
2047
                	$myBw = $qname['bandwidth'] * get_bandwidthtype_scale($q->GetBwscale());
2048
                        break;
2049 40de74f5 Ermal Luçi
                }
2050
                $q->SetAvailableBandwidth($myBw);
2051
                $this->SetAvailableBandwidth($this->GetAvailableBandwidth() - $myBw);
2052
2053 197bfe96 Ermal Luçi
		$q->SetEnabled("on");
2054 92125c97 Ermal Luçi
		$q->SetLink($path);
2055
		$this->subqueues[$q->GetQName()] = &$q;
2056 197bfe96 Ermal Luçi
		ref_on_altq_queue_list($this->GetQname(), $q->GetQname());
2057
		if (is_array($qname['queue'])) {
2058 f5881023 Ermal Lu?i
			foreach ($qname['queue'] as $key1 => $que) {
2059
				array_push($path, $key1);
2060
				$q->add_queue($q->GetInterface(), &$que, &$path, $input_errors);
2061
				array_pop($path);
2062
			}
2063 92125c97 Ermal Luçi
		}
2064 197bfe96 Ermal Luçi
2065
		return $q;
2066 f5881023 Ermal Lu?i
	}
2067 a843b04f Ermal Luçi
2068 f5881023 Ermal Lu?i
	function copy_queue($interface, &$cflink) {
2069 a843b04f Ermal Luçi
2070 f5881023 Ermal Lu?i
		$cflink['interface'] = $interface;
2071
		$cflink['qlimit'] = trim($this->GetQlimit());
2072
		if (empty($clink['qlimit']))
2073
			unset($cflink['qlimit']);
2074
		$cflink['priority'] = trim($this->GetQpriority());
2075
		if (empty($cflink['priority']))
2076
			unset($cflink['priority']);
2077
		$cflink['name'] = $this->GetQname();
2078
		$cflink['description'] = trim($this->GetDescription());
2079
		if (empty($cflink['description']))
2080
			unset($cflink['description']);
2081
		$cflink['bandwidth'] = $this->GetBandwidth();
2082
		$cflink['bandwidthtype'] = $this->GetBwscale();
2083
		$cflink['enabled'] = trim($this->GetEnabled());
2084
		if (empty($cflink['enabled']))
2085
			unset($cflink['enabled']);
2086
		$cflink['default'] = trim($this->GetDefault());
2087
		if (empty($cflink['default']))
2088
			unset($cflink['default']);
2089
		$cflink['red'] = trim($this->GetRed());
2090
		if (empty($cflink['red']))
2091
			unset($cflink['red']);
2092
		$cflink['rio'] = trim($this->GetRio());
2093
		if (empty($cflink['rio']))
2094
			unset($cflink['rio']);
2095
		$cflink['ecn'] = trim($this->GetEcn());
2096
		if (empty($cflink['ecn']))
2097
			unset($cflink['ecn']);
2098
		$cflink['borrow'] = trim($this->GetBorrow());
2099
		if (empty($cflink['borrow']))
2100
			unset($cflink['borrow']);
2101
		if (is_array($this->queues)) {
2102
			$cflinkp['queue'] = array();
2103
			foreach ($this->subqueues as $q) {
2104
				$cflink['queue'][$q->GetQname()] = array();
2105
				$q->copy_queue($interface, &$cflink['queue'][$q->GetQname()]);
2106
			}
2107 a843b04f Ermal Luçi
		}
2108 f5881023 Ermal Lu?i
	}
2109 197bfe96 Ermal Luçi
	
2110 f5881023 Ermal Lu?i
	/*
2111
	 * Should search even its children
2112
	 */
2113
	function &find_queue($interface, $qname) {
2114
		if ($qname == $this->GetQname())
2115
			return $this;
2116
		foreach ($this->subqueues as $q) {
2117
			$result =& $q->find_queue("", $qname);
2118 197bfe96 Ermal Luçi
			if ($result)
2119 f5881023 Ermal Lu?i
				return $result;
2120 92125c97 Ermal Luçi
		}
2121 f5881023 Ermal Lu?i
	}
2122 197bfe96 Ermal Luçi
2123
	function &find_parentqueue($interface, $qname) {
2124 f5881023 Ermal Lu?i
		if ($this->subqueues[$qname])
2125
			return $this;
2126
		foreach ($this->subqueues as $q) {
2127
			$result = $q->find_parentqueue("", $qname);
2128 197bfe96 Ermal Luçi
			if ($result)
2129
				return $result;
2130
		}
2131 f5881023 Ermal Lu?i
	}
2132 197bfe96 Ermal Luçi
2133 f5881023 Ermal Lu?i
	function delete_queue() {
2134
		unref_on_altq_queue_list($this->GetQname());
2135
		if ($this->GetDefault())
2136
			altq_set_default_queue($this->GetInterface(), "false");
2137
		cleanup_queue_from_rules($this->GetQname());
2138
		foreach ($this->subqueues as $q) {
2139
		$this->SetAvailableBandwidth($this->GetAvailableBandwidth() + $q->GetAvailableBandwidth());
2140
			$q->delete_queue();
2141 92125c97 Ermal Luçi
		}
2142 f5881023 Ermal Lu?i
		unset_object_by_reference($this->GetLink());
2143
	}
2144 197bfe96 Ermal Luçi
	
2145
	function validate_input($data, &$input_errors) {
2146
		parent::validate_input($data, $input_errors);
2147 92125c97 Ermal Luçi
		
2148 197bfe96 Ermal Luçi
		if ($data['priority'] > 7)
2149 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Priority must be an integer between 1 and 7.");
2150 2c072899 jim-p
		$reqdfields[] = "bandwidth";
2151 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidth");
2152 2c072899 jim-p
		$reqdfields[] = "bandwidthtype";
2153 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidthtype");
2154 061f78b1 Bill Marquette
2155 40de74f5 Ermal Luçi
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2156 92125c97 Ermal Luçi
		
2157 40de74f5 Ermal Luçi
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2158 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Bandwidth must be an integer.");
2159 92125c97 Ermal Luçi
2160 40de74f5 Ermal Luçi
2161 f5881023 Ermal Lu?i
		if ($data['bandwidth'] < 0)
2162 dbaf21d4 Renato Botelho
                       $input_errors[] = gettext("Bandwidth cannot be negative.");
2163 40de74f5 Ermal Luçi
2164 f5881023 Ermal Lu?i
		if ($data['bandwidthtype'] == "%") {
2165
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2166 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
2167 f5881023 Ermal Lu?i
		}
2168 40de74f5 Ermal Luçi
2169 a2f70da3 Ermal Luçi
/*
2170 40de74f5 Ermal Luçi
           $parent =& $this->GetParent();
2171
           switch ($data['bandwidthtype']) {
2172
                       case "%":
2173 3a54efed Ermal Luçi
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2174 40de74f5 Ermal Luçi
                       default:
2175 a2f70da3 Ermal Luçi
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2176 40de74f5 Ermal Luçi
                             break;
2177
           }
2178 3a54efed Ermal Luçi
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2179 70b139a3 Chris Buechler
                        $input_errors[] = "The sum of the children bandwidth exceeds that of the parent.";
2180 a2f70da3 Ermal Luçi
*/
2181 92125c97 Ermal Luçi
	}
2182 f5881023 Ermal Lu?i
2183
	function ReadConfig(&$q) {
2184
		parent::ReadConfig($q);
2185
		if (!empty($q['borrow']))
2186 197bfe96 Ermal Luçi
			$this->SetBorrow("on");
2187 7ed9c6ac Ermal
		else
2188
			$this->SetBorrow("");
2189 f5881023 Ermal Lu?i
	}
2190 92125c97 Ermal Luçi
		
2191 197bfe96 Ermal Luçi
	function build_javascript() {
2192
		return parent::build_javascript();
2193
	}
2194 061f78b1 Bill Marquette
2195 197bfe96 Ermal Luçi
	function build_tree() {
2196
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . $this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2197 f5881023 Ermal Lu?i
		$tree .= "\" ";
2198
		$tmpvalue = trim($this->GetDefault());
2199
		if (!empty($tmpvalue))
2200
			$tree .= " class=\"navlnk\"";
2201
		$tree .= " >" . $this->GetQname() . "</a>";
2202
		if (is_array($this->subqueues)) {
2203
			$tree .= "<ul>";
2204
			foreach ($this->subqueues as $q)  {
2205
				$tree .= $q->build_tree();
2206
			}	
2207
			$tree .= "</ul>";
2208
		}
2209
		$tree .= "</li>";
2210
		return $tree;
2211 197bfe96 Ermal Luçi
	}
2212
		
2213 70b139a3 Chris Buechler
	/* Even this should take children into consideration */
2214 92125c97 Ermal Luçi
	function build_rules() {
2215 f5881023 Ermal Lu?i
		$pfq_rule = "queue ". $this->qname;
2216
		if ($this->GetInterface())
2217
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2218
		if ($this->GetBandwidth() && $this->GetBwscale())
2219
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2220
		$tmpvalue = $this->GetQpriority();
2221
		if (!empty($tmpvalue))
2222
			$pfq_rule .= " priority " . $this->GetQpriority();
2223
		$tmpvalue = trim($this->GetQlimit());
2224
		if (!empty($tmpvalue))
2225
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2226
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() || $this->GetEcn() || $this->GetBorrow()) {
2227
			$pfq_rule .= " cbq ( ";
2228
			$tmpvalue = trim($this->GetRed());
2229
			if (!empty($tmpvalue)) {
2230
				$comma = 1;
2231
				$pfq_rule .= " red ";
2232
			}
2233
			$tmpvalue = trim($this->GetRio());
2234
			if (!empty($tmpvalue)) {
2235
				if ($comma) 
2236
					$pfq_rule .= " ,";
2237
				$comma = 1;
2238
				$pfq_rule .= " rio ";
2239
			}
2240
			$tmpvalue = trim($this->GetEcn());
2241
			if (!empty($tmpvalue)) {
2242
				if ($comma) 
2243
					$pfq_rule .= " ,";
2244
				$comma = 1;
2245
				$pfq_rule .= " ecn ";
2246
			}
2247
			$tmpvalue = trim($this->GetDefault());
2248
			if (!empty($tmpvalue)) {
2249
				if ($comma)
2250
					$pfq_rule .= " ,";
2251
				$comma = 1;
2252
				$pfq_rule .= " default ";
2253
			}
2254
			$tmpvalue = trim($this->GetBorrow());
2255
			if (!empty($tmpvalue)) {
2256
				if ($comma)
2257
					$pfq_rule .= ", ";
2258
				$pfq_rule .= " borrow ";
2259 92125c97 Ermal Luçi
			}
2260 f5881023 Ermal Lu?i
			$pfq_rule .= " ) ";
2261
		} 
2262
		if (count($this->subqueues)) {
2263
			$i = count($this->subqueues);
2264
			$pfq_rule .= " { ";
2265
			foreach ($this->subqueues as $qkey => $qnone) {
2266
				if ($i > 1) {
2267
					$i--;
2268
					$pfq_rule .= " {$qkey}, ";
2269
				} else
2270
					$pfq_rule .= " {$qkey} ";
2271
			}
2272
			$pfq_rule .= " } \n";
2273
			foreach ($this->subqueues as $q)
2274
				$pfq_rule .= $q->build_rules();
2275
		}
2276 92125c97 Ermal Luçi
2277 f5881023 Ermal Lu?i
		$pfq_rule .= " \n";
2278
		return $pfq_rule;
2279 92125c97 Ermal Luçi
	}
2280
2281
	function build_form() {
2282 f5e511d3 Ermal
		$form = parent::build_form();
2283
		$form .= "<tr>";
2284 dbaf21d4 Renato Botelho
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
2285 92125c97 Ermal Luçi
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2286
		if ($this->GetBandwidth() > 0)
2287 f5881023 Ermal Lu?i
			$form .= htmlspecialchars($this->GetBandwidth());
2288 92125c97 Ermal Luçi
		$form .= "\">";
2289 197bfe96 Ermal Luçi
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2290 92125c97 Ermal Luçi
		$form .= "<option value=\"Gb\"";
2291
		if ($this->GetBwscale() == "Gb")
2292 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2293 92125c97 Ermal Luçi
		$form .= ">Gbit/s</option>";
2294
		$form .= "<option value=\"Mb\"";
2295
		if ($this->GetBwscale() == "Mb")
2296 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2297 92125c97 Ermal Luçi
		$form .= ">Mbit/s</option>";
2298
		$form .= "<option value=\"Kb\"";
2299
		if ($this->GetBwscale() == "Kb")
2300 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2301 92125c97 Ermal Luçi
		$form .= ">Kbit/s</option>";
2302
		$form .= "<option value=\"\"";
2303
		if ($this->GetBwscale() == "b")
2304 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2305 92125c97 Ermal Luçi
		$form .= ">Bit/s</option>";
2306
		$form .= "<option value=\"%\"";
2307
		if ($this->GetBwscale() == "%")
2308 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2309 92125c97 Ermal Luçi
		$form .= ">%</option>";
2310
		$form .= "</select> <br>";
2311 dbaf21d4 Renato Botelho
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
2312 92125c97 Ermal Luçi
		$form .= "</span></td></tr>";
2313 dbaf21d4 Renato Botelho
		$form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>";
2314 197bfe96 Ermal Luçi
		$form .= "<td class=\"vtable\"><input type=\"checkbox\" id=\"borrow\" name=\"borrow\"";
2315 f5881023 Ermal Lu?i
		if($this->GetBorrow() == "on") 
2316
			$form .=  " CHECKED ";
2317 dbaf21d4 Renato Botelho
		$form .= "> " . gettext("Borrow from other queues when available") . "<br></td></tr>";
2318 197bfe96 Ermal Luçi
2319 92125c97 Ermal Luçi
		return $form;
2320
	}
2321 197bfe96 Ermal Luçi
2322
	function update_altq_queue_data(&$data) { 
2323
		$this->ReadConfig($data);
2324
	}
2325 061f78b1 Bill Marquette
2326 92125c97 Ermal Luçi
	function wconfig() {
2327 197bfe96 Ermal Luçi
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2328 f5881023 Ermal Lu?i
		if (!is_array($cflink))
2329
			$cflink = array();
2330
		$cflink['interface'] = $this->GetInterface();
2331
		$cflink['qlimit'] = trim($this->GetQlimit());
2332
		if (empty($cflink['qlimit']))
2333
			unset($cflink['qlimit']);
2334
		$cflink['priority'] = $this->GetQpriority();
2335
		if (empty($cflink['priority']))
2336
			unset($cflink['priority']);
2337
		$cflink['name'] = $this->GetQname();
2338
		$cflink['description'] = $this->GetDescription();
2339
		if (empty($cflink['description']))
2340
			unset($cflink['description']);
2341
		$cflink['bandwidth'] = $this->GetBandwidth();
2342
		$cflink['bandwidthtype'] = $this->GetBwscale();
2343
		$cflink['enabled'] = trim($this->GetEnabled());
2344
		if (empty($cflink['enabled']))
2345
			unset($cflink['enabled']);
2346
		$cflink['default'] = trim($this->GetDefault());
2347
		if (empty($cflink['default']))
2348
			unset($cflink['default']);
2349
		$cflink['red'] = trim($this->GetRed());
2350
		if (empty($cflink['red']))
2351
			unset($cflink['red']);
2352
		$cflink['rio'] = trim($this->GetRio());
2353
		if (empty($cflink['rio']))
2354
			unset($cflink['rio']);
2355
		$cflink['ecn'] = trim($this->GetEcn());
2356
		if (empty($cflink['ecn']))
2357
			unset($cflink['ecn']);
2358
		$cflink['borrow'] = trim($this->GetBorrow());
2359
		if (empty($cflink['borrow']))
2360
			unset($cflink['borrow']);
2361
	}
2362 197bfe96 Ermal Luçi
}
2363 061f78b1 Bill Marquette
2364 2b5caa0e Ermal Luçi
class fairq_queue extends priq_queue {
2365 f5881023 Ermal Lu?i
	var $hogs;
2366
	var $buckets;
2367 2b5caa0e Ermal Luçi
2368
	function GetBuckets() {
2369
		return $this->buckets;
2370
	}
2371
	function SetBuckets($buckets) {
2372 ae3d3adb Ermal Luçi
		$this->buckets = $buckets;
2373 2b5caa0e Ermal Luçi
	}
2374
	function GetHogs() {
2375
		return $this->hogs;
2376
	}
2377
	function SetHogs($hogs) {
2378 ae3d3adb Ermal Luçi
		$this->hogs = $hogs;
2379 2b5caa0e Ermal Luçi
	}
2380 70b139a3 Chris Buechler
	function CanHaveChildren() {
2381 2b5caa0e Ermal Luçi
		return false;
2382
	}
2383
2384
2385
	function copy_queue($interface, &$cflink) {
2386
                $cflink['interface'] = $interface;
2387
                $cflink['qlimit'] = $this->GetQlimit();
2388
                $cflink['priority'] = $this->GetQpriority();
2389
                $cflink['name'] = $this->GetQname();
2390
                $cflink['description'] = $this->GetDescription();
2391
                $cflink['bandwidth'] = $this->GetBandwidth();
2392
                $cflink['bandwidthtype'] = $this->GetBwscale();
2393
                $cflink['enabled'] = $this->GetEnabled();
2394
                $cflink['default'] = $this->GetDefault();
2395
                $cflink['red'] = $this->GetRed();
2396
                $cflink['rio'] = $this->GetRio();
2397
                $cflink['ecn'] = $this->GetEcn();
2398 8774ca6e Ermal Luçi
                $cflink['buckets'] = $this->GetBuckets();
2399
		$cflink['hogs'] = $this->GetHogs();
2400 2b5caa0e Ermal Luçi
	}
2401
	
2402
	/*
2403 70b139a3 Chris Buechler
	 * Should search even its children
2404 2b5caa0e Ermal Luçi
	 */
2405
	function &find_queue($interface, $qname) {
2406
		if ($qname == $this->GetQname())
2407
			return $this;
2408
	}
2409
2410 62150088 Ermal Lu?i
	function find_parentqueue($interface, $qname) { return; }
2411 2b5caa0e Ermal Luçi
2412
	function delete_queue() {
2413
		unref_on_altq_queue_list($this->GetQname());
2414
		if ($this->GetDefault())
2415
			altq_set_default_queue($this->GetInterface(), "false");
2416
		cleanup_queue_from_rules($this->GetQname());
2417
		unset_object_by_reference($this->GetLink());
2418
	}
2419
	
2420
	function validate_input($data, &$input_errors) {
2421
		parent::validate_input($data, $input_errors);
2422
		
2423
		if ($data['priority'] > 255)
2424 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Priority must be an integer between 1 and 255.");
2425 2c072899 jim-p
		$reqdfields[] = "bandwidth";
2426 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidth");
2427 2c072899 jim-p
		$reqdfields[] = "bandwidthtype";
2428 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidthtype");
2429 2b5caa0e Ermal Luçi
2430
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2431
		
2432
		if ($data['bandwidth'] && !is_numeric($data['bandwidth']))
2433 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Bandwidth must be an integer.");
2434 2b5caa0e Ermal Luçi
2435
2436 dbaf21d4 Renato Botelho
		if ($data['bandwidth'] < 0)
2437
			$input_errors[] = gettext("Bandwidth cannot be negative.");
2438 2b5caa0e Ermal Luçi
2439
2440 dbaf21d4 Renato Botelho
		if ($data['bandwidthtype'] == "%") {
2441
			if ($data['bandwidth'] > 100 || $data['bandwidth'] < 0)
2442
				$input_errors[] = gettext("Bandwidth in percentage should be between 1 and 100 bounds.");
2443
		}
2444 2b5caa0e Ermal Luçi
2445
/*
2446
           	$parent =& $this->GetParent();
2447
           	switch ($data['bandwidthtype']) {
2448
                       case "%":
2449
                             $myBw = $parent->GetAvailableBandwidth() * floatval($data['bandwidth']) / 100;
2450
                       default:
2451
                             $mybw = floatval($data['bandwidth']) * get_bandwidthtype_scale($data['bandwidthtype']);
2452
                             break;
2453
           	}
2454
                if ($parent->GetAvailableBandwidth() < floatval($myBw))
2455 70b139a3 Chris Buechler
                        $input_errors[] = "The sum of children bandwidth exceeds that of the parent.";
2456 2b5caa0e Ermal Luçi
*/
2457
	}
2458
	
2459
	function ReadConfig(&$q) {
2460
		parent::ReadConfig($q);
2461 f5881023 Ermal Lu?i
		if (!empty($q['buckets']))
2462 2b5caa0e Ermal Luçi
			$this->SetBuckets($q['buckets']);
2463 7ed9c6ac Ermal
		else
2464
			$this->SetBuckets("");
2465 f5881023 Ermal Lu?i
		if (!empty($q['hogs']) && is_valid_shaperbw($q['hogs']))
2466 2b5caa0e Ermal Luçi
			$this->SetHogs($q['hogs']);
2467 7ed9c6ac Ermal
		else
2468
			$this->SetHogs("");
2469 2b5caa0e Ermal Luçi
	}
2470
		
2471
	function build_javascript() {
2472
		return parent::build_javascript();
2473
	}
2474
2475
	function build_tree() {
2476
		$tree = " <li><a href=\"firewall_shaper.php?interface=" . 
2477 f5881023 Ermal Lu?i
		$this->GetInterface()."&queue=" . $this->GetQname()."&action=show"; 
2478
		$tree .= "\" ";
2479
		$tmpvalue = trim($this->GetDefault());
2480
		if (!empty($tmpvalue))
2481
			$tree .= " class=\"navlnk\"";
2482
		$tree .= " >" . $this->GetQname() . "</a>";
2483
		$tree .= "</li>";
2484
		return $tree;
2485 2b5caa0e Ermal Luçi
	}
2486
		
2487 70b139a3 Chris Buechler
	/* Even this should take children into consideration */
2488 2b5caa0e Ermal Luçi
	function build_rules() {
2489
		$pfq_rule = "queue ". $this->qname;
2490
		if ($this->GetInterface())
2491 85a5da13 Ermal Luçi
			$pfq_rule .= " on ".get_real_interface($this->GetInterface());
2492 2b5caa0e Ermal Luçi
		if ($this->GetBandwidth() && $this->GetBwscale())
2493
			$pfq_rule .= " bandwidth ".trim($this->GetBandwidth()).$this->GetBwscale();
2494 f5881023 Ermal Lu?i
		$tmpvalue = trim($this->GetQpriority());
2495
		if (!empty($tmpvalue))
2496 2b5caa0e Ermal Luçi
			$pfq_rule .= " priority " . $this->GetQpriority();
2497 f5881023 Ermal Lu?i
		$tmpvalue = trim($this->GetQlimit());
2498
		if (!empty($tmpvalue))
2499 2b5caa0e Ermal Luçi
			$pfq_rule .= " qlimit " . $this->GetQlimit();
2500
		if ($this->GetDefault() || $this->GetRed() || $this->GetRio() 
2501
			|| $this->GetEcn() || $this->GetBuckets() || $this->GetHogs()) {
2502 ae3d3adb Ermal Luçi
			$pfq_rule .= " fairq ( ";
2503 f5881023 Ermal Lu?i
			$tmpvalue = trim($this->GetRed());
2504
			if (!empty($tmpvalue)) {
2505 2b5caa0e Ermal Luçi
				$comma = 1;
2506
				$pfq_rule .= " red ";
2507
			}
2508 f5881023 Ermal Lu?i
			$tmpvalue = trim($this->GetRio());
2509
			if (!empty($tmpvalue)) {
2510 2b5caa0e Ermal Luçi
				if ($comma) 
2511
					$pfq_rule .= " ,";
2512
				$comma = 1;
2513
				$pfq_rule .= " rio ";
2514
			}
2515 f5881023 Ermal Lu?i
			$tmpvalue = trim($this->GetEcn());
2516
			if (!empty($tmpvalue)) {
2517 2b5caa0e Ermal Luçi
				if ($comma) 
2518
					$pfq_rule .= " ,";
2519
				$comma = 1;
2520
				$pfq_rule .= " ecn ";
2521
			}
2522 f5881023 Ermal Lu?i
			$tmpvalue = trim($this->GetDefault());
2523
			if (!empty($tmpvalue)) {
2524 2b5caa0e Ermal Luçi
				if ($comma)
2525
					$pfq_rule .= " ,";
2526
				$comma = 1;
2527
				$pfq_rule .= " default ";
2528
			}
2529 f5881023 Ermal Lu?i
			$tmpvalue = trim($this->GetBuckets());
2530
			if (!empty($tmpvalue)) {
2531 2b5caa0e Ermal Luçi
				if ($comma)
2532
					$pfq_rule .= ", ";
2533
				$pfq_rule .= " buckets " . $this->GetBuckets() . " ";
2534
			}
2535 f5881023 Ermal Lu?i
			$tmpvalue = trim($this->GetHogs());
2536
			if (!empty($tmpvalue)) {
2537 2b5caa0e Ermal Luçi
				if ($comma)
2538
					$pfq_rule .= ", ";
2539
				$pfq_rule .= " hogs " . $this->GetHogs() . " ";
2540
			}
2541
				$pfq_rule .= " ) ";
2542
		} 
2543
2544
		$pfq_rule .= " \n";
2545
		return $pfq_rule;
2546
	}
2547
2548
	function build_form() {
2549 f5e511d3 Ermal
		$form = parent::build_form();
2550
		$form .= "<tr>";
2551 dbaf21d4 Renato Botelho
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth") . "</td>";
2552 2b5caa0e Ermal Luçi
		$form .= "<td class=\"vtable\"> <input name=\"bandwidth\" id=\"bandwidth\" class=\"formfld unknown\" value=\"";
2553
		if ($this->GetBandwidth() > 0)
2554 f5881023 Ermal Lu?i
			$form .= htmlspecialchars($this->GetBandwidth());
2555 2b5caa0e Ermal Luçi
		$form .= "\">";
2556
		$form .= "<select name=\"bandwidthtype\" id=\"bandwidthtype\" class=\"formselect\">";
2557
		$form .= "<option value=\"Gb\"";
2558
		if ($this->GetBwscale() == "Gb")
2559 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2560 2b5caa0e Ermal Luçi
		$form .= ">Gbit/s</option>";
2561
		$form .= "<option value=\"Mb\"";
2562
		if ($this->GetBwscale() == "Mb")
2563 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2564 2b5caa0e Ermal Luçi
		$form .= ">Mbit/s</option>";
2565
		$form .= "<option value=\"Kb\"";
2566
		if ($this->GetBwscale() == "Kb")
2567 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2568 2b5caa0e Ermal Luçi
		$form .= ">Kbit/s</option>";
2569
		$form .= "<option value=\"\"";
2570
		if ($this->GetBwscale() == "b")
2571 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2572 2b5caa0e Ermal Luçi
		$form .= ">Bit/s</option>";
2573
		$form .= "<option value=\"%\"";
2574
		if ($this->GetBwscale() == "%")
2575 f5881023 Ermal Lu?i
			$form .= " selected=\"yes\"";
2576 2b5caa0e Ermal Luçi
		$form .= ">%</option>";
2577
		$form .= "</select> <br>";
2578 dbaf21d4 Renato Botelho
		$form .= "<span class=\"vexpl\">" . gettext("Choose the amount of bandwidth for this queue");
2579 2b5caa0e Ermal Luçi
		$form .= "</span></td></tr>";
2580 dbaf21d4 Renato Botelho
		$form .= "<tr><td class=\"vncellreq\">" . gettext("Scheduler specific options") . "</td>";
2581 ae3d3adb Ermal Luçi
		$form .= "<td class=\"vtable\"><table><tr><td>";
2582
		$form .= "<input id=\"buckets\" name=\"buckets\" value=\"";
2583 f5881023 Ermal Lu?i
		$tmpvalue = trim($this->GetBuckets());
2584
		if(!empty($tmpvalue)) 
2585
			$form .=  $this->GetBuckets();
2586 dbaf21d4 Renato Botelho
		$form .= "\"> " . gettext("Number of buckets available.") . "<br></td></tr>";
2587 ae3d3adb Ermal Luçi
		$form .= "<tr><td class=\"vtable\"><input id=\"hogs\" name=\"hogs\" value=\"";
2588 f5881023 Ermal Lu?i
		$tmpvalue = trim($this->GetHogs());
2589
		if(!empty($tmpvalue)) 
2590
			$form .=  $this->GetHogs();
2591 dbaf21d4 Renato Botelho
		$form .= "\"> " . gettext("Bandwidth limit for hosts to not saturate link.") . "<br></td></tr>";
2592 ae3d3adb Ermal Luçi
		$form .= "</table></td></tr>";
2593 2b5caa0e Ermal Luçi
		return $form;
2594
	}
2595
2596
	function update_altq_queue_data(&$data) { 
2597
		$this->ReadConfig($data);
2598
	}
2599
2600
	function wconfig() {
2601
		$cflink =& get_reference_to_me_in_config($this->GetLink());
2602
		if (!is_array($cflink))
2603
			$cflink = array();
2604
		$cflink['interface'] = $this->GetInterface();
2605 f5881023 Ermal Lu?i
		$cflink['qlimit'] = trim($this->GetQlimit());
2606
		if (empty($cflink['qlimit']))
2607
			unset($cflink['qlimit']);
2608
		$cflink['priority'] = trim($this->GetQpriority());
2609
		if (empty($cflink['priority']))
2610
			unset($cflink['priority']);
2611 2b5caa0e Ermal Luçi
		$cflink['name'] = $this->GetQname();
2612 f5881023 Ermal Lu?i
		$cflink['description'] = trim($this->GetDescription());
2613
		if (empty($cflink['description']))
2614
			unset($cflink['description']);
2615 2b5caa0e Ermal Luçi
		$cflink['bandwidth'] = $this->GetBandwidth();
2616
		$cflink['bandwidthtype'] = $this->GetBwscale();
2617
		$cflink['enabled'] = $this->GetEnabled();
2618 f5881023 Ermal Lu?i
		if (empty($cflink['enabled']))
2619
			unset($cflink['enabled']);
2620
		$cflink['default'] = trim($this->GetDefault());
2621
		if (empty($cflink['default']))
2622
			unset($cflink['default']);
2623
		$cflink['red'] = trim($this->GetRed());
2624
		if (empty($cflink['red']))
2625
			unset($cflink['red']);
2626
		$cflink['rio'] = trim($this->GetRio());
2627
		if (empty($cflink['rio']))
2628
			unset($cflink['rio']);
2629
		$cflink['ecn'] = trim($this->GetEcn());
2630
		if (empty($cflink['ecn']))
2631
			unset($cflink['ecn']);
2632
		$cflink['buckets'] = trim($this->GetBuckets());
2633
		if (empty($cflink['buckets']))
2634
			unset($cflink['buckets']);
2635
		$cflink['hogs'] = trim($this->GetHogs());
2636
		if (empty($cflink['hogs']))
2637
			unset($cflink['hogs']);
2638 2b5caa0e Ermal Luçi
	}
2639
}
2640 061f78b1 Bill Marquette
2641
2642 c25a6b6a Ermal Luçi
/*
2643 0dc7b4aa Ermal
 * dummynet(4) wrappers.
2644 c25a6b6a Ermal Luçi
 */
2645
2646
2647
/*
2648
 * List of respective objects!
2649
 */
2650 d62ba478 Ermal Luçi
$dummynet_pipe_list = array();
2651 c25a6b6a Ermal Luçi
2652
class dummynet_class {
2653
        var $qname;
2654 f5881023 Ermal Lu?i
	var $qnumber; /* dummynet(4) uses numbers instead of names; maybe integrate with pf the same as altq does?! */
2655 c25a6b6a Ermal Luçi
        var $qlimit;
2656
        var $description;
2657 f5881023 Ermal Lu?i
	var $qenabled;
2658
	var $link;
2659
	var $qparent; /* link to upper class so we do things easily on WF2Q+ rule creation */
2660 c25a6b6a Ermal Luçi
        var $plr;
2661
2662
        var $buckets;
2663
        /* mask parameters */
2664
        var $mask;
2665
        var $noerror;
2666
2667 70b139a3 Chris Buechler
        /* Accessor functions */
2668 c25a6b6a Ermal Luçi
        function SetLink($link) {
2669
                $this->link = $link;
2670
        }
2671
        function GetLink() {
2672
                return $this->link;
2673
        }
2674 f5881023 Ermal Lu?i
	function Getmask() {
2675
		return $this->mask;
2676
	}
2677
	function SetMask($mask) {
2678
		$this->mask = $mask;
2679
	}
2680
	function &GetParent() {
2681
		return $this->qparent;
2682
	}
2683
	function SetParent(&$parent) {
2684
		$this->qparent = &$parent;
2685
	}
2686 c25a6b6a Ermal Luçi
        function GetEnabled() {
2687
                return $this->qenabled;
2688
        }
2689
        function SetEnabled($value) {
2690
                $this->qenabled = $value;
2691
        }
2692 f5881023 Ermal Lu?i
	function CanHaveChildren() {
2693
		return false;
2694 c25a6b6a Ermal Luçi
        }
2695 f5881023 Ermal Lu?i
	function CanBeDeleted() {
2696 c25a6b6a Ermal Luçi
                return true;
2697
        }
2698
        function GetQname() {
2699
                return $this->qname;
2700
        }
2701
        function SetQname($name) {
2702
                $this->qname = trim($name);
2703
        }
2704
        function GetQlimit() {
2705
                return $this->qlimit;
2706
        }
2707
        function SetQlimit($limit) {
2708
               	$this->qlimit = $limit;
2709
        }
2710
        function GetDescription() {
2711
                return $this->description;
2712
        }
2713
        function SetDescription($str) {
2714 da0ce7ee Chris Buechler
                $this->description = trim($str);
2715 c25a6b6a Ermal Luçi
        }
2716
        function GetFirstime() {
2717
                return $this->firsttime;
2718
        }
2719
        function SetFirsttime($number) {
2720
                $this->firsttime = $number;
2721
        }
2722
        function GetBuckets() {
2723
                return $this->buckets;
2724
        }
2725
        function SetBuckets($buckets) {
2726
                $this->buckets = $buckets;
2727
        }
2728 f5881023 Ermal Lu?i
	function SetNumber($number) {
2729
		$this->qnumber = $number;
2730
	}
2731
	function GetNumber() {
2732
		return $this->qnumber;
2733
	}
2734 c25a6b6a Ermal Luçi
        function GetPlr() {
2735
                return $this->plr;
2736
        }
2737
        function SetPlr($plr) {
2738
                $this->plr = $plr;
2739
        }
2740
2741 f5881023 Ermal Lu?i
	function build_javascript() { return; } /* Do not remove */
2742 d62ba478 Ermal Luçi
2743 f5881023 Ermal Lu?i
	function validate_input($data, &$input_errors) {
2744
		$reqdfields[] = "bandwidth";
2745 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidth");
2746 f5881023 Ermal Lu?i
		$reqdfields[] = "bandwidthtype";
2747 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Bandwidthtype");
2748 f5881023 Ermal Lu?i
		$reqdfields[] = "name";
2749 dbaf21d4 Renato Botelho
		$reqdfieldsn[] = gettext("Name");
2750 f5881023 Ermal Lu?i
	
2751
		shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
2752
2753
		if ($data['plr'] && ((!is_numeric($data['plr'])) ||
2754
			($data['plr'] <= 0 && $data['plr'] > 1))) 
2755 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Plr must be an integer between 1 and 100.");
2756 f5881023 Ermal Lu?i
		if (($data['buckets'] && (!is_numeric($data['buckets']))) ||
2757
			($data['buckets'] < 1 && $data['buckets'] > 100)) 
2758 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Buckets must be an integer between 16 and 65535.");
2759 f5881023 Ermal Lu?i
		if ($data['qlimit'] && (!is_numeric($data['qlimit']))) 
2760 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Queue limit must be an integer");
2761
		if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['name']))
2762
			$input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
2763 f5881023 Ermal Lu?i
	}
2764 c25a6b6a Ermal Luçi
}
2765
2766
class dnpipe_class extends dummynet_class {
2767
        var $delay;
2768 d62ba478 Ermal Luçi
	var $qbandwidth;
2769
	var $qbandwidthtype;
2770 c25a6b6a Ermal Luçi
2771
		/* This is here to help on form building and building rules/lists */
2772
        var $subqueues = array();
2773
2774 70b139a3 Chris Buechler
	function CanHaveChildren() {
2775 c25a6b6a Ermal Luçi
	        return true;
2776
        }
2777 d62ba478 Ermal Luçi
	function SetDelay($delay) {
2778
		$this->delay = $delay;
2779
	}
2780
	function GetDelay() {
2781
		return $this->delay;
2782
	}
2783
	function GetBwscale() {
2784 c25a6b6a Ermal Luçi
                return $this->qbandwidthtype;
2785
        }
2786
        function SetBwscale($scale) {
2787
               	$this->qbandwidthtype = $scale;
2788
        }		
2789 d62ba478 Ermal Luçi
	function delete_queue() {
2790
		cleanup_dnqueue_from_rules($this->GetQname());
2791
		foreach ($this->subqueues as $q)
2792
			$q->delete_queue();
2793
		unset_dn_object_by_reference($this->GetLink());
2794 3f115d0e Ermal
		mwexec("/sbin/ipfw pipe delete " . $this->GetNumber());
2795 c25a6b6a Ermal Luçi
        }
2796
        function GetBandwidth() {
2797
                return $this->qbandwidth;
2798
        }
2799
        function SetBandwidth($bandwidth) {
2800
                $this->qbandwidth = $bandwidth;
2801
        }
2802
2803 d62ba478 Ermal Luçi
	function &add_queue($interface, &$queue, &$path, &$input_errors) {
2804 c25a6b6a Ermal Luçi
2805 d62ba478 Ermal Luçi
		if (!is_array($this->subqueues))
2806
			$this->subqueues = array();
2807
			
2808 62150088 Ermal Lu?i
		$q =& new dnqueue_class();
2809 d62ba478 Ermal Luçi
		$q->SetLink($path);
2810
		$q->SetEnabled("on");
2811
		$q->SetPipe($this->GetQname());
2812
		$q->SetParent(&$this);
2813
		$q->ReadConfig($queue);
2814
		$q->validate_input($queue, $input_errors);
2815
		if (count($input_errors))
2816
			return $q;
2817
		$this->subqueues[$q->GetQname()] = &$q;
2818
            
2819
		return $q;
2820
	}
2821 c25a6b6a Ermal Luçi
2822 309ffde9 Ermal Luçi
	function &get_queue_list($q = null) {
2823 d62ba478 Ermal Luçi
		$qlist = array();
2824 c25a6b6a Ermal Luçi
2825 64c7753b Ermal Luçi
		$qlist[$this->GetQname()] = $this->GetNumber();
2826 d62ba478 Ermal Luçi
		if (is_array($this->subqueues)) {
2827
			foreach ($this->subqueues as $queue)
2828
				$queue->get_queue_list(&$qlist);
2829 c25a6b6a Ermal Luçi
		}
2830 d62ba478 Ermal Luçi
		return $qlist;
2831
	}
2832 c25a6b6a Ermal Luçi
		
2833
        /*
2834 70b139a3 Chris Buechler
         * Should search even its children
2835 c25a6b6a Ermal Luçi
         */
2836
        function &find_queue($pipe, $qname) {
2837
                if ($qname == $this->GetQname()) 
2838
                        return $this;
2839
               	foreach ($this->subqueues as $q) {
2840
                       	$result =& $q->find_queue("", $qname);
2841
						if ($result)
2842
                       	        return $result;
2843
               	}
2844
        }
2845
2846 d62ba478 Ermal Luçi
	function &find_parentqueue($pipe, $qname) {
2847
		return NULL;
2848
       	}
2849 c25a6b6a Ermal Luçi
2850 d62ba478 Ermal Luçi
	function validate_input($data, &$input_errors) {
2851
		parent::validate_input($data, $input_errors);
2852 c25a6b6a Ermal Luçi
2853 d62ba478 Ermal Luçi
		if ($data['bandwidth'] && (!is_numeric($data['bandwidth']))) 
2854 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Bandwidth must be an integer.");
2855 d62ba478 Ermal Luçi
		if ($data['delay'] && (!is_numeric($data['delay'])))
2856 dbaf21d4 Renato Botelho
			$input_errors[] = gettext("Delay must be an integer.");
2857
	}
2858 c25a6b6a Ermal Luçi
2859 d62ba478 Ermal Luçi
	function ReadConfig(&$q) {
2860 c25a6b6a Ermal Luçi
           	$this->SetQname($q['name']);
2861 d62ba478 Ermal Luçi
		$this->SetNumber($q['number']);
2862
		if (isset($q['bandwidth']) && $q['bandwidth'] <> "") { 
2863
			$this->SetBandwidth($q['bandwidth']);
2864
			if (isset($q['bandwidthtype']) && $q['bandwidthtype'])
2865
				$this->SetBwscale($q['bandwidthtype']);
2866
		}
2867
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
2868
              		$this->SetQlimit($q['qlimit']);
2869
		if (isset($q['mask']) && $q['mask'] <> "")
2870
              		$this->SetMask($q['mask']);
2871
		if (isset($q['buckets']) && $q['buckets'] <> "")
2872
              		$this->SetBuckets($q['buckets']);
2873
            	if (isset($q['plr']) && $q['plr'] <> "")
2874
            		$this->SetPlr($q['plr']);
2875
		if (isset($q['delay']) && $q['delay'] <> "")
2876
            		$this->SetDelay($q['delay']);
2877
            	if (isset($q['description']) && $q['description'] <> "")
2878
			$this->SetDescription($q['description']);
2879
		$this->SetEnabled($q['enabled']);
2880 c25a6b6a Ermal Luçi
2881
        }
2882
2883 d62ba478 Ermal Luçi
	function build_tree() {
2884
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $this->GetQname() ."&queue=".$this->GetQname() ."&action=show\">"; 
2885
		$tree .= $this->GetQname() . "</a>";
2886
		if (is_array($this->subqueues)) {
2887
			$tree .= "<ul>";
2888
			foreach ($this->subqueues as $q)  {
2889
				$tree .= $q->build_tree();
2890
			}	
2891
			$tree .= "</ul>";
2892 c25a6b6a Ermal Luçi
		}
2893 d62ba478 Ermal Luçi
		$tree .= "</li>";
2894
		
2895
		return $tree;
2896
	}
2897 c25a6b6a Ermal Luçi
2898
        function build_rules() {
2899 8cb1c6e3 Ermal Luçi
		if ($this->GetEnabled() == "")
2900
			return;
2901
2902 f40980ad Ermal
       		$pfq_rule = "\npipe ". $this->GetNumber() . " config ";
2903 d62ba478 Ermal Luçi
		if ($this->GetBandwidth() && $this->GetBwscale())
2904 d41e63b6 Ermal
                    	$pfq_rule .= " bw ".trim($this->GetBandwidth()).$this->GetBwscale();
2905 d62ba478 Ermal Luçi
		if ($this->GetQlimit())
2906
                    	$pfq_rule .= " queue " . $this->GetQlimit();
2907
		if ($this->GetPlr())
2908
			$pfq_rule .= " plr " . $this->GetPlr();
2909
		if ($this->GetBuckets())
2910
			$pfq_rule .= " buckets " . $this->GetBuckets();
2911
		if ($this->GetDelay())
2912
			$pfq_rule .= " delay " . $this->GetDelay();
2913
2914
		$mask = $this->GetMask();
2915
		if (!empty($mask)) {
2916
			/* XXX TODO extend this to support more complicated masks */
2917
			switch ($mask) {
2918
			case 'srcaddress':
2919
				$pfq_rule .= " mask src-ip 0xffffffff ";
2920
				break;
2921
			case 'dstaddress':
2922
				$pfq_rule .= " mask dst-ip 0xffffffff ";
2923
				break;
2924
			default:
2925
				break;
2926
			}
2927
			$pfq_rule .= "\n";
2928 c25a6b6a Ermal Luçi
2929 d62ba478 Ermal Luçi
			if (!empty($this->subqueues) && count($this->subqueues) > 0) {
2930
       			        foreach ($this->subqueues as $q)
2931
				$pfq_rule .= $q->build_rules();
2932
               		}
2933 c25a6b6a Ermal Luçi
    		}            
2934 d62ba478 Ermal Luçi
		$pfq_rule .= " \n";
2935 c25a6b6a Ermal Luçi
2936 d62ba478 Ermal Luçi
		return $pfq_rule;
2937 c25a6b6a Ermal Luçi
        }
2938
2939 d62ba478 Ermal Luçi
	function update_dn_data(&$data) { 
2940
		$this->ReadConfig($data);
2941
	}
2942 c25a6b6a Ermal Luçi
2943
        function build_form() { 
2944 f5e511d3 Ermal
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
2945 dbaf21d4 Renato Botelho
                $form .= gettext("Enable/Disable");
2946 34a3694b Ermal
                $form .= "</td><td class=\"vncellreq\">";
2947
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
2948
                if ($this->GetEnabled() == "on")
2949
                        $form .=  " CHECKED";
2950 dbaf21d4 Renato Botelho
                $form .= " ><span class=\"vexpl\"> " . gettext("Enable/Disable limiter and its children") . "</span>";
2951 34a3694b Ermal
                $form .= "</td></tr>";
2952 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
2953 c25a6b6a Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
2954
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
2955 d62ba478 Ermal Luçi
		$form .= $this->GetQname()."\">";
2956 c25a6b6a Ermal Luçi
		$form .= "</td></tr>";
2957 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Bandwidth");
2958 c25a6b6a Ermal Luçi
		$form .= "</td><td class=\"vncellreq\">";
2959
		$form .= "<input type=\"text\" id=\"bandwidth\" name=\"bandwidth\" value=\"";
2960
		$form .= $this->GetBandwidth() . "\">"; 
2961
		$form .= "<select id=\"bandwidthtype\" name=\"bandwidthtype\" class=\"formselect\">";
2962
		$form .= "<option value=\"Kb\"";
2963
		if ($this->GetBwscale() == "Kb")
2964
			$form .= " selected=\"yes\"";
2965
		$form .= ">Kbit/s</option>";
2966
		$form .= "<option value=\"Mb\"";
2967
		if ($this->GetBwscale() == "Mb")
2968
			$form .= " selected=\"yes\"";
2969
		$form .= ">Mbit/s</option>";
2970
		$form .= "<option value=\"Gb\"";
2971
		if ($this->GetBwscale() == "Gb")
2972
			$form .= " selected=\"yes\"";
2973
		$form .= ">Gbit/s</option>";		
2974
		$form .= "<option value=\"\"";
2975
		if ($this->GetBwscale() == "b")
2976
			$form .= " selected=\"yes\"";
2977 dbaf21d4 Renato Botelho
		$form .= ">" . gettext("Bit/s") . "</option>";
2978 c25a6b6a Ermal Luçi
		$form .= "</select>";
2979
		$form .= "</td></tr>";
2980 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Mask") . "</td>";
2981 2e1abb31 Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
2982
		$form .= "<select name=\"mask\" class=\"formselect\">";
2983
		$form .= "<option value=\"none\"";
2984
		if ($this->GetMask() == "none")
2985
			$form .= " selected=\"yes\"";
2986
		$form .= ">none</option>";
2987
		$form .= "<option value=\"srcaddress\"";
2988
		if ($this->GetMask() == "srcaddress")
2989
			$form .= " selected=\"yes\"";
2990 dbaf21d4 Renato Botelho
		$form .= ">" . gettext("Source addresses") . "</option>";
2991 2e1abb31 Ermal Luçi
		$form .= "<option value=\"dstaddress\"";
2992
		if ($this->GetMask() == "dstaddress")
2993
			$form .= " selected=\"yes\"";
2994 dbaf21d4 Renato Botelho
		$form .= ">" . gettext("Destination addresses") . "</option>";
2995 2e1abb31 Ermal Luçi
		$form .= "</select>";
2996 1c3fd96b Ermal Luçi
		$form .= "&nbsp;<br>";
2997 dbaf21d4 Renato Botelho
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' is chosen, \n"
2998
		      .  "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n"
2999
		      .  "be created for each source/destination IP address encountered, \n"
3000
		      .  "respectively. This makes it possible to easily specify bandwidth \n"
3001
		      .  "limits per host.") . "</span>";
3002 2e1abb31 Ermal Luçi
		$form .= "</td></tr>";
3003 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Description") . "</td>";
3004 2e1abb31 Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
3005
		$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3006
		$form .= $this->GetDescription();
3007
		$form .= "\">";
3008
		$form .= "<br> <span class=\"vexpl\">";
3009 dbaf21d4 Renato Botelho
		$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3010 2e1abb31 Ermal Luçi
		$form .= "</td></tr>";
3011 a83afb1f Ermal Luçi
      		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3012 2e1abb31 Ermal Luçi
		$form .= "<td></td>";
3013 77dc6894 Ermal Luçi
                $form .= "<td><div id=\"showadvancedboxspr\">";
3014
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3015 dbaf21d4 Renato Botelho
		$form .= " value=\"" . gettext("Show advanced options") . "\"></input></a>";
3016 77dc6894 Ermal Luçi
                $form .= "</div></td></tr>";
3017
                $form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3018
3019 f5e511d3 Ermal
		$form .= "<td valign=\"center\" class=\"vncellreq\">Delay</td>";
3020
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3021 c25a6b6a Ermal Luçi
		$form .= "<input name=\"delay\" type=\"text\" id=\"delay\" size=\"5\" value=\"";
3022
		$form .= $this->GetDelay() . "\">";
3023 dbaf21d4 Renato Botelho
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3024
			  .  "should specify 0 here (or leave the field empty)") . "</span>";
3025 77dc6894 Ermal Luçi
		$form .= "</td></tr><br/>";
3026 ff0189e7 Ermal Luçi
      		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3027 f5e511d3 Ermal
		$form .= "<td valign=\"center\" class=\"vncellreq\">Packet loss rate</td>";
3028
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3029 c25a6b6a Ermal Luçi
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3030
		$form .= $this->GetPlr() . "\">";
3031 dbaf21d4 Renato Botelho
		$form .= "&nbsp;<br> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3032
			  .  "should specify 0 here (or leave the field empty). "
3033
		      .  "A value of 0.001 means one packet in 1000 gets dropped") . "</span>";
3034 c25a6b6a Ermal Luçi
		$form .= "</td></tr>";
3035 ff0189e7 Ermal Luçi
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3036 dbaf21d4 Renato Botelho
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Queue Size") . "</td>";
3037 c25a6b6a Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
3038
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3039
		$form .= $this->GetQlimit() . "\">";
3040
		$form .= "&nbsp;slots<br>";
3041 dbaf21d4 Renato Botelho
		$form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3042
		      .  "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, "
3043
	              .  "then they are delayed by value specified in the Delay field, and then they "
3044
		      .  "are delivered to their destination.") . "</span>";
3045 ff0189e7 Ermal Luçi
		$form .= "</td></tr>";
3046 1c3fd96b Ermal Luçi
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3047 dbaf21d4 Renato Botelho
                $form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bucket Size") . "</td>";
3048 1c3fd96b Ermal Luçi
                $form .= "<td class=\"vncellreq\">";
3049
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3050
                $form .= $this->GetBuckets() . "\">";
3051
                $form .= "&nbsp;slots<br>";
3052 dbaf21d4 Renato Botelho
                $form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3053
                      .  "should leave the field empty. It increases the hash size set.");
3054 1c3fd96b Ermal Luçi
                $form .= "</td></tr>";
3055 c25a6b6a Ermal Luçi
3056
		return $form;
3057
			
3058
		}
3059
3060 d62ba478 Ermal Luçi
	function wconfig() {
3061
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3062
            	if (!is_array($cflink))
3063
            		$cflink = array();
3064
		$cflink['name'] = $this->GetQname();
3065
		$cflink['number'] = $this->GetNumber();
3066
            	$cflink['qlimit'] = $this->GetQlimit();
3067
            	$cflink['plr'] = $this->GetPlr();
3068
            	$cflink['description'] = $this->GetDescription();
3069
		$cflink['bandwidth'] = $this->GetBandwidth();
3070
            	$cflink['bandwidthtype'] = $this->GetBwscale();
3071
		$cflink['enabled'] = $this->GetEnabled();
3072
		$cflink['buckets'] = $this->GetBuckets();
3073
		$cflink['mask'] = $this->GetMask();
3074
		$cflink['delay'] = $this->GetDelay();
3075
	}
3076 c25a6b6a Ermal Luçi
3077
}
3078
3079
class dnqueue_class extends dummynet_class {
3080
        var $pipeparent;
3081
        var $weight;
3082
3083
        function GetWeight() {
3084
                return $this->weight;
3085
        }
3086
        function SetWeight($weight) {
3087
                $this->weight = $weight;
3088
        }
3089 d62ba478 Ermal Luçi
	function GetPipe() {
3090
		return $this->pipeparent;
3091
	}
3092
	function SetPipe($pipe) {
3093
		$this->pipeparent = $pipe;
3094
	}
3095 c25a6b6a Ermal Luçi
3096 d62ba478 Ermal Luçi
	/* Just a stub in case we ever try to call this from the frontend. */
3097
	function &add_queue($interface, &$queue, &$path, &$input_errors) { return; }
3098 c25a6b6a Ermal Luçi
3099 d62ba478 Ermal Luçi
	function delete_queue() {
3100
		cleanup_dnqueue_from_rules($this->GetQname());
3101
		unset_dn_object_by_reference($this->GetLink());
3102 3f115d0e Ermal
		mwexec("/sbin/ipfw queue delete " . $this->GetNumber());
3103 c25a6b6a Ermal Luçi
        }
3104
3105 d62ba478 Ermal Luçi
	function validate_input($data, &$input_errors) {
3106
		parent::validate_input($data, $input_errors);
3107 c25a6b6a Ermal Luçi
3108 d62ba478 Ermal Luçi
		if ($data['weight'] && ((!is_numeric($data['weight'])) ||
3109
			($data['weight'] < 1 && $data['weight'] > 100))) 
3110 dbaf21d4 Renato Botelho
				$input_errors[] = gettext("Weight must be an integer between 1 and 100.");
3111 d62ba478 Ermal Luçi
	}
3112 c25a6b6a Ermal Luçi
3113
        /*
3114 70b139a3 Chris Buechler
         * Should search even its children
3115 c25a6b6a Ermal Luçi
         */
3116
        function &find_queue($pipe, $qname) {
3117
                if ($qname == $this->GetQname()) 
3118 d62ba478 Ermal Luçi
                	return $this;
3119
		else
3120
			return NULL;
3121 c25a6b6a Ermal Luçi
        }
3122
3123 d62ba478 Ermal Luçi
	function &find_parentqueue($pipe, $qname) {
3124
		return $this->qparent;
3125 c25a6b6a Ermal Luçi
        }
3126
3127 309ffde9 Ermal Luçi
        function &get_queue_list(&$qlist) {
3128 64c7753b Ermal Luçi
        	$qlist[$this->GetQname()] = "?" .$this->GetNumber();
3129 c25a6b6a Ermal Luçi
        }		
3130
3131 d62ba478 Ermal Luçi
	function ReadConfig(&$q) {
3132
          	$this->SetQname($q['name']);
3133
		$this->SetNumber($q['number']);
3134
		if (isset($q['qlimit']) && $q['qlimit'] <> "")
3135
       		       	$this->SetQlimit($q['qlimit']);
3136
		if (isset($q['mask']) && $q['mask'] <> "")
3137
              		$this->SetMask($q['mask']);
3138
       		if (isset($q['weight']) && $q['weight'] <> "")
3139
            		$this->SetWeight($q['weight']);
3140 da0ce7ee Chris Buechler
            	if (isset($q['description']) && $q['description'] <> "")
3141 d62ba478 Ermal Luçi
			$this->SetDescription($q['description']);
3142
		$this->SetEnabled($q['enabled']);
3143 c25a6b6a Ermal Luçi
        }
3144
3145 d62ba478 Ermal Luçi
	function build_tree() {
3146
		$parent =& $this->GetParent();
3147
		$tree = " <li><a href=\"firewall_shaper_vinterface.php?pipe=" . $parent->GetQname() ."&queue=" . $this->GetQname() ."&action=show\">"; 
3148
		$tree .= $this->GetQname() . "</a>";
3149
		$tree .= "</li>";
3150 c25a6b6a Ermal Luçi
		
3151 d62ba478 Ermal Luçi
		return $tree;
3152
	}
3153 c25a6b6a Ermal Luçi
3154
        function build_rules() {
3155 8cb1c6e3 Ermal Luçi
		if ($this->GetEnabled() == "")
3156
			return; 
3157
3158 d62ba478 Ermal Luçi
		$parent =& $this->GetParent();
3159 f40980ad Ermal
            	$pfq_rule = "queue ". $this->GetNumber() . " config pipe " . $parent->GetNumber();
3160 d62ba478 Ermal Luçi
		if ($this->GetQlimit())
3161
                    	$pfq_rule .= " queue " . $this->GetQimit();
3162
		if ($this->GetWeight())
3163
			$pfq_rule .= " weight " . $this->GetWeight();
3164
		if ($this->GetBuckets())
3165
			$pfq_rule .= " buckets " . $this->GetBuckets();
3166
		$mask = $this->GetMask();
3167
		if (!empty($mask)) {
3168
			/* XXX TODO extend this to support more complicated masks */
3169
			switch ($mask) {
3170
			case 'srcaddress':
3171
				$pfq_rule .= " mask src-ip 0xffffffff ";
3172
				break;
3173
			case 'dstaddress':
3174
				$pfq_rule .= " mask dst-ip 0xffffffff ";
3175
				break;
3176
			default:
3177
				break;
3178 c25a6b6a Ermal Luçi
			}
3179 d62ba478 Ermal Luçi
			$pfq_rule .= "\n";
3180 c25a6b6a Ermal Luçi
		}
3181
3182 d62ba478 Ermal Luçi
		return $pfq_rule;
3183
	}
3184
3185
        function build_form() { 
3186 f5e511d3 Ermal
		$form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
3187 dbaf21d4 Renato Botelho
                $form .= gettext("Enable/Disable");
3188 34a3694b Ermal
                $form .= "</td><td class=\"vncellreq\">";
3189
                $form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\"";
3190
                if ($this->GetEnabled() == "on")
3191
                        $form .=  " CHECKED";
3192 dbaf21d4 Renato Botelho
                $form .= " ><span class=\"vexpl\"> " . gettext("Enable/Disable queue and its children") . "</span>";
3193 34a3694b Ermal
                $form .= "</td></tr>";
3194 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
3195 c25a6b6a Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
3196
		$form .= "<input type=\"text\" id=\"name\" name=\"name\" value=\"";
3197 d62ba478 Ermal Luçi
		$form .= $this->GetQname()."\">";
3198 c25a6b6a Ermal Luçi
		$form .= "</td></tr>";
3199 dbaf21d4 Renato Botelho
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Mask") . "</td>";
3200 c25a6b6a Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
3201
		$form .= "<select name=\"mask\" class=\"formselect\">";
3202
		$form .= "<option value=\"none\"";
3203 d62ba478 Ermal Luçi
		if ($this->GetMask() == "none")
3204 c25a6b6a Ermal Luçi
			$form .= " selected=\"yes\"";
3205 dbaf21d4 Renato Botelho
		$form .= ">" . gettext("none") . "</option>";
3206 d62ba478 Ermal Luçi
		$form .= "<option value=\"srcaddress\"";
3207
		if ($this->GetMask() == "srcaddress")
3208 c25a6b6a Ermal Luçi
			$form .= " selected=\"yes\"";
3209 dbaf21d4 Renato Botelho
		$form .= ">" . gettext("Source addresses") . "</option>";
3210 d62ba478 Ermal Luçi
		$form .= "<option value=\"dstaddress\"";
3211
		if ($this->GetMask() == "dstaddress")
3212 c25a6b6a Ermal Luçi
			$form .= " selected=\"yes\"";
3213 dbaf21d4 Renato Botelho
		$form .= ">" . gettext("Destination addresses") . "</option>";
3214 c25a6b6a Ermal Luçi
		$form .= "</select>";
3215
		$form .= "&nbsp;slots<br>";
3216 dbaf21d4 Renato Botelho
		$form .= "<span class=\"vexpl\">" . gettext("If 'source' or 'destination' is chosen, \n"
3217
		      .  "a dynamic pipe with the bandwidth, delay, packet loss and queue size given above will \n"
3218
		      .  "be created for each source/destination IP address encountered, \n"
3219
		      .  "respectively. This makes it possible to easily specify bandwidth \n"
3220
		      .  "limits per host.") . "</span>";
3221 c25a6b6a Ermal Luçi
		$form .= "</td></tr>";
3222 f5e511d3 Ermal
		$form .= "<tr><td valign=\"center\" class=\"vncellreq\">Description</td>";
3223 c25a6b6a Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
3224 d62ba478 Ermal Luçi
		$form .= "<input type=\"text\" id=\"description\" class=\"formfld unknown\" size=\"50%\" name=\"description\" value=\"";
3225 c25a6b6a Ermal Luçi
		$form .= $this->GetDescription();
3226
		$form .= "\">";
3227
		$form .= "<br> <span class=\"vexpl\">";
3228 dbaf21d4 Renato Botelho
		$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3229 c25a6b6a Ermal Luçi
		$form .= "</td></tr>";
3230 19190e1a Ermal Luçi
		$form .= "<tr id=\"sprtable4\" name=\"sprtable4\">";
3231
		$form .= "<td></td>";
3232
                $form .= "<td><div id=\"showadvancedboxspr\">";
3233
                $form .= "<p><input type=\"button\" onClick=\"show_source_port_range()\"";
3234 dbaf21d4 Renato Botelho
		$form .= " value=\"" . gettext("Show advanced options") . "\"></input></a>";
3235 19190e1a Ermal Luçi
                $form .= "</div></td></tr>";
3236
		$form .= "<tr style=\"display:none\" id=\"sprtable\" name=\"sprtable\">";
3237 dbaf21d4 Renato Botelho
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Weight") . "</td>";
3238 f5e511d3 Ermal
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3239 19190e1a Ermal Luçi
		$form .= "<input name=\"weight\" type=\"text\" id=\"weight\" size=\"5\" value=\"";
3240
		$form .= $this->GetWeight() . "\">";
3241 dbaf21d4 Renato Botelho
		$form .= "&nbsp;ms<br> <span class=\"vexpl\">" . gettext("Hint: For queues under the same parent "
3242
		      .  "this specifies the share that a queue gets(values range from 1 to 100, you can leave it blank otherwise)") . "</span>";
3243 19190e1a Ermal Luçi
		$form .= "</td></tr>";
3244
		$form .= "<tr style=\"display:none\" id=\"sprtable1\" name=\"sprtable1\">";
3245 dbaf21d4 Renato Botelho
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Packet loss rate") . "</td>";
3246 f5e511d3 Ermal
		$form .= "<td valign=\"center\" class=\"vncellreq\">";
3247 19190e1a Ermal Luçi
		$form .= "<input name=\"plr\" type=\"text\" id=\"plr\" size=\"5\" value=\"";
3248
		$form .= $this->GetPlr() . "\">";
3249 dbaf21d4 Renato Botelho
		$form .= "&nbsp;<br> <span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3250
			  .  "should specify 0 here (or leave the field empty). "
3251
			  .  "A value of 0.001 means one packet in 1000 gets dropped") . "</span>";
3252 19190e1a Ermal Luçi
		$form .= "</td></tr>";
3253
		$form .= "<tr style=\"display:none\" id=\"sprtable2\" name=\"sprtable2\">";
3254 dbaf21d4 Renato Botelho
		$form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Queue Size") . "</td>";
3255 19190e1a Ermal Luçi
		$form .= "<td class=\"vncellreq\">";
3256
		$form .= "<input type=\"text\" id=\"qlimit\" name=\"qlimit\" value=\"";
3257
		$form .= $this->GetQlimit() . "\">";
3258
		$form .= "&nbsp;slots<br>";
3259 dbaf21d4 Renato Botelho
		$form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3260
			  .  "should leave the field empty. All packets in this pipe are placed into a fixed-size queue first, "
3261
			  .  "then they are delayed by value specified in the Delay field, and then they "
3262
			  .  "are delivered to their destination.") . "</span>";
3263 19190e1a Ermal Luçi
		$form .= "</td></tr>";
3264 1c3fd96b Ermal Luçi
		$form .= "<tr style=\"display:none\" id=\"sprtable5\" name=\"sprtable5\">";
3265 dbaf21d4 Renato Botelho
                $form .= "<td valign=\"center\" class=\"vncellreq\">" . gettext("Bucket Size") . "</td>";
3266 1c3fd96b Ermal Luçi
                $form .= "<td class=\"vncellreq\">";
3267
                $form .= "<input type=\"text\" id=\"buckets\" name=\"buckets\" value=\"";
3268
                $form .= $this->GetBuckets() . "\">";
3269 dbaf21d4 Renato Botelho
                $form .= "&nbsp;" . gettext("slots") . "<br>";
3270
                $form .= "<span class=\"vexpl\">" . gettext("Hint: in most cases, you "
3271
                      .  "should leave the field empty. It increases the hash size set.");
3272 1c3fd96b Ermal Luçi
                $form .= "</td></tr>";
3273
3274 c25a6b6a Ermal Luçi
		$form .= "<input type=\"hidden\" id=\"pipe\" name=\"pipe\"";
3275
		$form .= " value=\"" . $this->GetPipe() . "\">";
3276
3277
		return $form;
3278
			
3279 d62ba478 Ermal Luçi
	}
3280 c25a6b6a Ermal Luçi
3281 d62ba478 Ermal Luçi
        function update_dn_data(&$data) { 
3282
		$this->ReadConfig($data);
3283
	}
3284 c25a6b6a Ermal Luçi
3285 d62ba478 Ermal Luçi
	function wconfig() {
3286
		$cflink =& get_dn_reference_to_me_in_config($this->GetLink());
3287
            	if (!is_array($cflink))
3288
            		$cflink = array();
3289
		$cflink['name'] = $this->GetQname();
3290
		$cflink['number'] = $this->GetNumber();
3291
            	$cflink['qlimit'] = $this->GetQlimit();
3292
            	$cflink['description'] = $this->GetDescription();
3293
		$cflink['weight'] = $this->GetWeight();
3294
		$cflink['enabled'] = $this->GetEnabled();
3295
		$cflink['buckets'] = $this->GetBuckets();
3296
		$cflink['mask'] = $this->GetMask();
3297
	}
3298 c25a6b6a Ermal Luçi
}
3299
3300 f63d5b66 Helder Pereira
// List of layer7 objects
3301
$layer7_rules_list = array();
3302
3303
class layer7 {
3304
    
3305
    var $rname; //alias
3306
    var $rdescription; //alias description
3307
    var $rport; //divert port
3308
    var $renabled; //rule enabled
3309
    var $rsets = array(); //array of l7 associations
3310
    
3311
    // Auxiliary functions
3312
    
3313
    function GetRName() {
3314
        return $this->rname;
3315
    }
3316
    function SetRName($rname) {
3317
        $this->rname = $rname;
3318
    }
3319
    function GetRDescription() {
3320
        return $this->rdescription;
3321
    }
3322
    function SetRDescription($rdescription) {
3323
        $this->rdescription = $rdescription;
3324
    }
3325
    function GetRPort() {
3326
        return $this->rport;
3327
    }
3328
    function SetRPort($rport) {
3329
        $this->rport = $rport;
3330
    }
3331
    function GetREnabled() {
3332
        return $this->renabled;
3333
    }
3334
    function SetREnabled($value) {
3335
        $this->renabled = $value;
3336
    }
3337
    function GetRl7() {
3338
        return $this->rsets;
3339
    }
3340
    function SetRl7($rsets) {
3341
        $this->rsets = $rsets;
3342
    }
3343
    
3344
    //Add a tuple (rule,sctructure,element) to the $rsets
3345
    
3346
    function add_rule($l7set) {
3347 51b14faa Ermal Lu?i
       	$this->rsets[] = $l7set;
3348 f63d5b66 Helder Pereira
    }
3349
    
3350
    // Build the layer7 rules
3351
    function build_l7_rules() {
3352
        if($this->GetREnabled() == "") {
3353
            return;
3354
        }
3355
        //$l7rules = "#" . $this->rdescription . "\n";
3356
        foreach ($this->rsets as $rl7) {
3357
            $l7rules .= $rl7->build_rules();
3358
        }
3359
        return $l7rules;
3360
    }
3361
    
3362
    // Read the config from array
3363
    function ReadConfig(&$qname, &$q) {
3364
        $this->SetRName($qname);
3365
        $this->SetREnabled($q['enabled']);
3366
        $this->SetRPort($q['divert_port']);
3367
        if(isset($q['description']) && $q['description'] <> "")
3368
            $this->SetRDescription($q['description']);
3369
        $rsets = $q['l7rules'];
3370
        //Put individual rules in the array
3371
	if(is_array($rsets)) {
3372 51b14faa Ermal Lu?i
	    $this->rsets = array(); // XXX: ugly hack
3373 f63d5b66 Helder Pereira
	    foreach($rsets as $l7r) {
3374
	        $l7obj = new l7rule();
3375
	        $l7obj->SetRProtocol($l7r['protocol']);
3376
	        $l7obj->SetRStructure($l7r['structure']);
3377
	        $l7obj->SetRBehaviour($l7r['behaviour']);
3378
	        $this->add_rule($l7obj);
3379
	    }
3380
	}
3381
    }
3382
    
3383
    //Generate a random port for the divert socket
3384
    function gen_divert_port() {
3385
        $dports = get_divert_ports(); //array of used ports
3386 6ec23212 Ermal Lu?i
	$divert_port = 1; // Initialize
3387
	while (($divert_port % 2) != 0 || in_array($divert_port, $dports)) {
3388
		$divert_port = rand(40000, 60000);
3389
	}
3390 f63d5b66 Helder Pereira
        return $divert_port;
3391
    }
3392
    
3393
    //Helps building the left tree
3394
    function build_tree() {
3395
        $tree = " <li><a href=\"firewall_shaper_layer7.php?container=" . $this->GetRName() ."&action=show\">"; 
3396
        $tree .= $this->GetRName() . "</a>";
3397
	$tree .= "</li>";
3398
		
3399
	return $tree;
3400
    }
3401
    
3402
    function build_form() {
3403 f5e511d3 Ermal
        $form = "<tr><td valign=\"center\" class=\"vncellreq\"><br>";
3404 dbaf21d4 Renato Botelho
	$form .= gettext("Enable/Disable");
3405 f63d5b66 Helder Pereira
	$form .= "</td><td class=\"vncellreq\">";
3406 96cbc5aa Ermal
	$form .= " <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" value=\"on\" ";
3407
	if ($this->GetREnabled() == "on") {
3408 f63d5b66 Helder Pereira
       	    $form .=  "checked = \"CHECKED\"";
3409
	}
3410 dbaf21d4 Renato Botelho
	$form .= " ><span class=\"vexpl\"> " . gettext("Enable/Disable layer7 Container") . "</span>";
3411 f63d5b66 Helder Pereira
	$form .= "</td></tr>";
3412 dbaf21d4 Renato Botelho
        $form .= "<tr><td valign=\"center\" class=\"vncellreq\"><br><span class=\"vexpl\">" . gettext("Name") . "</span></td>";
3413 f63d5b66 Helder Pereira
	$form .= "<td class=\"vncellreq\">";
3414
	$form .= "<input type=\"text\" id=\"container\" name=\"container\" value=\"";
3415
	$form .= $this->GetRName()."\">";
3416
	$form .= "</td></tr>";
3417 dbaf21d4 Renato Botelho
	$form .= "<tr><td valign=\"center\" class=\"vncellreq\">" . gettext("Description") . "</td>";
3418 f63d5b66 Helder Pereira
	$form .= "<td class=\"vncellreq\">";
3419
	$form .= "<input type=\"text\" class=\"formfld unknown\" size=\"50%\" id=\"description\" name=\"description\" value=\"";
3420
	$form .= $this->GetRDescription();
3421
	$form .= "\">";
3422
	$form .= "<br> <span class=\"vexpl\">";
3423 dbaf21d4 Renato Botelho
	$form .= gettext("You may enter a description here for your reference (not parsed).") . "</span>";
3424 f63d5b66 Helder Pereira
	$form .= "</td></tr>";
3425
	
3426
	return $form;
3427
    }
3428
    
3429
    //Write the setting to the $config array
3430
    function wconfig() {
3431
	global $config;
3432
	
3433
	if(!is_array($config['l7shaper']['container'])) {
3434
		$config['l7shaper']['container'] = array();
3435
	}
3436
        //
3437
        $cflink =& get_l7c_reference_to_me_in_config($this->GetRName());
3438
	// Test if this rule does exists already
3439
	if(!$cflink) {
3440
		$cflink =& $config['l7shaper']['container'][];
3441
	}
3442
	$cflink['name'] = $this->GetRName();
3443
        $cflink['enabled'] = $this->GetREnabled();
3444
        $cflink['description'] = $this->GetRDescription();
3445
        $cflink['divert_port'] = $this->GetRPort();
3446
        
3447
	//Destroy previously existent rules
3448
	if(is_array($cflink['rules'])) {
3449
		unset($cflink['l7rules']);
3450
	}
3451
	
3452
        $cflink['l7rules'] = array();
3453
	
3454
        $i = 0;
3455
        foreach($this->rsets as $rulel7) {
3456
            $cflink['l7rules'][$i]['protocol'] = $rulel7->GetRProtocol();
3457
            $cflink['l7rules'][$i]['structure'] = $rulel7->GetRStructure();
3458
            $cflink['l7rules'][$i]['behaviour'] = $rulel7->GetRBehaviour();
3459
            $i++;
3460
        }
3461
    }
3462
    
3463
    //This function is necessary to help producing the overload options for keep state
3464
    function get_unique_structures() {
3465
        
3466
        $unique_structures = array("action" => false, "dummynet" => false, "altq" => false);
3467
        foreach($this->rsets as $l7rule) {
3468
		if($l7rule->GetRStructure() == "action")
3469
			$unique_structures['action'] = true;
3470
		else if($l7rule->GetRStructure() == "limiter")
3471
			$unique_structures['dummynet'] = true;
3472
		else
3473
			$unique_structures['altq'] = true;
3474
        }
3475
	//Delete non used structures so we don't have to check this in filter.inc
3476
	foreach($unique_structures as $key => $value)
3477
		if(!$value)
3478
			unset($unique_structures[$key]);
3479
        return $unique_structures;
3480
    }
3481
    
3482
    function validate_input($data, &$input_errors) {
3483 2c072899 jim-p
	$reqdfields[] = "container";
3484 dbaf21d4 Renato Botelho
	$reqdfieldsn[] = gettext("Name");
3485 f63d5b66 Helder Pereira
		
3486
	shaper_do_input_validation($data, $reqdfields, $reqdfieldsn, $input_errors);
3487
        
3488
        if (!preg_match("/^[a-zA-Z0-9_-]+$/", $data['container']))
3489 dbaf21d4 Renato Botelho
            $input_errors[] = gettext("Queue names must be alphanumeric and _ or - only.");
3490 f63d5b66 Helder Pereira
    }
3491
    
3492
    function delete_l7c() {
3493 bb37dc86 Ermal
	mwexec("/bin/pkill -f 'ipfw-classifyd .* -p ". $this->GetRPort() . "'", true);
3494 f63d5b66 Helder Pereira
	unset_l7_object_by_reference($this->GetRName());
3495
	cleanup_l7_from_rules($this->GetRName());
3496
    }
3497
}
3498
3499
class l7rule {
3500
    
3501
    var $rprotocol; //protocol
3502
    var $rstructure; //action, limiter, queue
3503
    var $rbehaviour; //allow, block, queue_name, pipe_number ...
3504
    
3505
    //Auxiliary Functions
3506
    
3507
    function GetRProtocol() {
3508
        return $this->rprotocol;
3509
    }
3510
    function SetRProtocol($rprotocol) {
3511
        $this->rprotocol = $rprotocol;
3512
    }
3513
    function GetRStructure() {
3514
        return $this->rstructure;
3515
    }
3516
    function SetRStructure($rstructure) {
3517
        $this->rstructure = $rstructure;
3518
    }
3519
    function GetRBehaviour() {
3520
        return $this->rbehaviour;
3521
    }
3522
    function SetRBehaviour($rbehaviour) {
3523
        $this->rbehaviour = $rbehaviour;
3524
    }
3525
    
3526
    //XXX Do we need to test any particularity for AltQ queues?
3527
    function build_rules() {
3528
	global $dummynet_pipe_list;
3529
	switch ($this->GetRStructure()) {
3530
		case "limiter":
3531
			read_dummynet_config();
3532
			$dn_list =& get_unique_dnqueue_list();
3533
			$found = false;
3534
			if(is_array($dn_list)) {
3535
				foreach($dn_list as $key => $value) {
3536
					if($key == $this->GetRBehaviour()) {
3537
						if($value[0] == "?")
3538
							$l7rule = $this->GetRProtocol() . " = dnqueue " . substr($value, 1) . "\n";
3539
						else
3540
							$l7rule = $this->GetRProtocol() . " = dnpipe " . $value . "\n";
3541
						$found = true;
3542
					}
3543
					if($found)
3544
						break;
3545
				}
3546
			}
3547
			break;
3548
		default: //This is for action and for altq
3549
			$l7rule = $this->GetRProtocol() . " = " . $this->GetRStructure() . " " . $this->GetRBehaviour() . "\n";
3550
			break;
3551
	}
3552
        return $l7rule;
3553
    }
3554
}
3555
3556
/*
3557
 * This function allows to return an array with all the used divert socket ports
3558
 */
3559
function get_divert_ports() {
3560
    global $layer7_rules_list;
3561
    $dports = array();
3562
    
3563
    foreach($layer7_rules_list as $l7r)
3564
        $dports[] = $l7r->GetRPort();
3565
    
3566
    return $dports;
3567
}
3568
3569
function &get_l7c_reference_to_me_in_config(&$name) {
3570
	global $config;
3571
	
3572
	$ptr = NULL;
3573
	
3574
	if(is_array($config['l7shaper']['container'])) {
3575
		foreach($config['l7shaper']['container'] as $key => $value) {
3576
			if($value['name'] == $name)
3577
				$ptr =& $config['l7shaper']['container'][$key];
3578
		}
3579
	}	
3580
	return $ptr;
3581
// $ptr can be null. has to be checked later
3582
}
3583
3584
function unset_l7_object_by_reference(&$name) {
3585
	global $config;
3586
        
3587
	if(is_array($config['l7shaper']['container'])) {
3588
		foreach($config['l7shaper']['container'] as $key => $value) {
3589
			if($value['name'] == $name) {
3590
				unset($config['l7shaper']['container'][$key]['l7rules']);
3591
				unset($config['l7shaper']['container'][$key]);
3592
				break;
3593
			}
3594
		}
3595
	}
3596
}
3597
3598
function read_layer7_config() {
3599
    global $layer7_rules_list, $config;
3600
    
3601
    $l7cs = &$config['l7shaper']['container'];
3602
    
3603
    $layer7_rules_list = array();
3604
    
3605
    if (!is_array($config['l7shaper']['container']) || !count($config['l7shaper']['container']))
3606
	return;
3607
    
3608
    foreach ($l7cs as $conf) {
3609
	if (empty($conf['name']))
3610
		continue; /* XXX: grrrrrr at php */ 
3611 62150088 Ermal Lu?i
        $root =& new layer7();
3612 f63d5b66 Helder Pereira
        $root->ReadConfig($conf['name'],$conf);
3613
        $layer7_rules_list[$root->GetRName()] = &$root;
3614
    }
3615
}
3616
3617
function generate_layer7_files() {
3618 6955830f Ermal Lu?i
    global $layer7_rules_list, $g;
3619 f63d5b66 Helder Pereira
    
3620
    read_layer7_config();
3621
    
3622
    if (!empty($layer7_rules_list)) {
3623 1ab56363 Ermal Lu?i
	if (!is_module_loaded("ipdivert.ko"))
3624
		mwexec("/sbin/kldload ipdivert.ko");
3625 effe3da7 Ermal Lu?i
3626 6955830f Ermal Lu?i
	mwexec("rm -f {$g['tmp_path']}/*.l7");
3627 f63d5b66 Helder Pereira
    }
3628
    
3629
    foreach($layer7_rules_list as $l7rules) {
3630
        if($l7rules->GetREnabled()) {
3631
            $filename = $l7rules->GetRName() . ".l7";
3632 6955830f Ermal Lu?i
            $path = "{$g['tmp_path']}/" . $filename;
3633 f63d5b66 Helder Pereira
        
3634
            $rules = $l7rules->build_l7_rules();
3635
        
3636
            $fp = fopen($path,'w');
3637
            fwrite($fp,$rules);
3638
            fclose($fp);
3639 f476ef15 Ermal Lu?i
        }
3640
    }
3641
}
3642
3643
function layer7_start_l7daemon() {
3644 6955830f Ermal Lu?i
    global $layer7_rules_list, $g;
3645 f476ef15 Ermal Lu?i
3646
    /*
3647 1ab56363 Ermal Lu?i
     * XXX: ermal - Needed ?!
3648 f476ef15 Ermal Lu?i
     * read_layer7_config();
3649
     */
3650
3651
    foreach($layer7_rules_list as $l7rules) {
3652
        if($l7rules->GetREnabled()) {
3653
            $filename = $l7rules->GetRName() . ".l7";
3654 6955830f Ermal Lu?i
            $path = "{$g['tmp_path']}/" . $filename;
3655 f476ef15 Ermal Lu?i
3656 1ab56363 Ermal Lu?i
	    unset($l7pid);
3657
	    /* Only reread the configuration rather than restart to avoid loosing information. */
3658 6f76920c thompsa
	    exec("/bin/pgrep -f 'ipfw-classifyd .* -p ". $l7rules->GetRPort() . "'", $l7pid);
3659 ddd127eb Ermal Lu?i
	    if (count($l7pid) > 0) {
3660
		log_error("Sending HUP signal to {$l7pid[0]}");
3661
		mwexec("/bin/kill -HUP {$l7pid[0]}");
3662
	    } else {
3663 1ab56363 Ermal Lu?i
		// XXX: Hardcoded number of packets to garbage collect and queue length..
3664
		$ipfw_classifyd_init = "/usr/local/sbin/ipfw-classifyd -n 5 -q 700 -c {$path} -p " . $l7rules->GetRPort() . " -P /usr/local/share/protocols";
3665
		mwexec_bg($ipfw_classifyd_init);
3666
	    }
3667 f63d5b66 Helder Pereira
        }
3668
    }
3669
}
3670
3671
// This function uses /usr/local/share/protocols as a default directory for searching .pat files
3672
function generate_protocols_array() {
3673
	$protocols = return_dir_as_array("/usr/local/share/protocols");
3674 c7ed2141 sullrich
	$protocols_new = array();
3675 f63d5b66 Helder Pereira
	if(is_array($protocols)) {
3676 850cff07 Ermal Lu?i
		foreach($protocols as $key => $proto) {
3677 20138aba sullrich
			if (strstr($proto, ".pat"))
3678 c7ed2141 sullrich
				$protocols_new[$key] =& str_replace(".pat", "", $proto);
3679 850cff07 Ermal Lu?i
		}
3680 c7ed2141 sullrich
		sort($protocols_new);
3681 f63d5b66 Helder Pereira
	}		
3682 c7ed2141 sullrich
	return $protocols_new;
3683 f63d5b66 Helder Pereira
}
3684
3685
function get_l7_unique_list() {
3686
	global $layer7_rules_list;
3687
	
3688
	$l7list = array();
3689
	if(is_array($layer7_rules_list)) 
3690
		foreach($layer7_rules_list as $l7c)
3691
			if($l7c->GetREnabled())
3692
				$l7list[] = $l7c->GetRName();
3693
	
3694
	return $l7list;
3695
}
3696
3697
// Disable a removed l7 container from the filter
3698
function cleanup_l7_from_rules(&$name) {
3699
	global $config;
3700
3701 daee46a5 Helder Pereira
	if(is_array($config['filter']['rule']))
3702
		foreach ($config['filter']['rule'] as $key => $rule) {
3703
			if ($rule['l7container'] == $name)
3704
				unset($config['filter']['rule'][$key]['l7container']);
3705
		}
3706
}
3707
3708
function get_dummynet_name_list() {
3709
	
3710
	$dn_name_list =& get_unique_dnqueue_list();
3711
	$dn_name = array();
3712
	if(is_array($dn_name_list))
3713
		foreach($dn_name_list as $key => $value)
3714
			$dn_name[] = $key;
3715
	
3716
	return $dn_name;
3717
	
3718
}
3719
3720
function get_altq_name_list() {
3721
	$altq_name_list =& get_unique_queue_list();
3722
	$altq_name = array();
3723
	if(is_array($altq_name_list))
3724
		foreach($altq_name_list as $key => $aqobj)
3725
			$altq_name[] = $key;
3726
		
3727
	return $altq_name;
3728 f63d5b66 Helder Pereira
}
3729 c25a6b6a Ermal Luçi
3730 197bfe96 Ermal Luçi
/*
3731
 * XXX: TODO Make a class shaper to hide all these function
3732
 * from the global namespace.
3733
 */
3734
3735
/* 
3736
 * This is a layer violation but for now there is no way 
3737
 * i can find to properly do this with PHP.
3738
 */
3739
function altq_set_default_queue($interface, $value) {
3740
	global $altq_list_queues;
3741
		
3742
	$altq_tmp =& $altq_list_queues[$interface];
3743
	if ($altq_tmp) {
3744
		if ($value) {
3745
			$altq_tmp->SetDefaultQueuePresent("true");
3746 061f78b1 Bill Marquette
		}
3747 197bfe96 Ermal Luçi
		else {
3748
			$altq_tmp->SetDefaultQueuePresent("false");
3749 061f78b1 Bill Marquette
		}
3750 197bfe96 Ermal Luçi
	}
3751
}
3752 061f78b1 Bill Marquette
3753 197bfe96 Ermal Luçi
function altq_get_default_queue($interface) {
3754
	global $altq_list_queues;
3755 061f78b1 Bill Marquette
3756 197bfe96 Ermal Luçi
	$altq_tmp = $altq_list_queues[$interface];
3757
	if ($altq_tmp)  
3758
		return $altq_tmp->GetDefaultQueuePresent(); 
3759
}
3760 061f78b1 Bill Marquette
3761 21a0464c Ermal Luçi
function altq_check_default_queues() {
3762
	global $altq_list_queues;
3763
3764
	$count = 0;
3765
	if (is_array($altq_list_queues)) {
3766
		foreach($altq_list_queues as $altq) {
3767
			if ($altq->GetDefaultQueuePresent())
3768
				$count++;
3769
		}
3770
	}
3771
	else  $count++;;
3772
	
3773
	return 0;
3774
}
3775
3776
function &get_unique_queue_list() {
3777
	global $altq_list_queues;
3778
	
3779
	$qlist = array();
3780
	if (is_array($altq_list_queues)) {
3781
		foreach ($altq_list_queues as $altq) {
3782
			$tmplist =& $altq->get_queue_list();
3783
			foreach ($tmplist as $qname => $link)
3784
				$qlist[$qname] = $link;	
3785
		}
3786
	}
3787
	return $qlist;
3788
}
3789
3790 309ffde9 Ermal Luçi
function &get_unique_dnqueue_list() {
3791 c25a6b6a Ermal Luçi
	global $dummynet_pipe_list;
3792
	
3793
	$qlist = array();
3794
	if (is_array($dummynet_pipe_list)) {
3795
		foreach ($dummynet_pipe_list as $dn) {
3796
			$tmplist =& $dn->get_queue_list();
3797
			foreach ($tmplist as $qname => $link)
3798
				$qlist[$qname] = $link;	
3799
		}
3800
	}
3801
	return $qlist;
3802
}
3803
3804 197bfe96 Ermal Luçi
function ref_on_altq_queue_list($parent, $qname) {
3805
	if (isset($GLOBALS['queue_list'][$qname]))
3806
		$GLOBALS['queue_list'][$qname]++;
3807
	else
3808
		$GLOBALS['queue_list'][$qname] = 1;
3809 061f78b1 Bill Marquette
3810 197bfe96 Ermal Luçi
	unref_on_altq_queue_list($parent);
3811
}
3812 061f78b1 Bill Marquette
3813 197bfe96 Ermal Luçi
function unref_on_altq_queue_list($qname) {
3814
	$GLOBALS['queue_list'][$qname]--;
3815
	if ($GLOBALS['queue_list'][$qname] <= 1)
3816
		unset($GLOBALS['queue_list'][$qname]);	
3817
}
3818 061f78b1 Bill Marquette
3819 197bfe96 Ermal Luçi
function read_altq_config() {
3820
	global $altq_list_queues, $config;
3821
	$path = array();
3822
	
3823 7849bdd5 Ermal Lu?i
	if (!is_array($config['shaper']))
3824
		$config['shaper'] = array();
3825
	if (!is_array($config['shaper']['queue']))
3826
		$config['shaper']['queue'] = array();
3827 197bfe96 Ermal Luçi
	$a_int = &$config['shaper']['queue'];
3828
3829
	$altq_list_queues = array();
3830
	
3831
	if (!is_array($config['shaper']['queue']))
3832
		return;
3833
3834
	foreach ($a_int as $key => $conf) {
3835 92125c97 Ermal Luçi
				$int = $conf['interface'];
3836 62150088 Ermal Lu?i
				$root =& new altq_root_queue();
3837 92125c97 Ermal Luçi
				$root->SetInterface($int);
3838
				$altq_list_queues[$root->GetInterface()] = &$root;
3839
				$root->ReadConfig($conf);
3840 197bfe96 Ermal Luçi
		array_push($path, $key);
3841
		$root->SetLink($path);
3842
		if (is_array($conf['queue'])) {
3843
			foreach ($conf['queue'] as $key1 => $q) {
3844
				array_push($path, $key1);
3845 92125c97 Ermal Luçi
				/* 
3846
				 * XXX: we compeletely ignore errors here but anyway we must have 
3847
				 *	checked them before so no harm should be come from this.
3848
				 */
3849
				$root->add_queue($root->GetInterface(), $q, &$path, $input_errors);
3850 197bfe96 Ermal Luçi
				array_pop($path);
3851
			} 	
3852 92125c97 Ermal Luçi
				}
3853 197bfe96 Ermal Luçi
		array_pop($path);
3854
	}
3855
}
3856 0a33f73e Scott Ullrich
3857 c25a6b6a Ermal Luçi
function read_dummynet_config() {
3858
	global $dummynet_pipe_list, $config;
3859
	$path = array();
3860 d62ba478 Ermal Luçi
	$dnqueuenumber = 1;
3861
	$dnpipenumber = 1;
3862
3863 aa10aadc Ermal Lu?i
	if (!is_array($config['dnshaper']))
3864
		$config['dnshaper'] = array();
3865
	if (!is_array($config['dnshaper']['queue']))
3866
		$config['dnshaper']['queue'] = array();
3867 c25a6b6a Ermal Luçi
	$a_int = &$config['dnshaper']['queue'];
3868 2f038c0b Scott Ullrich
3869 c25a6b6a Ermal Luçi
	$dummynet_pipe_list = array();
3870
	
3871 ec656e20 Ermal Luçi
	if (!is_array($config['dnshaper']['queue'])
3872
		|| !count($config['dnshaper']['queue']))
3873 c25a6b6a Ermal Luçi
		return;
3874
3875
	foreach ($a_int as $key => $conf) {
3876 ec656e20 Ermal Luçi
		if (empty($conf['name']))
3877
			continue; /* XXX: grrrrrr at php */ 
3878 62150088 Ermal Lu?i
		$root =& new dnpipe_class();
3879 d62ba478 Ermal Luçi
		$root->ReadConfig($conf);
3880
		$root->SetNumber($dnpipenumber);	
3881
		$dummynet_pipe_list[$root->GetQname()] = &$root;
3882
		array_push($path, $key);
3883
		$root->SetLink($path);
3884
		if (is_array($conf['queue'])) {
3885
			foreach ($conf['queue'] as $key1 => $q) {
3886
				array_push($path, $key1);
3887
				/* XXX: We cheat a little here till a better way is found. */
3888
				$q['number'] = $dnqueuenumber;
3889
				/* 
3890
				 * XXX: we compeletely ignore errors here but anyway we must have 
3891
				 *	checked them before so no harm should be come from this.
3892
				 */	
3893
				$root->add_queue($root->GetQname(), $q, &$path, $input_errors);
3894 c25a6b6a Ermal Luçi
				array_pop($path);
3895 d62ba478 Ermal Luçi
3896
				$dnqueuenumber++;
3897
			} 	
3898
		}
3899
		array_pop($path);
3900
			
3901
		$dnpipenumber++;
3902 c25a6b6a Ermal Luçi
	}
3903
}
3904 0a33f73e Scott Ullrich
3905 197bfe96 Ermal Luçi
function get_interface_list_to_show() {
3906
	global $altq_list_queues, $config;
3907 057399e4 Ermal Luçi
	global $shaperIFlist;
3908
3909 197bfe96 Ermal Luçi
	$tree = "";
3910 057399e4 Ermal Luçi
	foreach ($shaperIFlist as $shif => $shDescr) {
3911
		if ($altq_list_queues[$shif]) {
3912 197bfe96 Ermal Luçi
			continue;
3913 a843b04f Ermal Luçi
		} else  {
3914 057399e4 Ermal Luçi
			if (!is_altq_capable(get_real_interface($shif)))
3915 0b033d22 Ermal Luçi
				continue;
3916 9cf48832 Ermal Luçi
			$tree .= " <li><a href=\"firewall_shaper.php?interface=".$shif."&action=add\">".$shDescr."</a></li>";
3917 197bfe96 Ermal Luçi
		}
3918
	}
3919
	
3920
	return $tree;
3921
}
3922 061f78b1 Bill Marquette
3923 197bfe96 Ermal Luçi
function filter_generate_altq_queues() {
3924
	global $altq_list_queues;
3925
	
3926
	read_altq_config();
3927 061f78b1 Bill Marquette
3928 197bfe96 Ermal Luçi
	$altq_rules = "";
3929
	foreach ($altq_list_queues as $altq) 
3930
		$altq_rules .= $altq->build_rules();
3931 0f0c6a9e Scott Ullrich
3932 197bfe96 Ermal Luçi
	return $altq_rules;
3933
}
3934 0f0c6a9e Scott Ullrich
3935 d62ba478 Ermal Luçi
function filter_generate_dummynet_rules() {
3936 d41e63b6 Ermal
	global $g, $dummynet_pipe_list;
3937 c25a6b6a Ermal Luçi
	
3938
	read_dummynet_config();
3939 d62ba478 Ermal Luçi
	
3940 ec656e20 Ermal Luçi
	if (!empty($dummynet_pipe_list)) {
3941 1ab56363 Ermal Lu?i
		if (!is_module_loaded("dummynet.ko"))
3942
			mwexec("/sbin/kldload dummynet");
3943 3a05416f Ermal Luçi
		/* XXX: Needs to be added code elsewhere to clear pipes/queues from kernel when not needed! */
3944
		//mwexec("pfctl -F dummynet");
3945 d62ba478 Ermal Luçi
	}
3946 c25a6b6a Ermal Luçi
3947
	$dn_rules = "";
3948 7807634c Ermal Luçi
	foreach ($dummynet_pipe_list as $dn) 
3949 c25a6b6a Ermal Luçi
		$dn_rules .= $dn->build_rules();
3950
3951 e3e5160c Ermal
	if (!empty($dn_rules)) {
3952 d41e63b6 Ermal
		file_put_contents("{$g['tmp_path']}/rules.limiter", $dn_rules);
3953
		mwexec("/sbin/ipfw {$g['tmp_path']}/rules.limiter");
3954
	}
3955
	//return $dn_rules;
3956 c25a6b6a Ermal Luçi
}
3957 0a33f73e Scott Ullrich
3958 197bfe96 Ermal Luçi
function build_iface_without_this_queue($iface, $qname) {
3959
	global $g, $altq_list_queues;
3960 0a33f73e Scott Ullrich
3961 197bfe96 Ermal Luçi
	$altq =& $altq_list_queues[$iface];
3962 92125c97 Ermal Luçi
				if ($altq)
3963
						$scheduler = ": " . $altq->GetScheduler();
3964 197bfe96 Ermal Luçi
	$form = "<tr><td width=\"20%\" >";
3965 17d058aa Ermal
	$form .= "<a href=\"firewall_shaper.php?interface=" . $iface . "&queue=" . $iface."&action=show\">".$iface.": ".$scheduler."</a>";
3966 dbaf21d4 Renato Botelho
	$form .= "</td></tr>";
3967
	$form .= "<tr><td width=\"100%\" class=\"vncellreq\">";
3968
	$form .= "<a href=\"firewall_shaper_queues.php?interface=";
3969
	$form .= $iface . "&queue=". $qname . "&action=add\">";
3970
	$form .= "<img src=\"";
3971
	$form .= "./themes/".$g['theme']."/images/icons/icon_plus.gif\"";
3972
	$form .= " width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("Clone shaper/queue on this interface") . "\">";
3973
	$form .= gettext(" Clone shaper/queue on this interface") . "</a></td></tr>";
3974 92125c97 Ermal Luçi
3975 dbaf21d4 Renato Botelho
	return $form;
3976 0a33f73e Scott Ullrich
3977 197bfe96 Ermal Luçi
}
3978 0a33f73e Scott Ullrich
3979 061f78b1 Bill Marquette
3980 58dc3a03 Ermal Luçi
$default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3981 dbaf21d4 Renato Botelho
$default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>" . sprintf(gettext("Welcome to the %s Traffic Shaper."), $g['product_name']) . "</b><br />";
3982
$default_shaper_msg .= gettext("The tree on the left helps you navigate through the queues <br />"
3983
                    .  "buttons at the bottom represent queue actions and are activated accordingly.");
3984 f63d5b66 Helder Pereira
$default_shaper_msg .= " </p></strong></span>";
3985 197bfe96 Ermal Luçi
$default_shaper_msg .= "</td></tr>";
3986 061f78b1 Bill Marquette
3987 d62ba478 Ermal Luçi
$dn_default_shaper_msg =	"<tr><td align=\"center\" width=\"80%\" >";
3988 dbaf21d4 Renato Botelho
$dn_default_shaper_msg .= "<span class=\"vexpl\"><strong><p><b>" . sprintf(gettext("Welcome to the %s Traffic Shaper."), $g['product_name']) . "</b><br />";
3989
$dn_default_shaper_msg .= gettext("The tree on the left helps you navigate through the queues <br />"
3990
                       .  "buttons at the bottom represent queue actions and are activated accordingly.");
3991 f63d5b66 Helder Pereira
$dn_default_shaper_msg .= " </p></strong></span>";
3992 d62ba478 Ermal Luçi
$dn_default_shaper_msg .= "</td></tr>";
3993
3994
3995
3996 6955830f Ermal Lu?i
?>