1 <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML
4.0//EN'
>
4 Copyright (C) 2006-2010 Jonathan Zarate
5 http://www.polarcloud.com/tomato/
7 For use with Tomato Firmware only.
8 No part of this file may be used without permission.
12 <meta http-equiv='content-type' content='text/html;charset=utf-
8'
>
13 <meta name='robots' content='noindex,nofollow'
>
14 <title>[<%
ident(); %>] QoS: Classification
</title>
15 <link rel='stylesheet' type='text/css' href='tomato.css'
>
16 <link rel='stylesheet' type='text/css' href='color.css'
>
17 <script type='text/javascript' src='tomato.js'
></script>
18 <script type='text/javascript' src='protocols.js'
></script>
22 <style type='text/css'
>
78 padding: 2px 8px 0 8px;
94 <script type='text/javascript' src='debug.js'
></script>
96 <script type='text/javascript'
>
98 // <% nvram("qos_enable,qos_orules"); %>
100 var abc
= ['Highest', 'High', 'Medium', 'Low', 'Lowest', 'A','B','C','D','E'];
103 [0,'IPP2P (disabled)'],[0xFFF,'All IPP2P filters'],[1,'AppleJuice'],[2,'Ares'],[4,'BitTorrent'],[8,'Direct Connect'],
104 [16,'eDonkey'],[32,'Gnutella'],[64,'Kazaa'],[128,'Mute'],[256,'SoulSeek'],[512,'Waste'],[1024,'WinMX'],[2048,'XDCC']]
108 for (i
= 0; i
< layer7
.length
; ++i
)
109 layer7
[i
] = [layer7
[i
],layer7
[i
]];
110 layer7
.unshift(['', 'Layer 7 (disabled)']);
112 var class1
= [[-1,'Disabled']];
113 for (i
= 0; i
< 10; ++i
) class1
.push([i
, abc
[i
]]);
114 var class2
= class1
.slice(1);
116 var qosg
= new TomatoGrid();
118 qosg
.dataToView = function(data
) {
123 b
.push(((data
[0] == 1) ? 'To ' : 'From ') + data
[1]);
126 if (data
[2] == -1) b
.push('TCP/UDP');
127 else if (data
[2] >= 0) b
.push(protocols
[data
[2]] || data
[2]);
128 if (data
[3] != 'a') {
129 if (data
[3] == 'd') s
= 'Dst ';
130 else if (data
[3] == 's') s
= 'Src ';
132 b
.push(s
+ 'Port: ' + data
[4].replace(/:/g
, '-'));
136 for (i
= 0; i
< ipp2p
.length
; ++i
)
137 if (ipp2p
[i
][0] == data
[5]) {
138 b
.push('IPP2P: ' + ipp2p
[i
][1])
143 else if (data
[6] != '') {
144 b
.push('L7: ' + data
[6])
148 b
.push('Transferred: ' + data
[7] + ((data
[8] == '') ? '<small>KB+</small>' : (' - ' + data
[8] + '<small>KB</small>')));
150 return [b
.join('<br>'), class1
[(data
[9] * 1) + 1][1], escapeHTML(data
[10])];
153 qosg
.fieldValuesToData = function(row
) {
154 var f
= fields
.getAll(row
);
155 var proto
= f
[2].value
;
156 var dir
= f
[3].value
;
157 if ((proto
!= -1) && (proto
!= 6) && (proto
!= 17)) dir
= 'a';
158 return [f
[0].value
, f
[0].selectedIndex
? f
[1].value
: '',
159 proto
, dir
, (dir
!= 'a') ? f
[4].value
: '',
160 f
[5].value
, f
[6].value
, f
[7].value
, f
[8].value
, f
[9].value
, f
[10].value
];
163 qosg
.resetNewEditor = function() {
164 var f
= fields
.getAll(this.newEditor
);
165 f
[0].selectedIndex
= 0;
167 f
[2].selectedIndex
= 1;
168 f
[3].selectedIndex
= 0;
170 f
[5].selectedIndex
= 0;
171 f
[6].selectedIndex
= 0;
174 f
[9].selectedIndex
= 5;
176 this.enDiFields(this.newEditor
);
177 ferror
.clearAll(fields
.getAll(this.newEditor
));
180 qosg
._disableNewEditor
= qosg
.disableNewEditor
;
181 qosg
.disableNewEditor = function(disable
) {
182 qosg
._disableNewEditor(disable
);
184 this.enDiFields(this.newEditor
);
188 qosg
.enDiFields = function(row
) {
189 var f
= fields
.getAll(row
);
192 f
[1].disabled
= (f
[0].selectedIndex
== 0);
194 x
= ((x
!= -1) && (x
!= 6) && (x
!= 17));
196 if (f
[3].selectedIndex
== 0) x
= 1;
199 f
[6].disabled
= (f
[5].selectedIndex
!= 0);
200 f
[5].disabled
= (f
[6].selectedIndex
!= 0);
203 qosg
.verifyFields = function(row
, quiet
) {
204 var f
= fields
.getAll(row
);
207 this.enDiFields(row
);
211 if ((a
== 1) || (a
== 2)) {
212 if (!v_iptip(f
[1], quiet
)) return 0;
214 else if ((a
== 3) && (!v_mac(f
[1], quiet
))) return 0;
216 b
= f
[2].selectedIndex
;
217 if ((b
> 0) && (b
<= 3) && (f
[3].selectedIndex
!= 0) && (!v_iptport(f
[4], quiet
))) return 0;
219 var BMAX
= 1024 * 1024;
222 a
= e
.value
= e
.value
.trim();
224 if (!v_range(e
, quiet
, 0, BMAX
)) return 0;
229 b
= e
.value
= e
.value
.trim();
232 if (b
>= BMAX
) e
.value
= '';
233 else if (!v_range(e
, quiet
, 0, BMAX
)) return 0;
234 if (a
== '') f
[7].value
= a
= 0;
240 if ((b
!= '') && (a
>= b
)) {
241 ferror
.set(f
[7], 'Invalid range', quiet
);
245 return v_length(f
[10], quiet
);
248 qosg
.setup = function() {
250 a
= [[-2, 'Any Protocol'],[-1,'TCP/UDP'],[6,'TCP'],[17,'UDP']];
251 for (i
= 0; i
< 256; ++i
) {
252 if ((i
!= 6) && (i
!= 17)) a
.push([i
, protocols
[i
] || i
]);
256 this.init('qg', 'move', 50, [
258 { type
: 'select', options
: [[0,'Any Address'],[1,'Dst IP'],[2,'Src IP'],[3,'Src MAC']],
259 prefix
: '<div class="x1a">', suffix
: '</div>' },
260 { type
: 'text', prefix
: '<div class="x1b">', suffix
: '</div>' },
261 { type
: 'select', prefix
: '<div class="x2a">', suffix
: '</div>', options
: a
},
262 { type
: 'select', prefix
: '<div class="x2b">', suffix
: '</div>',
263 options
: [['a','Any Port'],['d','Dst Port'],['s','Src Port'],['x','Src or Dst']] },
264 { type
: 'text', prefix
: '<div class="x2c">', suffix
: '</div>' },
265 { type
: 'select', prefix
: '<div class="x3a">', suffix
: '</div>', options
: ipp2p
},
266 { type
: 'select', prefix
: '<div class="x3b">', suffix
: '</div>', options
: layer7
},
268 { type
: 'text', prefix
: '<div class="x4a">', suffix
: '</div>' },
269 { type
: 'text', prefix
: '<div class="x4b"> - </div><div class="x4c">', suffix
: '</div><div class="x4d">KB Transferred</div>' }
272 { type
: 'select', options
: class1
, vtop
: 1 },
273 { type
: 'text', maxlen
: 32, vtop
: 1 }
276 this.headerSet(['Match Rule', 'Class', 'Description']);
278 // addr_type < addr < proto < port_type < port < ipp2p < L7 < bcount < class < desc
280 a
= nvram
.qos_orules
.split('>');
281 for (i
= 0; i
< a
.length
; ++i
) {
284 // fixup < 0.08 !!! temp
285 b
.splice(7, 0, '', '');
287 else if (b
.length
== 10) {
289 b
.splice(7, 1, c
[0], (c
.length
== 1) ? '' : c
[1]);
290 b
[10] = unescape(b
[10]);
293 b
[4] = b
[4].replace(/:/g
, '-');
294 qosg
.insertData(-1, b
);
297 this.showNewEditor();
298 this.resetNewEditor();
301 function verifyFields(focused
, quiet
)
308 if (qosg
.isEditing()) return;
313 c
= qosg
.getAllData();
315 for (i
= 0; i
< c
.length
; ++i
) {
317 b
[4] = b
[4].replace(/-/g
, ':');
318 b
.splice(7, 2, (b
[7] == '') ? '' : [b
[7],b
[8]].join(':'));
319 b
[9] = escapeD(b
[9]);
322 fom
.qos_orules
.value
= a
.join('>');
334 <body onload='init()'
>
335 <form id='_fom' method='post' action='tomato.cgi'
>
336 <table id='container' cellspacing=
0>
337 <tr><td colspan=
2 id='header'
>
338 <div class='title'
>Tomato
</div>
339 <div class='version'
>Version <%
version(); %></div>
341 <tr id='body'
><td id='navi'
><script type='text/javascript'
>navi()</script></td>
343 <div id='ident'
><%
ident(); %></div>
347 <input type='hidden' name='_nextpage' value='qos-classify.asp'
>
348 <input type='hidden' name='_service' value='qos-restart'
>
349 <input type='hidden' name='qos_orules'
>
351 <div class='section-title'
>Outbound Direction
</div>
352 <div class='section'
>
353 <table class='tomato-grid' cellspacing=
1 id='qg'
></table>
356 <script type='text/javascript'
>
357 if (nvram
.qos_enable
!= '1') {
358 W('<div class="note-disabled"><b>QoS disabled.</b> <a href="qos-settings.asp">Enable »</a></div>');
365 <tr><td id='footer' colspan=
2>
366 <span id='footer-msg'
></span>
367 <input type='button' value='Save' id='save-button' onclick='save()'
>
368 <input type='button' value='Cancel' id='cancel-button' onclick='reloadPage();'
>
372 <script type='text/javascript'
>qosg
.setup();</script>