]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - html/cgi-bin/qos.cgi
suricata: Change midstream policy to "pass-flow"
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / qos.cgi
CommitLineData
904a41b9 1#!/usr/bin/perl
70df8302
MT
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
57d4e488 5# Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
70df8302
MT
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
904a41b9 21
7ccede9b 22use RRDs;
904a41b9
MT
23use strict;
24# enable only the following on debugging purpose
e8babc92 25# use warnings;
33e1f48c 26# use CGI::Carp 'fatalsToBrowser';
904a41b9
MT
27
28require '/var/ipfire/general-functions.pl';
29require "${General::swroot}/lang.pl";
30require "${General::swroot}/header.pl";
0b1641db 31require "${General::swroot}/graphs.pl";
904a41b9 32
2db5d932
MT
33my %qossettings = ();
34my %checked = ();
35my %netsettings = ();
363fb6af 36my $message = '';
904a41b9 37my $errormessage = "";
2db5d932
MT
38my $c = "";
39my $direntry = "";
414e011d 40my $classentry = "";
414e011d 41my $l7ruleentry = "";
84cab473 42my $portruleentry = "";
e8babc92 43my $tosruleentry = "";
414e011d
MT
44my @tmp = ();
45my @classes = ();
414e011d 46my @l7rules = ();
84cab473 47my @portrules = ();
e8babc92 48my @tosrules = ();
414e011d
MT
49my @tmpline = ();
50my @classline = ();
414e011d 51my @l7ruleline = ();
84cab473 52my @portruleline = ();
e8babc92 53my @tosruleline = ();
2db5d932 54my @proto = ();
e8babc92
MT
55my %selected= ();
56my @checked = ();
414e011d 57my $classfile = "/var/ipfire/qos/classes";
414e011d 58my $level7file = "/var/ipfire/qos/level7config";
84cab473 59my $portfile = "/var/ipfire/qos/portconfig";
e8babc92 60my $tosfile = "/var/ipfire/qos/tosconfig";
904a41b9
MT
61&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
62
2db5d932 63$qossettings{'ENABLED'} = 'off';
414e011d 64$qossettings{'EDIT'} = 'no';
904a41b9
MT
65$qossettings{'OUT_SPD'} = '';
66$qossettings{'INC_SPD'} = '';
84cab473
MT
67$qossettings{'DEF_OUT_SPD'} = '';
68$qossettings{'DEF_INC_SPD'} = '';
2db5d932
MT
69$qossettings{'DEFCLASS_INC'} = '';
70$qossettings{'DEFCLASS_OUT'} = '';
4d17a269 71$qossettings{'RED_DEV'} = 'ppp0';
904a41b9 72$qossettings{'IMQ_DEV'} = 'imq0';
414e011d 73$qossettings{'VALID'} = 'yes';
84cab473
MT
74### Values that have to be initialized
75$qossettings{'ACTION'} = '';
76$qossettings{'ACTIONDEF'} = '';
77$qossettings{'ACTIONBW'} = '';
e8babc92
MT
78$qossettings{'RED_DEV_SEL'} = '';
79$qossettings{'IMQ_DEV_SEL'} = '';
84cab473
MT
80$qossettings{'PRIO'} = '';
81$qossettings{'SPD'} = '';
82$qossettings{'CLASS'} = '';
84cab473
MT
83$qossettings{'QPORT'} = '';
84$qossettings{'DPORT'} = '';
85$qossettings{'QIP'} = '';
86$qossettings{'DIP'} = '';
87$qossettings{'PPROT'} = '';
88$qossettings{'L7PROT'} = '';
89$qossettings{'DEVICE'} = '';
90$qossettings{'MINBWDTH'} = '';
91$qossettings{'MAXBWDTH'} = '';
92$qossettings{'BURST'} = '';
93$qossettings{'CBURST'} = '';
94$qossettings{'DOCLASS'} = '';
84cab473
MT
95$qossettings{'DOLEVEL7'} = '';
96$qossettings{'DOPORT'} = '';
7ccede9b
MT
97$qossettings{'CLASS'} = '';
98$qossettings{'CLASSPRFX'} = '';
99$qossettings{'DEV'} = '';
e8babc92 100$qossettings{'TOS'} = '';
ca26f732
MT
101$qossettings{'CAKE_PROFILE'} = 'conservative';
102
103my %CAKE_PROFILES = (
104 "ethernet" => $Lang::tr{'cake profile ethernet 38'},
105 "ethernet ether-vlan" => $Lang::tr{'cake profile ethernet vlan 42'},
106 "raw" => $Lang::tr{'cake profile raw 0'},
107 "conservative" => $Lang::tr{'cake profile conservative 48'},
108 "docsis" => $Lang::tr{'cake profile docsis 18'},
109 "bridged-ptm" => $Lang::tr{'cake profile bridged-ptm 19'},
110 "pppoe-ptm" => $Lang::tr{'cake profile pppoe-ptm 27'},
111 "pppoe-llcsnap" => $Lang::tr{'cake profile pppoe-llcsnap 40'},
112 "pppoe-vcmux" => $Lang::tr{'cake profile pppoe-vcmux 32'},
113 "pppoa-llc" => $Lang::tr{'cake profile pppoa-llc 14'},
114 "pppoa-vcmux" => $Lang::tr{'cake profile pppoa-vcmux 10'},
115 "bridged-llcsnap" => $Lang::tr{'cake profile bridged-llcsnap 32'},
116 "bridged-vcmux" => $Lang::tr{'cake profile bridged-vcmux 24'},
117 "ipoa-llcsnap" => $Lang::tr{'cake profile ipoa-llcsnap 16'},
118 "ipoa-vcmux" => $Lang::tr{'cake profile ipoa-vcmux 8'},
119);
904a41b9
MT
120
121&General::readhash("${General::swroot}/qos/settings", \%qossettings);
122&Header::getcgihash(\%qossettings);
123
12317449 124$qossettings{'RED_DEV'} = &General::get_red_interface();
4d17a269 125
f2fdd0c1
CS
126my %color = ();
127my %mainsettings = ();
128&General::readhash("${General::swroot}/main/settings", \%mainsettings);
8186b372 129&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
f2fdd0c1 130
ca26f732
MT
131$selected{'CAKE_PROFILE'} = ();
132foreach my $key (keys %CAKE_PROFILES) {
133 $selected{'CAKE_PROFILE'}{$key} = '';
134}
135$selected{'CAKE_PROFILE'}{$qossettings{'CAKE_PROFILE'}} = 'selected';
136
4190b2a6 137&Header::showhttpheaders();
bcad0fd0 138
4190b2a6
LAH
139&Header::openpage('QoS', 1, '');
140&Header::openbigbox('100%', 'left', '', $errormessage);
904a41b9 141
84cab473
MT
142############################################################################################################################
143############################################################################################################################
144
145if ($qossettings{'DOCLASS'} eq $Lang::tr{'save'})
414e011d
MT
146{
147 &validclass();
148 &validminbwdth();
149 &validmaxbwdth();
150 if ( $qossettings{'VALID'} eq 'yes' ) {
151 open( FILE, ">> $classfile" ) or die "Unable to write $classfile";
152 print FILE <<END
f013ab2b 153$qossettings{'DEVICE'};$qossettings{'CLASS'};$qossettings{'PRIO'};$qossettings{'MINBWDTH'};$qossettings{'MAXBWDTH'};$qossettings{'BURST'};$qossettings{'CBURST'};$qossettings{'TOS'};$qossettings{'REMARK'};
414e011d
MT
154END
155;
156 close FILE;
157 } else {
65e8619a 158 $qossettings{'ACTION'} = $Lang::tr{'parentclass add'};
414e011d
MT
159 }
160}
65e8619a 161elsif ($qossettings{'DOCLASS'} eq $Lang::tr{'edit'})
414e011d
MT
162{
163 open( FILE, "< $classfile" ) or die "Unable to read $classfile";
164 @classes = <FILE>;
165 close FILE;
166 open( FILE, "> $classfile" ) or die "Unable to write $classfile";
167 foreach $classentry (sort @classes)
168 {
169 @classline = split( /\;/, $classentry );
170 if ( $classline[1] ne $qossettings{'CLASS'} ) {
171 print FILE $classentry;
172 } else {
173 $qossettings{'DEVICE'} = $classline[0];
174 $qossettings{'PRIO'} = $classline[2];
175 $qossettings{'MINBWDTH'} = $classline[3];
176 $qossettings{'MAXBWDTH'} = $classline[4];
177 $qossettings{'BURST'} = $classline[5];
178 $qossettings{'CBURST'} = $classline[6];
f013ab2b
MT
179 $qossettings{'TOS'} = $classline[7];
180 $qossettings{'REMARK'} = $classline[8];
414e011d
MT
181 $qossettings{'EDIT'} = 'yes';
182 }
183 }
184 close FILE;
185 &parentclass();
186 &Header::closebigbox();
187 &Header::closepage();
188 exit
189}
65e8619a 190elsif ($qossettings{'DOCLASS'} eq $Lang::tr{'delete'})
414e011d
MT
191{
192 open( FILE, "< $classfile" ) or die "Unable to read $classfile";
193 @tmp = <FILE>;
194 close FILE;
195 open( FILE, "> $classfile" ) or die "Unable to write $classfile";
196 foreach $classentry (sort @tmp)
197 {
198 @tmpline = split( /\;/, $classentry );
199 if ( $tmpline[1] ne $qossettings{'CLASS'} )
200 {
201 print FILE $classentry;
202 }
203 }
204 close FILE;
0b1641db 205 $message = "$Lang::tr{'Class'} $qossettings{'CLASS'} $Lang::tr{'Class was deleted'}";
414e011d 206}
84cab473
MT
207
208############################################################################################################################
209############################################################################################################################
210
84cab473 211if ($qossettings{'DOLEVEL7'} eq $Lang::tr{'save'})
414e011d
MT
212{
213 if ( $qossettings{'QIP'} ne '' ) {
5a7491ff
MT
214 if ((!&General::validipandmask($qossettings{'QIP'})) && (!&General::validip($qossettings{'QIP'}))) {
215 $qossettings{'VALID'} = 'no';
216 $message = $Lang::tr{'The source IP address is invalid.'};
414e011d
MT
217 }
218 }
219 if ( $qossettings{'DIP'} ne '' ) {
5a7491ff
MT
220 if ((!&General::validipandmask($qossettings{'DIP'})) && (!&General::validip($qossettings{'DIP'}))) {
221 $qossettings{'VALID'} = 'no';
222 $message = $Lang::tr{'The destination IP address is invalid.'};
414e011d
MT
223 }
224 }
225 if ($qossettings{'CLASS'} >= 100 && $qossettings{'CLASS'} < 121) {
226 $qossettings{'DEVICE'} = $qossettings{'RED_DEV'};
227 } elsif ($qossettings{'CLASS'} >= 1000 && $qossettings{'CLASS'} < 1021) {
228 $qossettings{'DEVICE'} = $qossettings{'RED_DEV'};
229 } elsif ($qossettings{'CLASS'} >= 200 && $qossettings{'CLASS'} < 221) {
230 $qossettings{'DEVICE'} = $qossettings{'IMQ_DEV'};
231 } elsif ($qossettings{'CLASS'} >= 2000 && $qossettings{'CLASS'} < 2021) {
232 $qossettings{'DEVICE'} = $qossettings{'IMQ_DEV'};
233 }
234 if ( $qossettings{'VALID'} eq 'yes' ) {
235 open( FILE, ">> $level7file" ) or die "Unable to write $level7file";
236 print FILE <<END
237$qossettings{'CLASS'};$qossettings{'DEVICE'};$qossettings{'L7PROT'};$qossettings{'QIP'};$qossettings{'DIP'};
238END
239;
240 close FILE;
241 } else {
65e8619a 242 $qossettings{'ACTION'} = $Lang::tr{'Add Level7 rule'};
414e011d 243 }
65e8619a 244} elsif ($qossettings{'DOLEVEL7'} eq $Lang::tr{'delete'})
414e011d
MT
245{
246 open( FILE, "< $level7file" ) or die "Unable to read $level7file";
247 @l7rules = <FILE>;
248 close FILE;
5b8ecec9 249 &General::system("rm", "$level7file");
414e011d
MT
250 foreach $l7ruleentry (sort @l7rules)
251 {
252 @l7ruleline = split( /\;/, $l7ruleentry );
399d32cb 253 if ( ($l7ruleline[0] eq $qossettings{'CLASS'}) && ($l7ruleline[2] eq $qossettings{'L7PROT'}))
65e8619a 254 {$message = "$Lang::tr{'Level7 Rule'} ($qossettings{'CLASS'} - $qossettings{'L7PROT'}) $Lang::tr{'was deleted'}.";}
399d32cb
CS
255 else
256 { open( FILE, ">> $level7file" ) or die "Unable to read $level7file";
257 print FILE $l7ruleentry;
258 close FILE;
259 }
260 }
5b8ecec9 261 open( FILE, "< $level7file" ) or &General::system("touch", "$level7file");close FILE;
65e8619a 262 } elsif ($qossettings{'DOLEVEL7'} eq $Lang::tr{'edit'})
399d32cb
CS
263{
264 open( FILE, "< $level7file" ) or die "Unable to read $level7file";
265 @l7rules = <FILE>;
414e011d 266 close FILE;
5b8ecec9 267 &General::system("rm", "$level7file");
399d32cb
CS
268 foreach $l7ruleentry (sort @l7rules)
269 {
270 @l7ruleline = split( /\;/, $l7ruleentry );
271 if ( ($l7ruleline[0] eq $qossettings{'CLASS'}) && ($l7ruleline[2] eq $qossettings{'L7PROT'}))
272 {$qossettings{'QIP'} = $l7ruleline[3];$qossettings{'DIP'} = $l7ruleline[4];}
273 else {
274 open( FILE, ">> $level7file" ) or die "Unable to write $level7file";
275 print FILE $l7ruleentry;
276 close FILE;
277 }
278 }
279 &level7rule;
5b8ecec9 280 open( FILE, "< $level7file" ) or &General::system("touch", "$level7file");close FILE;
399d32cb 281 }
84cab473
MT
282
283############################################################################################################################
284############################################################################################################################
285
286if ($qossettings{'DOPORT'} eq $Lang::tr{'save'})
287{
288 if ( $qossettings{'QIP'} ne '' ) {
5a7491ff 289 if ((!&General::validipandmask($qossettings{'QIP'})) && (!&General::validip($qossettings{'QIP'}))) {
84cab473 290 $qossettings{'VALID'} = 'no';
5a7491ff 291 $message = $Lang::tr{'The source IP address is invalid.'};
84cab473
MT
292 }
293 }
294 if ( $qossettings{'DIP'} ne '' ) {
5a7491ff 295 if ((!&General::validipandmask($qossettings{'DIP'})) && (!&General::validip($qossettings{'DIP'}))) {
84cab473 296 $qossettings{'VALID'} = 'no';
5a7491ff 297 $message = $Lang::tr{'The destination IP address is invalid.'};
84cab473
MT
298 }
299 }
300 if ($qossettings{'CLASS'} >= 100 && $qossettings{'CLASS'} < 121) {
301 $qossettings{'DEVICE'} = $qossettings{'RED_DEV'};
302 } elsif ($qossettings{'CLASS'} >= 1000 && $qossettings{'CLASS'} < 1021) {
303 $qossettings{'DEVICE'} = $qossettings{'RED_DEV'};
304 } elsif ($qossettings{'CLASS'} >= 200 && $qossettings{'CLASS'} < 221) {
305 $qossettings{'DEVICE'} = $qossettings{'IMQ_DEV'};
306 } elsif ($qossettings{'CLASS'} >= 2000 && $qossettings{'CLASS'} < 2021) {
307 $qossettings{'DEVICE'} = $qossettings{'IMQ_DEV'};
308 }
309 if ( $qossettings{'VALID'} eq 'yes' ) {
310 open( FILE, ">> $portfile" ) or die "Unable to write $portfile";
311 print FILE <<END
312$qossettings{'CLASS'};$qossettings{'DEVICE'};$qossettings{'PPROT'};$qossettings{'QIP'};$qossettings{'QPORT'};$qossettings{'DIP'};$qossettings{'DPORT'};
313END
314;
315 close FILE;
316 } else {
65e8619a 317 $qossettings{'ACTION'} = $Lang::tr{'Add Port Rule'};
84cab473 318 }
65e8619a 319} elsif ($qossettings{'DOPORT'} eq $Lang::tr{'delete'})
84cab473
MT
320{
321 open( FILE, "< $portfile" ) or die "Unable to read $portfile";
322 @portrules = <FILE>;
323 close FILE;
324 open( FILE, "> $portfile" ) or die "Unable to read $portfile";
325 foreach $portruleentry (sort @portrules)
326 {
327 @portruleline = split( /\;/, $portruleentry );
328 unless ( ($portruleline[0] eq $qossettings{'CLASS'}) && ($portruleline[2] eq $qossettings{'PPROT'}) && ($portruleline[3] eq $qossettings{'QIP'}) && ($portruleline[4] eq $qossettings{'QPORT'}) && ($portruleline[5] eq $qossettings{'DIP'}) && ($portruleline[6] eq $qossettings{'DPORT'}))
329 {
330 print FILE $portruleentry;
331 }
332 }
333 close FILE;
0b1641db 334 $message = "$Lang::tr{'Port Rule'} ($qossettings{'CLASS'} - $qossettings{'PPROT'}) $Lang::tr{'was deleted'}.";
65e8619a 335} elsif ($qossettings{'DOPORT'} eq $Lang::tr{'edit'})
399d32cb
CS
336{
337 open( FILE, "< $portfile" ) or die "Unable to read $portfile";
338 @portrules = <FILE>;
339 close FILE;
5b8ecec9 340 &General::system("rm", "$portfile");
399d32cb
CS
341 foreach $portruleentry (sort @portrules)
342 {
343 @portruleline = split( /\;/, $portruleentry );
344 if ( ($portruleline[0] eq $qossettings{'CLASS'}) && ($portruleline[2] eq $qossettings{'PPROT'}) && ($portruleline[3] eq $qossettings{'QIP'}) && ($portruleline[4] eq $qossettings{'QPORT'}) && ($portruleline[5] eq $qossettings{'DIP'}) && ($portruleline[6] eq $qossettings{'DPORT'}))
345 {$qossettings{'CLASS'}=$portruleline[0];$qossettings{'PPROT'}=$portruleline[2];$qossettings{'QIP'}=$portruleline[3];$qossettings{'QPORT'}=$portruleline[4];$qossettings{'DIP'}=$portruleline[5];$qossettings{'DPORT'}=$portruleline[6];}
346 else {
347 open( FILE, ">> $portfile" ) or die "Unable to write $portfile";
348 print FILE $portruleentry;
349 close FILE;
350 }
351 }
352 &portrule;
5b8ecec9 353 open( FILE, "< $portfile" ) or &General::system("touch", "$portfile");close FILE;
399d32cb 354 }
84cab473
MT
355
356############################################################################################################################
357############################################################################################################################
358
e8babc92
MT
359if ($qossettings{'DOTOS'} eq $Lang::tr{'save'})
360{
361 if ($qossettings{'CLASS'} >= 100 && $qossettings{'CLASS'} < 121) {
362 $qossettings{'DEVICE'} = $qossettings{'RED_DEV'};
363 } elsif ($qossettings{'CLASS'} >= 1000 && $qossettings{'CLASS'} < 1021) {
364 $qossettings{'DEVICE'} = $qossettings{'RED_DEV'};
365 } elsif ($qossettings{'CLASS'} >= 200 && $qossettings{'CLASS'} < 221) {
366 $qossettings{'DEVICE'} = $qossettings{'IMQ_DEV'};
367 } elsif ($qossettings{'CLASS'} >= 2000 && $qossettings{'CLASS'} < 2021) {
368 $qossettings{'DEVICE'} = $qossettings{'IMQ_DEV'};
369 }
370 open( FILE, ">> $tosfile" ) or die "Unable to write $tosfile";
371 print FILE <<END
372$qossettings{'CLASS'};$qossettings{'DEVICE'};$qossettings{'TOS'};
373END
374;
375 close FILE;
fcd5cb6f 376}
fc81e493 377elsif ($qossettings{'DOTOS'} eq $Lang::tr{'delete'})
e8babc92
MT
378{
379 open( FILE, "< $tosfile" ) or die "Unable to read $tosfile";
380 @tosrules = <FILE>;
381 close FILE;
382 open( FILE, "> $tosfile" ) or die "Unable to read $tosfile";
383 foreach $tosruleentry (sort @tosrules)
384 {
385 @tosruleline = split( /\;/, $tosruleentry );
386 unless ( ($tosruleline[0] eq $qossettings{'CLASS'}) && ($tosruleline[2] eq $qossettings{'TOS'}))
387 {
388 print FILE $tosruleentry;
389 }
390 }
391 close FILE;
0b1641db 392 $message = "$Lang::tr{'TOS Rule'} ($qossettings{'CLASS'} - $qossettings{'TOS'}) $Lang::tr{'was deleted'}.";
65e8619a 393} elsif ($qossettings{'DOTOS'} eq $Lang::tr{'edit'})
e8babc92
MT
394{
395 open( FILE, "< $tosfile" ) or die "Unable to read $tosfile";
396 @tosrules = <FILE>;
397 close FILE;
398 open( FILE, "> $tosfile" ) or die "Unable to write $tosfile";
399 foreach $tosruleentry (sort @tosrules)
400 {
401 @tosruleline = split( /\;/, $tosruleentry );
402 if (( $tosruleline[0] eq $qossettings{'CLASS'} ) && ( $tosruleline[2] eq $qossettings{'TOS'} )) {
403 $qossettings{'DEVICE'} = $tosruleline[1];
404 $qossettings{'CLASS'} = $tosruleline[0];
405 $qossettings{'TOS'} = $tosruleline[2];
406 $qossettings{'EDIT'} = 'yes';
407 } else {
408 print FILE $tosruleentry;
409 }
410 }
411 close FILE;
412 &tosrule();
413 &Header::closebigbox();
414 &Header::closepage();
415 exit
416}
417
418############################################################################################################################
419############################################################################################################################
420
65e8619a 421if ($qossettings{'ACTION'} eq $Lang::tr{'start'})
904a41b9 422{
8b6a7fde
CS
423 $qossettings{'ENABLED'} = 'on';
424 &General::writehash("${General::swroot}/qos/settings", \%qossettings);
5b8ecec9
MT
425 &General::system("/usr/local/bin/qosctrl", "generate");
426 &General::system("/usr/local/bin/qosctrl", "start");
427 &General::system("logger", "-t", "ipfire", "QoS started");
904a41b9 428}
65e8619a 429elsif ($qossettings{'ACTION'} eq $Lang::tr{'stop'})
904a41b9 430{
904a41b9
MT
431 $qossettings{'ENABLED'} = 'off';
432 &General::writehash("${General::swroot}/qos/settings", \%qossettings);
5b8ecec9
MT
433 &General::system("/usr/local/bin/qosctrl", "stop");
434 &General::system("/usr/local/bin/qosctrl", "generate");
435 &General::system("logger", "-t", "ipfire", "QoS stopped");
904a41b9 436}
65e8619a 437elsif ($qossettings{'ACTION'} eq $Lang::tr{'restart'})
84cab473
MT
438{
439 if ($qossettings{'ENABLED'} eq 'on'){
5b8ecec9
MT
440 &General::system("/usr/local/bin/qosctrl", "stop");
441 &General::system("/usr/local/bin/qosctrl", "generate");
442 &General::system("/usr/local/bin/qosctrl", "start");
443 &General::system("logger", "-t", "ipfire", "QoS restarted");
84cab473
MT
444 }
445}
904a41b9
MT
446elsif ($qossettings{'ACTION'} eq $Lang::tr{'save'})
447{
84cab473
MT
448 if ($qossettings{'DEF_INC_SPD'} eq '') {
449 $qossettings{'DEF_INC_SPD'} = int($qossettings{'INC_SPD'} * 0.9);
450 }
451 if ($qossettings{'DEF_OUT_SPD'} eq '') {
452 $qossettings{'DEF_OUT_SPD'} = int($qossettings{'OUT_SPD'} * 0.9);
453 }
904a41b9
MT
454 &General::writehash("${General::swroot}/qos/settings", \%qossettings);
455}
33e1f48c
CS
456elsif ($qossettings{'ACTION'} eq $Lang::tr{'template'} )
457{
40d3e729
MT
458 if (($qossettings{'OUT_SPD'} > 0) && ($qossettings{'INC_SPD'} > 0)) {
459 my @UP;
460 #print "UP<br />";
461 for(my $i = 1; $i <= 10; $i++) {
462 $UP[$i] = int($qossettings{'OUT_SPD'} / $i );
463 #print $i."=".$UP[$i]." ";
464 }
465 my @DOWN;
466 #print "<br /><br />Down<br />";
467 for(my $i = 1; $i <= 20; $i++) {
468 $DOWN[$i] = int($qossettings{'INC_SPD'} / $i);
469 #print $i."=".$DOWN[$i]." ";
470 }
471 open( FILE, "> $classfile" ) or die "Unable to write $classfile";
472 print FILE <<END
20ffa7d1 473imq0;200;1;$DOWN[20];$DOWN[1];;;8;VoIP;
33e1f48c
CS
474imq0;203;4;$DOWN[20];$DOWN[1];;;0;VPN;
475imq0;204;5;$DOWN[20];$DOWN[1];;;8;Webtraffic;
99a6f5f9 476imq0;210;6;1;$DOWN[1];;;0;Default;
f31cb9a1 477imq0;220;7;1;$DOWN[1];;;1;P2P;
20ffa7d1
DW
478$qossettings{'RED_DEV'};101;1;$UP[10];$UP[1];;;8;ACKs;
479$qossettings{'RED_DEV'};102;2;$UP[10];$UP[1];;;8;VoIP;
480$qossettings{'RED_DEV'};103;4;$UP[10];$UP[1];;;2;VPN;
fcd5cb6f 481$qossettings{'RED_DEV'};104;5;$UP[10];$UP[1];;;8;Webtraffic;
99a6f5f9 482$qossettings{'RED_DEV'};110;6;1;$UP[1];;;0;Default;
f31cb9a1 483$qossettings{'RED_DEV'};120;7;1;$UP[1];;;1;P2P;
33e1f48c
CS
484END
485;
40d3e729
MT
486 close FILE;
487 open( FILE, "> $level7file" ) or die "Unable to write $level7file";
488 print FILE <<END
fcd5cb6f 489102;$qossettings{'RED_DEV'};dns;;;
21067331 490102;$qossettings{'RED_DEV'};rtp;;;
fcd5cb6f
MT
491102;$qossettings{'RED_DEV'};skypetoskype;;;
492103;$qossettings{'RED_DEV'};ssh;;;
493103;$qossettings{'RED_DEV'};rdp;;;
494104;$qossettings{'RED_DEV'};http;;;
495104;$qossettings{'RED_DEV'};ssl;;;
496104;$qossettings{'RED_DEV'};pop3;;;
fcd5cb6f
MT
497120;$qossettings{'RED_DEV'};applejuice;;;
498120;$qossettings{'RED_DEV'};bittorrent;;;
21067331 499200;imq0;rtp;;;
33e1f48c
CS
500200;imq0;skypetoskype;;;
501203;imq0;ssh;;;
502203;imq0;rdp;;;
503204;imq0;http;;;
504204;imq0;pop3;;;
505204;imq0;ssl;;;
506220;imq0;applejuice;;;
507220;imq0;bittorrent;;;
33e1f48c
CS
508END
509;
40d3e729
MT
510 close FILE;
511 open( FILE, "> $portfile" ) or die "Unable to write $portfile";
512 print FILE <<END
fcd5cb6f
MT
513101;$qossettings{'RED_DEV'};icmp;;;;;
514102;$qossettings{'RED_DEV'};tcp;;;;53;
515102;$qossettings{'RED_DEV'};udp;;;;53;
516103;$qossettings{'RED_DEV'};esp;;;;;
8de8a508
AF
517103;$qossettings{'RED_DEV'};tcp;;1194;;;
518103;$qossettings{'RED_DEV'};udp;;1194;;;
fcd5cb6f 519103;$qossettings{'RED_DEV'};tcp;;;;1194;
99a6f5f9 520103;$qossettings{'RED_DEV'};udp;;;;1194;
fcd5cb6f
MT
521103;$qossettings{'RED_DEV'};udp;;4500;;4500;
522103;$qossettings{'RED_DEV'};udp;;500;;500;
523104;$qossettings{'RED_DEV'};tcp;;;;80;
33e1f48c
CS
524200;imq0;icmp;;;;;
525203;imq0;esp;;;;;
526203;imq0;tcp;;;;1194;
773362c5 527203;imq0;udp;;;;1194;
8de8a508
AF
528203;imq0;tcp;;1194;;;
529203;imq0;udp;;1194;;;
33e1f48c
CS
530203;imq0;udp;;4500;;4500;
531203;imq0;udp;;500;;500;
8de8a508 532204;imq0;tcp;;80;;;
33e1f48c
CS
533END
534;
40d3e729
MT
535 close FILE;
536 if ($qossettings{'DEF_INC_SPD'} eq '') {
537 $qossettings{'DEF_INC_SPD'} = int($qossettings{'INC_SPD'} * 0.9);
538 }
539 if ($qossettings{'DEF_OUT_SPD'} eq '') {
540 $qossettings{'DEF_OUT_SPD'} = int($qossettings{'OUT_SPD'} * 0.9);
541 }
542 $qossettings{'DEFCLASS_INC'} = "210";
543 $qossettings{'DEFCLASS_OUT'} = "110";
40d3e729
MT
544 $qossettings{'ENABLED'} = 'on';
545 &General::writehash("${General::swroot}/qos/settings", \%qossettings);
5b8ecec9
MT
546 &General::system("/usr/local/bin/qosctrl", "generate");
547 &General::system("/usr/local/bin/qosctrl", "start");
548 &General::system("logger", "-t", "ipfire", "QoS started");
40d3e729
MT
549 } else {
550 $message = $Lang::tr{'qos enter bandwidths'};
33e1f48c 551 }
33e1f48c 552}
65e8619a 553elsif ($qossettings{'ACTION'} eq $Lang::tr{'status'} )
92b5fba4
MT
554{
555 &Header::openbox('100%', 'left', 'QoS Status');
556 if ($qossettings{'ENABLED'} eq 'on'){
557 my $output = "";
12317449 558 my @output = &General::system_output("/usr/local/bin/qosctrl", "status");
c4522a17 559 $output = &Header::cleanhtml(join("", @output), "y");
92b5fba4 560 print "<pre>$output</pre>\n";
0b1641db 561 } else { print "$Lang::tr{'QoS not enabled'}"; }
92b5fba4
MT
562 &Header::closebox();
563 &Header::closebigbox();
564 &Header::closepage();
565 exit
566}
65e8619a 567elsif ($qossettings{'ACTION'} eq $Lang::tr{'parentclass add'} )
2db5d932
MT
568{
569 &parentclass();
570 &Header::closebigbox();
571 &Header::closepage();
572 exit
573}
65e8619a 574elsif ($qossettings{'ACTION'} eq $Lang::tr{'Add Rule'})
2db5d932 575{
0b1641db 576 &Header::openbox('100%', 'center', $Lang::tr{'Add Rule'});
e8babc92
MT
577 print <<END
578 <table>
0b1641db 579 <tr><td align='center'>$Lang::tr{'Choose Rule'}
e8babc92 580 <tr><td align='center'>
65e8619a
JPT
581 <input type="button" onClick="swapVisibility('l7rule')" value='$Lang::tr{'Level7 Rule'}' />
582 <input type="button" onClick="swapVisibility('portrule')" value='$Lang::tr{'Port Rule'}' />
583 <input type="button" onClick="swapVisibility('tosrule')" value='$Lang::tr{'TOS rule'}' />
e8babc92
MT
584 </table>
585END
586;
587 &Header::closebox();
588 print <<END
589 <div id='l7rule' style='display: none'>
590END
591;
592 &level7rule();
593 print <<END
594 </div>
595 <div id='portrule' style='display: none'>
596END
597;
598 &portrule();
599 print <<END
600 </div>
601 <div id='tosrule' style='display: none'>
602END
603;
604 &tosrule();
605 print <<END
606 </div>
607END
608;
414e011d
MT
609 &Header::closebigbox();
610 &Header::closepage();
611 exit
612}
1dd22be2 613if ($qossettings{'ACTIONBW'} eq "$Lang::tr{'modify'}" )
904a41b9 614{
2db5d932
MT
615 &changebandwidth();
616 &Header::closebigbox();
617 &Header::closepage();
618 exit
619}
1dd22be2 620if ($qossettings{'ACTIONDEF'} eq "$Lang::tr{'modify'}" )
2db5d932
MT
621{
622 &changedefclasses();
904a41b9
MT
623 &Header::closebigbox();
624 &Header::closepage();
625 exit
626}
627
628&General::readhash("${General::swroot}/qos/settings", \%qossettings);
629
630my $status = $Lang::tr{'stopped'};
84cab473 631my $statuscolor = '#993333';
904a41b9
MT
632if ( $qossettings{'ENABLED'} eq 'on' ) {
633 $status = $Lang::tr{'running'};
84cab473 634 $statuscolor = '#339933';
904a41b9
MT
635}
636
637if ( $netsettings{'RED_TYPE'} ne 'PPPOE' ) {
638 $qossettings{'RED_DEV'} = $netsettings{'RED_DEV'};
639}
640
641if ($errormessage) {
642 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
643 print "<class name='base'>$errormessage\n";
644 print "&nbsp;</class>\n";
645 &Header::closebox();
646}
647
414e011d
MT
648############################################################################################################################
649############################################################################################################################
650
5ef70cca 651&Header::openbox('100%', 'center', );
f013ab2b 652
904a41b9 653print <<END
f841744c
CS
654 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
655 <table width='66%'>
414e011d
MT
656END
657;
658 if ( $message ne "" ) {
5ef70cca 659 print "<tr><td colspan='2' align='center'><font color='red'>$message</font></tr>";
414e011d
MT
660 }
661 print <<END
5ef70cca
AM
662 <tr><td width='50%' align='left'><b>Quality of Service:</b></td>
663 <td width='50%' align='center' bgcolor='$statuscolor'><font color='white'>$status</font></td></tr>
664 <tr>
665 <td colspan='2'><br></td>
666 </tr>
667 <tr><td width='100%' align='right' colspan='2'>
668 <input type='submit' name='ACTION' value="$Lang::tr{'start'}">
669 <input type='submit' name='ACTION' value="$Lang::tr{'stop'}">
670 <input type='submit' name='ACTION' value="$Lang::tr{'restart'}" ></td></tr></table></form>
904a41b9
MT
671END
672;
673 if (($qossettings{'OUT_SPD'} ne '') && ($qossettings{'INC_SPD'} ne '')) {
674 print <<END
f841744c
CS
675 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
676 <table width='66%'>
904a41b9 677 <tr><td colspan='3'>&nbsp;
1b73b07e 678 <tr><td width='50%' align='right'>$Lang::tr{'downlink speed'}: <td width='30%' align='left'>$qossettings{'INC_SPD'}
1dd22be2 679 <td width='20%' rowspan='2' align='center' valign='middle'><input type='submit' name='ACTIONBW' value='$Lang::tr{'modify'}' />
1b73b07e 680 <tr><td width='50%' align='right'>$Lang::tr{'uplink speed'}: <td width='30%' align='left'>$qossettings{'OUT_SPD'}
f841744c 681 </table></form>
2db5d932
MT
682END
683;
684 }
0bb882c4 685 if (($qossettings{'DEFCLASS_OUT'} ne '') && ($qossettings{'DEFCLASS_INC'} ne '')) {
2db5d932 686 print <<END
f841744c
CS
687 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
688 <table width='66%'>
f013ab2b 689 <tr><td colspan='3'><hr />
fcd5cb6f 690 <tr><td width='50%' align='right'>$Lang::tr{'downlink std class'}: <td width='30%' align='left'>$qossettings{'DEFCLASS_INC'}
1dd22be2 691 <td width='20%' rowspan='3' align='center' valign='middle'><input type='submit' name='ACTIONDEF' value='$Lang::tr{'modify'}' />
1b73b07e 692 <tr><td width='50%' align='right'>$Lang::tr{'uplink std class'}: <td width='30%' align='left'>$qossettings{'DEFCLASS_OUT'}
f013ab2b 693 <tr><td colspan='3' width='100%'><hr />
7ccede9b 694 <tr><td colspan='3' width='100%' align='center'>
f841744c
CS
695 </table>
696 </form>
697 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
48d9bbba
SS
698 <table width='66%' border='0'>
699 <tr><td width='100%' align='center'>
700 <input type='submit' name='ACTION' value='$Lang::tr{'parentclass add'}' />
701 <input type='submit' name='ACTION' value='$Lang::tr{'status'}' />
702 </td></tr></table>
414e011d 703 </form>
904a41b9
MT
704END
705;
706 }
904a41b9
MT
707&Header::closebox();
708
709if ( ($qossettings{'OUT_SPD'} eq '') || ($qossettings{'INC_SPD'} eq '') ) {
2db5d932 710 &changebandwidth();
2db5d932
MT
711 &Header::closebigbox();
712 &Header::closepage();
713 exit
714}
715
0bb882c4 716if ( ($qossettings{'DEFCLASS_INC'} eq '') || ($qossettings{'DEFCLASS_OUT'} eq '') ) {
2db5d932
MT
717 &changedefclasses();
718 &Header::closebigbox();
719 &Header::closepage();
720 exit
721}
722
4190b2a6
LAH
723&Header::openbox('100%', 'center', "$qossettings{'RED_DEV'} $Lang::tr{'graph'}, $Lang::tr{'uplink'}");
724&Graphs::makegraphbox("qos.cgi",$qossettings{'RED_DEV'},"hour");
725&Header::closebox();
726&Header::openbox('100%', 'center', "$qossettings{'IMQ_DEV'} $Lang::tr{'graph'}, $Lang::tr{'downlink'}");
727&Graphs::makegraphbox("qos.cgi",$qossettings{'IMQ_DEV'},"hour");
728&Header::closebox();
f013ab2b
MT
729
730&showclasses($qossettings{'RED_DEV'});
731&showclasses($qossettings{'IMQ_DEV'});
2db5d932 732
904a41b9
MT
733&Header::closebigbox();
734&Header::closepage();
904a41b9 735
414e011d
MT
736############################################################################################################################
737############################################################################################################################
2db5d932
MT
738
739sub changedefclasses {
0b1641db 740 &Header::openbox('100%', 'center', $Lang::tr{'std classes'});
904a41b9 741 print <<END
2db5d932
MT
742 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
743 <table width='66%'>
0b1641db 744 <tr><td width='100%' colspan='3'>$Lang::tr{'no filter pass'}
597005f5 745 <tr><td width='33%' align='right'>$Lang::tr{'download'}:<td width='33%' align='left'><select name='DEFCLASS_INC'>
2db5d932
MT
746END
747;
414e011d 748 for ( $c = 200 ; $c <= 220 ; $c++ )
2db5d932
MT
749 {
750 if ( $qossettings{'DEFCLASS_INC'} ne $c )
fcd5cb6f 751 { print "<option value='$c'>$c</option>\n"; }
414e011d 752 else { print "<option selected value='$c'>$c</option>\n"; }
2db5d932
MT
753 }
754 print <<END
755 </select><td width='33%' align='center'>&nbsp;
597005f5 756 <tr><td width='33%' align='right'>$Lang::tr{'upload'}:<td width='33%' align='left'><select name='DEFCLASS_OUT'>
2db5d932
MT
757END
758;
414e011d 759 for ( $c = 100 ; $c <= 120 ; $c++ )
2db5d932
MT
760 {
761 if ( $qossettings{'DEFCLASS_OUT'} ne $c )
414e011d
MT
762 { print "<option value='$c'>$c</option>\n"; }
763 else { print "<option selected value='$c'>$c</option>\n"; }
2db5d932
MT
764 }
765 print <<END
f013ab2b 766 </select><td width='33%' align='center'><input type='submit' name='ACTION' value="$Lang::tr{'save'}" />
2db5d932
MT
767 </table>
768 </form>
904a41b9
MT
769END
770;
3a70a538 771 &Header::closebox();
2db5d932
MT
772}
773
774sub changebandwidth {
2f6232d5 775 &Header::openbox('100%', 'center', $Lang::tr{'bandwidthsettings'});
2d42f1df 776
2db5d932 777 if ($qossettings{'ENABLED'} eq 'on') {
2f6232d5 778 print "$Lang::tr{'bandwidtherror'}";
57d4e488 779 print "<table width='100%'><tr><td align='center'><a href='/cgi-bin/qos.cgi'><img src='/images/back.png' alt='$Lang::tr{'back'}' title='$Lang::tr{'back'}' /></a></td></tr></table>";
2db5d932 780 } else {
2d42f1df
MT
781 print <<END;
782 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
783 <input type='hidden' name='DEF_OUT_SPD' value='' /><input type='hidden' name='DEF_INC_SPD' value='' />
784 <table width='66%'>
785 <tr>
ca26f732 786 <td width='100%' colspan='2'>$Lang::tr{'down and up speed'}</td>
2d42f1df
MT
787 </tr>
788 <tr>
789 <td width='50%' align='right'>$Lang::tr{'downlink speed'}:</td>
ca26f732 790 <td width='50%' align='left'>
2d42f1df
MT
791 <input type='text' name='INC_SPD' maxlength='8' value="$qossettings{'INC_SPD'}" />
792 </td>
2d42f1df
MT
793 </tr>
794 <tr>
795 <td width='50%' align='right'>$Lang::tr{'uplink speed'}:</td>
ca26f732 796 <td width='50%' align='left'>
2d42f1df
MT
797 <input type='text' name='OUT_SPD' maxlength='8' value="$qossettings{'OUT_SPD'}" />
798 </td>
799 </tr>
ca26f732
MT
800
801 <tr>
802 <td colspan="2">&nbsp;</td>
803 </tr>
804
805 <tr>
806 <td width='50%' align='right'>$Lang::tr{'link-layer encapsulation'}:</td>
807 <td width='50%' align='left'>
808 <select name="CAKE_PROFILE">
809END
810
811 foreach my $key (sort { $CAKE_PROFILES{$a} cmp $CAKE_PROFILES{$b} } keys %CAKE_PROFILES) {
812 print <<END;
813 <option value="$key" $selected{'CAKE_PROFILE'}{$key}>$CAKE_PROFILES{$key}</option>
814END
815 }
816
817 print <<END;
818 </select>
819 </td>
820 </tr>
821
822 <tr>
823 <td colspan="2">&nbsp;</td>
824 </tr>
825
826 <tr>
827 <td width='100%' align='center' colspan="2">
828 <input type='submit' name='ACTION' value="$Lang::tr{'template'}" />
829 <input type='submit' name='ACTION' value="$Lang::tr{'save'}" />
830 <input type='reset' name='ACTION' value="$Lang::tr{'reset'}" />
831 </td>
832 </tr>
2d42f1df
MT
833 </table>
834 </form>
835 <font color='red'>$Lang::tr{'template warning'}</font>
2db5d932 836END
2db5d932 837 }
2d42f1df 838
904a41b9 839 &Header::closebox();
904a41b9
MT
840}
841
2db5d932 842sub parentclass {
0b1641db 843 &Header::openbox('100%', 'center', $Lang::tr{'parentclass'});
2db5d932
MT
844 print <<END
845 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
846 <table width='66%'>
414e011d
MT
847END
848;
849 if ( $message ne "" ) {
850 print "<tr><td colspan='3' align='center'>$message";
851 }
fcd5cb6f 852 if ( $qossettings{'EDIT'} eq 'yes' ) {
18322edf
CS
853 print "<input type='hidden' name='CLASS' value='$qossettings{'CLASS'}' />";
854 print "<input type='hidden' name='DEVICE' value='$qossettings{'DEVICE'}' />";
414e011d
MT
855 }
856 print <<END
0b1641db
CS
857 <tr><td width='100%' colspan='3'>$Lang::tr{'enter data'}
858 <tr><td width='33%' align='right'>$Lang::tr{'interface'}:
414e011d
MT
859 <td width='33%' align='left'>
860END
861;
fcd5cb6f 862 if ( $qossettings{'EDIT'} eq 'yes' ) {
414e011d
MT
863 print "<select name='DEVICE' disabled>";
864 } else {
865 print "<select name='DEVICE'>";
866 }
867 if ( $qossettings{'DEVICE'} eq $qossettings{'RED_DEV'} ) {
868 $qossettings{'RED_DEV_SEL'} = 'selected';
869 } elsif ( $qossettings{'DEVICE'} eq $qossettings{'IMQ_DEV'} ) {
870 $qossettings{'IMQ_DEV_SEL'} = 'selected';
871 }
872 print <<END
18322edf
CS
873 <option value='$qossettings{'RED_DEV'}' $qossettings{'RED_DEV_SEL'}>$qossettings{'RED_DEV'}</option>
874 <option value='$qossettings{'IMQ_DEV'}' $qossettings{'IMQ_DEV_SEL'}>$qossettings{'IMQ_DEV'}</option></select>
2db5d932 875 <td width='33%' align='center'>&nbsp;
0b1641db 876 <tr><td width='33%' align='right'>$Lang::tr{'Class'}:<td width='33%' align='left'>
2db5d932
MT
877END
878;
fcd5cb6f 879 if ( $qossettings{'EDIT'} eq 'yes' ) {
414e011d
MT
880 print "<select name='CLASS' disabled>";
881 } else {
882 print "<select name='CLASS'>";
883 }
2db5d932
MT
884 for ( $c = 100 ; $c <= 120 ; $c++ )
885 {
886 if ( $qossettings{'CLASS'} ne $c )
414e011d
MT
887 { print "<option value='$c'>$c</option>\n"; }
888 else { print "<option selected value='$c'>$c</option>\n"; }
2db5d932
MT
889 }
890 for ( $c = 200 ; $c <= 220 ; $c++ )
891 {
892 if ( $qossettings{'CLASS'} ne $c )
414e011d
MT
893 { print "<option value='$c'>$c</option>\n"; }
894 else { print "<option selected value='$c'>$c</option>\n"; }
2db5d932
MT
895 }
896 print <<END
897 </select>
898 <td width='33%' align='center'>&nbsp;
0b1641db 899 <tr><td width='33%' align='right'>$Lang::tr{'priority'}:<td width='33%' align='left'><select name='PRIO'>
2db5d932
MT
900END
901;
902 for ( $c = 1 ; $c <= 7 ; $c++ )
903 {
904 if ( $qossettings{'PRIO'} ne $c )
414e011d
MT
905 { print "<option value='$c'>$c</option>\n"; }
906 else { print "<option selected value='$c'>$c</option>\n"; }
2db5d932 907 }
f013ab2b 908 if ($qossettings{'MINBWDTH'} eq "") { $qossettings{'MINBWDTH'} = "1"; }
2db5d932 909 print <<END
f013ab2b 910 </select>
2db5d932 911 <td width='33%' align='center'>&nbsp;
2f6232d5 912 <tr><td width='33%' align='right'>$Lang::tr{'guaranteed bandwidth'}:
f013ab2b 913 <td width='33%' align='left'><input type='text' size='20' name='MINBWDTH' maxlength='8' required='1' value="$qossettings{'MINBWDTH'}" />
2db5d932 914 <td width='33%' align='center'>&nbsp;
2f6232d5 915 <tr><td width='33%' align='right'>$Lang::tr{'max bandwidth'}&nbsp;<img src='/blob.gif' alt='*' />:
f013ab2b 916 <td width='33%' align='left'><input type='text' size='20' name='MAXBWDTH' maxlength='8' required='1' value="$qossettings{'MAXBWDTH'}" />
2db5d932
MT
917 <td width='33%' align='center'>&nbsp;
918 <tr><td width='33%' align='right'>Burst:
f013ab2b 919 <td width='33%' align='left'><input type='text' size='20' name='BURST' maxlength='8' value="$qossettings{'BURST'}" />
2db5d932
MT
920 <td width='33%' align='center'>&nbsp;
921 <tr><td width='33%' align='right'>Ceilburst:
f013ab2b 922 <td width='33%' align='left'><input type='text' size='20' name='CBURST' maxlength='8' value="$qossettings{'CBURST'}" />
e8babc92 923 <td width='33%' align='center'>&nbsp;
f013ab2b 924 <tr><td width='33%' align='right'>$Lang::tr{'remark'}:
e3edceeb
LS
925 <td width='66%' colspan='2' align='left'><input type='text' name='REMARK' size='40' maxlength='40' value="$qossettings{'REMARK'}" />
926 <tr><td width='33%' align='right'><img src='/blob.gif' alt='*' />&nbsp;$Lang::tr{'required field'}
f013ab2b 927 <td width='33%' align='left'>&nbsp;
18322edf 928 <td width='33%' align='center'><input type='submit' name='DOCLASS' value='$Lang::tr{'save'}' />&nbsp;<input type='reset' value='$Lang::tr{'reset'}' />
2db5d932
MT
929 </table></form>
930END
931;
932 &Header::closebox();
933}
904a41b9 934
414e011d 935sub level7rule {
0b1641db 936 &Header::openbox('100%', 'center', $Lang::tr{'Level7 Rule'});
414e011d
MT
937 print <<END
938 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
939 <table width='66%'>
940END
941;
942 if ( $message ne "" ) {
943 print "<tr><td colspan='3' align='center'><font color='red'>$message</font>";
944 }
945 print <<END
0b1641db
CS
946 <tr><td colspan='3' width='100%'>$Lang::tr{'current class'}: $qossettings{'CLASS'}
947 <tr><td width='100%' colspan='3'>$Lang::tr{'enter data'}
948 <tr><td width='33%' align='right'>$Lang::tr{'protocol'}:
2db5d932
MT
949 <td width='33%' align='left'><select name='L7PROT'>
950END
951;
952 opendir( DIR, "/etc/l7-protocols/protocols" );
953 foreach $direntry ( sort readdir(DIR) )
954 {
955 next if $direntry eq ".";
956 next if $direntry eq "..";
957 next if -d "/etc/l7-protocols/protocols/$direntry";
958 @proto = split( /\./, $direntry );
959 if ( $proto[0] eq $qossettings{'L7PROT'} ) {
fcd5cb6f 960 print "<option value='$proto[0]' selected>$proto[0]</option>\n";
2db5d932
MT
961 } else {
962 print "<option value='$proto[0]'>$proto[0]</option>\n";
963 }
964 }
965 closedir DIR;
966 print <<END
967 </select><td width='33%' align='center'>&nbsp;
0b1641db 968 <tr><td width='33%' align='right'>$Lang::tr{'source ip'}:
5eee5a60 969 <td width='33%' align='left'><input type='text' name='QIP' maxlength='31' value='$qossettings{'QIP'}' />
2db5d932 970 <td width='33%' align='center'>&nbsp;
0b1641db 971 <tr><td width='33%' align='right'>$Lang::tr{'destination ip'}:
5eee5a60 972 <td width='33%' align='left'><input type='text' name='DIP' maxlength='31' value='$qossettings{'DIP'}' />
18322edf 973 <td width='33%' align='center'><input type='hidden' name='CLASS' value='$qossettings{'CLASS'}' /><input type='submit' name='DOLEVEL7' value='$Lang::tr{'save'}' />
11bccc3f 974 <tr><td colspan="3" align='center'><font color="red"><em>$Lang::tr{'qos warning'}</em></font>
2db5d932
MT
975 </table></form>
976END
977;
978 &Header::closebox();
414e011d
MT
979}
980
981sub portrule {
0b1641db 982 &Header::openbox('100%', 'center', $Lang::tr{'Add Port Rule'});
414e011d
MT
983 print <<END
984 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
985 <table width='66%'>
0b1641db
CS
986 <tr><td width='100%' colspan='3'>$Lang::tr{'enter data'}
987 <tr><td width='33%' align='right'>$Lang::tr{'protocol'}:
414e011d
MT
988 <td width='33%' align='left'><select name='PPROT'>
989END
990;
991 open( FILE, "< /etc/protocols" );
992 @proto = <FILE>;
993 close FILE;
994 foreach $direntry (sort @proto)
995 {
996 @tmpline = split( /\ /, $direntry );
997 next if $tmpline[0] =~ "#";
998 if ( $tmpline[0] eq $qossettings{'PPROT'} ) {
fcd5cb6f 999 print "<option value='$tmpline[0]' selected>$tmpline[0]</option>\n";
414e011d
MT
1000 } else {
1001 print "<option value='$tmpline[0]'>$tmpline[0]</option>\n";
1002 }
1003 }
1004 print <<END
1005 </select><td width='33%' align='center'>&nbsp;
0b1641db 1006 <tr><td width='33%' align='right'>$Lang::tr{'source port'}:
ec3573fc 1007 <td width='33%' align='left'><input type='text' name='QPORT' maxlength='11' value='$qossettings{'QPORT'}' />
414e011d 1008 <td width='33%' align='center'>&nbsp;
0b1641db 1009 <tr><td width='33%' align='right'>$Lang::tr{'destination port'}:
ec3573fc 1010 <td width='33%' align='left'><input type='text' name='DPORT' maxlength='11' value='$qossettings{'DPORT'}' />
414e011d 1011 <td width='33%' align='center'>&nbsp;
0b1641db 1012 <tr><td width='33%' align='right'>$Lang::tr{'source ip'}:
5eee5a60 1013 <td width='33%' align='left'><input type='text' name='QIP' maxlength='31' value='$qossettings{'QIP'}' />
414e011d 1014 <td width='33%' align='center'>&nbsp;
0b1641db 1015 <tr><td width='33%' align='right'>$Lang::tr{'destination ip'}:
5eee5a60 1016 <td width='33%' align='left'><input type='text' name='DIP' maxlength='31' value='$qossettings{'DIP'}' />
18322edf 1017 <td width='33%' align='center'><input type='hidden' name='CLASS' value='$qossettings{'CLASS'}' /><input type='submit' name='DOPORT' value='$Lang::tr{'save'}' />
414e011d
MT
1018 </table></form>
1019END
1020;
1021 &Header::closebox();
1022}
1023
e8babc92 1024sub tosrule {
0b1641db 1025 &Header::openbox('100%', 'center', $Lang::tr{'TOS Rule'});
e8babc92 1026 if ($qossettings{'TOS'}) {
0b1641db 1027 $checked{$qossettings{'TOS'}} = "checked";
e8babc92
MT
1028 }
1029 print <<END
1030 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
1031 <table width='66%'>
1032END
1033;
1034 if ( $message ne "" ) {
1035 print "<tr><td colspan='3' align='center'><font color='red'>$message</font>";
1036 }
1037 print <<END
0b1641db
CS
1038 <tr><td colspan='2' width='100%'>$Lang::tr{'current class'}: $qossettings{'CLASS'}
1039 <tr><td width='100%' colspan='2'>$Lang::tr{'Enter TOS'}
1040 <tr><td width='50%' align='left'>$Lang::tr{'min delay'} (8) <td width='50%'><input type="radio" name="TOS" value="8" $checked[8] />
1041 <tr><td width='50%' align='left'>$Lang::tr{'max throughput'} (4) <td width='50%'><input type="radio" name="TOS" value="4" $checked[4] />
1042 <tr><td width='50%' align='left'>$Lang::tr{'max reliability'} (2) <td width='50%'><input type="radio" name="TOS" value="2" $checked[2] />
da7e2665 1043 <tr><td width='50%' align='left'>$Lang::tr{'min costs'} (1) <td width='50%'><input type="radio" name="TOS" value="1" $checked[1] />
18322edf 1044 <tr><td width='100%' align='right' colspan='2'><input type='hidden' name='CLASS' value='$qossettings{'CLASS'}' /><input type='submit' name='DOTOS' value='$Lang::tr{'save'}' />
e8babc92
MT
1045 </table></form>
1046END
1047;
1048 &Header::closebox();
1049}
1050
414e011d 1051sub showclasses {
f013ab2b 1052 $qossettings{'DEV'} = shift;
414e011d
MT
1053 open( FILE, "< $classfile" ) or die "Unable to read $classfile";
1054 @classes = <FILE>;
1055 close FILE;
1056 if (@classes) {
f013ab2b
MT
1057 open( FILE, "< $level7file" ) or die "Unable to read $level7file";
1058 @l7rules = <FILE>;
1059 close FILE;
1060 open( FILE, "< $tosfile" ) or die "Unable to read $tosfile";
1061 @tosrules = <FILE>;
1062 close FILE;
1063 open( FILE, "< $portfile" ) or die "Unable to read $portfile";
1064 @portrules = <FILE>;
1065 close FILE;
414e011d
MT
1066 foreach $classentry (sort @classes)
1067 {
1068 @classline = split( /\;/, $classentry );
f013ab2b 1069 if ( $classline[0] eq $qossettings{'DEV'} )
414e011d 1070 {
be7534e3 1071 &Header::openbox('100%', 'center', "$Lang::tr{'Class'}: $classline[1] $classline[8]");
414e011d 1072 print <<END
f013ab2b 1073 <table border='0' width='100%' cellspacing='0'>
f2fdd0c1 1074 <tr><td bgcolor='$color{'color20'}' width='10%' align='center'><b>$Lang::tr{'interface'}</b>
0b1641db
CS
1075 <td bgcolor='$color{'color20'}' width='10%' align='center'><b>$Lang::tr{'Class'}</b>
1076 <td bgcolor='$color{'color20'}' width='10%' align='center'>$Lang::tr{'priority'}
2f6232d5
MF
1077 <td bgcolor='$color{'color20'}' width='10%' align='center'>$Lang::tr{'guaranteed bandwidth'}
1078 <td bgcolor='$color{'color20'}' width='10%' align='center'>$Lang::tr{'max bandwidth'}
f2fdd0c1
CS
1079 <td bgcolor='$color{'color20'}' width='10%' align='center'>Burst
1080 <td bgcolor='$color{'color20'}' width='10%' align='center'>Ceil Burst
1081 <td bgcolor='$color{'color20'}' width='10%' align='center'>TOS
0b1641db 1082 <td bgcolor='$color{'color20'}' width='20%' align='center'>$Lang::tr{'action'}
f2fdd0c1
CS
1083 <tr><td align='center' bgcolor='$color{'color22'}'>$classline[0]</td>
1084 <td align='center' bgcolor='$color{'color22'}'>$classline[1]</td>
1085 <td align='center' bgcolor='$color{'color22'}'>$classline[2]</td>
1086 <td align='center' bgcolor='$color{'color22'}'>$classline[3]</td>
1087 <td align='center' bgcolor='$color{'color22'}'>$classline[4]</td>
1088 <td align='center' bgcolor='$color{'color22'}'>$classline[5]</td>
1089 <td align='center' bgcolor='$color{'color22'}'>$classline[6]</td>
1090 <td align='center' bgcolor='$color{'color22'}'>$classline[7]</td>
1091 <td align='right' bgcolor='$color{'color22'}'>
649fd295 1092 <table border='0'><tr>
649fd295 1093 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f841744c 1094 <input type='hidden' name='CLASS' value='$classline[1]' />
65e8619a 1095 <input type='hidden' name='ACTION' value='$Lang::tr{'Add Rule'}' />
f8aa0679 1096 <input type='image' alt='$Lang::tr{'Add Rule'}' title='$Lang::tr{'Add Rule'}' src='/images/addgreen.gif' />
649fd295
MT
1097 </form>
1098 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f841744c 1099 <input type='hidden' name='CLASS' value='$classline[1]' />
65e8619a 1100 <input type='hidden' name='DOCLASS' value='$Lang::tr{'edit'}' />
f8aa0679 1101 <input type='image' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' src='/images/edit.gif' />
649fd295
MT
1102 </form>
1103 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f841744c 1104 <input type='hidden' name='CLASS' value='$classline[1]' />
65e8619a 1105 <input type='hidden' name='DOCLASS' value='$Lang::tr{'delete'}' />
f8aa0679 1106 <input type='image' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' src='/images/delete.gif' />
649fd295
MT
1107 </form>
1108 </table>
f013ab2b
MT
1109 </td>
1110 <tr><td align='right' colspan='2'><b>$Lang::tr{'remark'}:</b>
1111 <td align='center' colspan='6'> $classline[8]
1112 <td align='right'><b>Queueing:</b> $classline[9]
414e011d
MT
1113END
1114;
f013ab2b
MT
1115
1116 if (@l7rules) {
1117 foreach $l7ruleentry (sort @l7rules)
1118 {
1119 @l7ruleline = split( /\;/, $l7ruleentry );
1120 if ( $l7ruleline[0] eq $classline[1] )
1121 {
1122 print <<END
0b1641db 1123 <tr><td align='right' colspan='2'><b>$Lang::tr{'Level7 Protocol'}:</b>
f013ab2b
MT
1124 <td align='center' colspan='6'>$l7ruleline[2]
1125 <td align='right' >
649fd295 1126 <table border='0'><tr>
649fd295 1127 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f013ab2b
MT
1128 <input type='hidden' name='CLASS' value='$l7ruleline[0]' />
1129 <input type='hidden' name='L7PROT' value='$l7ruleline[2]' />
65e8619a 1130 <input type='hidden' name='DOLEVEL7' value='$Lang::tr{'edit'}' />
f8aa0679 1131 <input type='image' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' src='/images/edit.gif' />
649fd295
MT
1132 </form>
1133 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f013ab2b
MT
1134 <input type='hidden' name='CLASS' value='$l7ruleline[0]' />
1135 <input type='hidden' name='L7PROT' value='$l7ruleline[2]' />
65e8619a 1136 <input type='hidden' name='DOLEVEL7' value='$Lang::tr{'delete'}' />
f8aa0679 1137 <input type='image' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' src='/images/delete.gif' />
649fd295
MT
1138 </form>
1139 </table>
414e011d
MT
1140END
1141;
f013ab2b
MT
1142 if (($l7ruleline[3] ne "") || ($l7ruleline[4] ne "")){
1143 print <<END
1144 <tr><td align='center'>&nbsp;
0b1641db
CS
1145 <td align='right' colspan='3'><b>$Lang::tr{'source ip'}:</b> $l7ruleline[3]
1146 <td align='right' colspan='3'><b>$Lang::tr{'destination ip'}:</b> $l7ruleline[4]
84cab473
MT
1147END
1148;
f013ab2b
MT
1149 }
1150
414e011d 1151
84cab473
MT
1152END
1153;
f013ab2b
MT
1154 }
1155 }
1156 }
1157
1158
1159 if (@portrules) {
1160 foreach $portruleentry (sort @portrules)
1161 {
1162 @portruleline = split( /\;/, $portruleentry );
1163 if ( $portruleline[0] eq $classline[1] )
1164 {
1165 print <<END
0b1641db 1166 <tr><td align='right' colspan='2'><b>$Lang::tr{'Port Rule'}:</b>
f013ab2b
MT
1167 <td align='center'>($portruleline[2])
1168 <td align='center' colspan='2'>
84cab473
MT
1169END
1170;
f013ab2b
MT
1171 if ($portruleline[4]) {
1172 print <<END
99a6f5f9 1173 <i>$Lang::tr{'source port'}:</i> $portruleline[4]
84cab473
MT
1174END
1175;
f013ab2b
MT
1176 }
1177 print "<td align='center' colspan='2'>";
1178 if ($portruleline[6]) {
1179 print <<END
99a6f5f9 1180 <i>$Lang::tr{'destination port'}:</i> $portruleline[6]
84cab473
MT
1181END
1182;
f013ab2b
MT
1183 }
1184 print <<END
1185 <td>&nbsp;
1186 <td align='right'>
8b0883b8
MT
1187 <table border='0'><tr>
1188 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f841744c
CS
1189 <input type='hidden' name='CLASS' value='$portruleline[0]' />
1190 <input type='hidden' name='PPROT' value='$portruleline[2]' />
1191 <input type='hidden' name='QIP' value='$portruleline[3]' />
1192 <input type='hidden' name='QPORT' value='$portruleline[4]' />
1193 <input type='hidden' name='DIP' value='$portruleline[5]' />
1194 <input type='hidden' name='DPORT' value='$portruleline[6]' />
65e8619a 1195 <input type='hidden' name='DOPORT' value='$Lang::tr{'edit'}' />
f8aa0679 1196 <input type='image' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' src='/images/edit.gif' />
8b0883b8
MT
1197 </form>
1198 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f841744c
CS
1199 <input type='hidden' name='CLASS' value='$portruleline[0]' />
1200 <input type='hidden' name='PPROT' value='$portruleline[2]' />
1201 <input type='hidden' name='QIP' value='$portruleline[3]' />
1202 <input type='hidden' name='QPORT' value='$portruleline[4]' />
1203 <input type='hidden' name='DIP' value='$portruleline[5]' />
1204 <input type='hidden' name='DPORT' value='$portruleline[6]' />
65e8619a 1205 <input type='hidden' name='DOPORT' value='$Lang::tr{'delete'}' />
f8aa0679 1206 <input type='image' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' src='/images/delete.gif' />
8b0883b8
MT
1207 </form>
1208 </table>
414e011d
MT
1209END
1210;
f013ab2b
MT
1211 if (($portruleline[3] ne "") || ($portruleline[5] ne "")){
1212 print <<END
1213 <tr><td align='center'>&nbsp;
0b1641db
CS
1214 <td align='right' colspan='3'><b>$Lang::tr{'source ip'}:</b> $portruleline[3]
1215 <td align='right' colspan='3'><b>$Lang::tr{'destination ip'}:</b> $portruleline[5]
84cab473
MT
1216END
1217;
f013ab2b
MT
1218 }
1219 }
1220 }
1221 }
414e011d 1222
f013ab2b
MT
1223 if (@tosrules) {
1224 foreach $tosruleentry (sort @tosrules)
1225 {
1226 @tosruleline = split( /\;/, $tosruleentry );
1227 if ( $tosruleline[0] eq $classline[1] )
1228 {
1229 print <<END
1230 <tr><td align='right' colspan='2'>
1231 <b>TOS Bit matches:</b>
1232 <td colspan='6' align='center'>
e8babc92
MT
1233END
1234;
f013ab2b 1235 if ( $tosruleline[2] eq "8") {
0b1641db 1236 print "$Lang::tr{'min delay'}\n";
f013ab2b 1237 } elsif ( $tosruleline[2] eq "4") {
0b1641db 1238 print "$Lang::tr{'max throughput'}\n";
f013ab2b 1239 } elsif ( $tosruleline[2] eq "2") {
0b1641db 1240 print "$Lang::tr{'max reliability'}\n";
f013ab2b 1241 } elsif ( $tosruleline[2] eq "1") {
0b1641db 1242 print "$Lang::tr{'min costs'}\n";
f013ab2b
MT
1243 } else { print "&nbsp;\n"; }
1244
1245 print <<END
1246 ($tosruleline[2])
1247 <td align='right'>
1248 <table border='0'><tr>
1249 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f841744c
CS
1250 <input type='hidden' name='CLASS' value='$tosruleline[0]' />
1251 <input type='hidden' name='DEV' value='$tosruleline[1]' />
1252 <input type='hidden' name='TOS' value='$tosruleline[2]' />
65e8619a 1253 <input type='hidden' name='DOTOS' value='$Lang::tr{'edit'}' />
f8aa0679 1254 <input type='image' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' src='/images/edit.gif' />
f013ab2b
MT
1255 </form>
1256 <td><form method='post' action='$ENV{'SCRIPT_NAME'}'>
f841744c
CS
1257 <input type='hidden' name='CLASS' value='$tosruleline[0]' />
1258 <input type='hidden' name='DEV' value='$tosruleline[1]' />
1259 <input type='hidden' name='TOS' value='$tosruleline[2]' />
65e8619a 1260 <input type='hidden' name='DOTOS' value='$Lang::tr{'delete'}' />
f8aa0679 1261 <input type='image' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' src='/images/delete.gif' />
f013ab2b
MT
1262 </form>
1263 </table>
e8babc92
MT
1264END
1265;
f013ab2b
MT
1266 }
1267 }
1268 }
e8babc92
MT
1269END
1270;
f013ab2b
MT
1271 print <<END
1272 </table>
e8babc92
MT
1273END
1274;
18322edf 1275 &Header::closebox();
e8babc92 1276 }
18322edf
CS
1277 }
1278 }
e8babc92 1279 }
414e011d
MT
1280sub validminbwdth {
1281 if ( $qossettings{'VALID'} eq 'yes' ) {
1282 if ( $qossettings{'DEVICE'} eq $qossettings{'RED_DEV'} ) {
1283 $qossettings{'SPD'} = $qossettings{'OUT_SPD'};
1284 } elsif ( $qossettings{'DEVICE'} eq $qossettings{'IMQ_DEV'} ) {
1285 $qossettings{'SPD'} = $qossettings{'INC_SPD'};
1286 }
363fb6af 1287 unless ( ( $qossettings{'MINBWDTH'} >= 1 ) && ( $qossettings{'MINBWDTH'} <= $qossettings{'SPD'} ) ) {
414e011d 1288 $qossettings{'VALID'} = 'no';
2f6232d5 1289 $message = "$Lang::tr{'false min bandwidth'}";
414e011d
MT
1290 }
1291 $qossettings{'SPD'} = '';
1292 }
1293}
84cab473 1294
414e011d
MT
1295sub validmaxbwdth {
1296 if ( $qossettings{'VALID'} eq 'yes' ) {
1297 if ( $qossettings{'DEVICE'} eq $qossettings{'RED_DEV'} ) {
1298 $qossettings{'SPD'} = $qossettings{'OUT_SPD'};
1299 } elsif ( $qossettings{'DEVICE'} eq $qossettings{'IMQ_DEV'} ) {
1300 $qossettings{'SPD'} = $qossettings{'INC_SPD'};
1301 }
1302 unless ( ( $qossettings{'MAXBDWTH'} >= 0 ) && ($qossettings{'MAXBDWTH'} >= $qossettings{'MINBDWTH'}) &&( $qossettings{'MAXBDWTH'} <= $qossettings{'SPD'} ) ) {
1303 $qossettings{'VALID'} = 'no';
2f6232d5 1304 $message = "$Lang::tr{'false max bandwidth'}";
414e011d
MT
1305 }
1306 $qossettings{'SPD'} = '';
1307 }
1308}
1309
1310sub validclass {
1311 if ( $qossettings{'VALID'} eq 'yes' ) {
1312 if ( $qossettings{'DEVICE'} eq $qossettings{'RED_DEV'} ) {
1313 if ($qossettings{'CLASS'} lt 100 || $qossettings{'CLASS'} ge 121) {
1314 $qossettings{'VALID'} = 'no';
0b1641db 1315 $message = "$Lang::tr{'false classnumber'}";
414e011d
MT
1316 }
1317 } elsif ( $qossettings{'DEVICE'} eq $qossettings{'IMQ_DEV'} ) {
1318 if ($qossettings{'CLASS'} lt 200 || $qossettings{'CLASS'} ge 221) {
1319 $qossettings{'VALID'} = 'no';
65e8619a 1320 $message = "$Lang::tr{'The class number does not match the specified interface.'}";
414e011d
MT
1321 }
1322 }
1323 open( FILE, "< $classfile" ) or die "Unable to read $classfile";
1324 @tmp = <FILE>;
1325 close FILE;
1326 foreach $classentry (sort @tmp)
1327 {
1328 @tmpline = split( /\;/, $classentry );
1329 if ( $tmpline[1] eq $qossettings{'CLASS'} )
1330 {
1331 $qossettings{'VALID'} = 'no';
0b1641db 1332 $message = "$Lang::tr{'false classnumber'}";
414e011d
MT
1333 last
1334 }
1335 }
1336 }
1337}