Tomato 1.28
[tomato/tomato-null.git] / release / src / router / www / qos-classify.asp
blob6a07912e32da16a81deeaf5ea2102ddc1ea43edd
1 <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN'>
2 <!--
3 Tomato GUI
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.
9 -->
10 <html>
11 <head>
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>
20 <!-- / / / -->
22 <style type='text/css'>
23 #qg div {
24 padding: 0 0 1px 0;
25 margin: 0;
28 #qg .co1 {
29 width: 370px;
31 #qg .co2 {
32 width: 80px;
34 #qg .co3 {
35 width: 300px;
38 #qg .x1a {
39 width: 35%;
40 float: left;
42 #qg .x1b {
43 width: 64%;
44 float: left;
47 #qg .x2a {
48 width: 35%;
49 float: left;
50 clear: left;
52 #qg .x2b {
53 width: 23%;
54 float: left;
56 #qg .x2c {
57 width: 41%;
58 float: left;
61 #qg .x3a {
62 width: 40%;
63 float: left;
64 clear: left;
66 #qg .x3b {
67 width: 60%;
68 float: left;
71 #qg .x4a {
72 float: left;
73 clear: left;
74 width: 70px;
76 #qg .x4b {
77 float: left;
78 padding: 2px 8px 0 8px;
79 width: 10px;
80 text-align: center;
82 #qg .x4c {
83 float: left;
84 width: 70px;
86 #qg .x4d {
87 float: left;
88 padding: 2px 0 0 8px;
89 width: 100px;
92 </style>
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'];
102 var ipp2p = [
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']]
106 // <% layer7(); %>
107 layer7.sort();
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) {
119 var b = [];
120 var s, i;
122 if (data[0] != 0) {
123 b.push(((data[0] == 1) ? 'To ' : 'From ') + data[1]);
125 if (data[2] >= -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 ';
131 else s = '';
132 b.push(s + 'Port: ' + data[4].replace(/:/g, '-'));
135 if (data[5] != 0) {
136 for (i = 0; i < ipp2p.length; ++i)
137 if (ipp2p[i][0] == data[5]) {
138 b.push('IPP2P: ' + ipp2p[i][1])
139 break;
143 else if (data[6] != '') {
144 b.push('L7: ' + data[6])
147 if (data[7] != '') {
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;
166 f[1].value = '';
167 f[2].selectedIndex = 1;
168 f[3].selectedIndex = 0;
169 f[4].value = '';
170 f[5].selectedIndex = 0;
171 f[6].selectedIndex = 0;
172 f[7].value = '';
173 f[8].value = '';
174 f[9].selectedIndex = 5;
175 f[10].value = '';
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);
183 if (!disable) {
184 this.enDiFields(this.newEditor);
188 qosg.enDiFields = function(row) {
189 var f = fields.getAll(row);
190 var x;
192 f[1].disabled = (f[0].selectedIndex == 0);
193 x = f[2].value;
194 x = ((x != -1) && (x != 6) && (x != 17));
195 f[3].disabled = x;
196 if (f[3].selectedIndex == 0) x = 1;
197 f[4].disabled = x;
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);
205 var a, b, e;
207 this.enDiFields(row);
208 ferror.clearAll(f);
210 a = f[0].value * 1;
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;
221 e = f[7];
222 a = e.value = e.value.trim();
223 if (a != '') {
224 if (!v_range(e, quiet, 0, BMAX)) return 0;
225 a *= 1;
228 e = f[8];
229 b = e.value = e.value.trim();
230 if (b != '') {
231 b *= 1;
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;
236 else if (a != '') {
237 b = BMAX;
240 if ((b != '') && (a >= b)) {
241 ferror.set(f[7], 'Invalid range', quiet);
242 return 0;
245 return v_length(f[10], quiet);
248 qosg.setup = function() {
249 var i, a, b;
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]);
255 // what a mess...
256 this.init('qg', 'move', 50, [
257 { multi: [
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>' }
271 ] },
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) {
282 b = a[i].split('<');
283 if (b.length == 9) {
284 // fixup < 0.08 !!! temp
285 b.splice(7, 0, '', '');
287 else if (b.length == 10) {
288 c = b[7].split(':');
289 b.splice(7, 1, c[0], (c.length == 1) ? '' : c[1]);
290 b[10] = unescape(b[10]);
292 else continue;
293 b[4] = b[4].replace(/:/g, '-');
294 qosg.insertData(-1, b);
297 this.showNewEditor();
298 this.resetNewEditor();
301 function verifyFields(focused, quiet)
303 return 1;
306 function save()
308 if (qosg.isEditing()) return;
310 var fom = E('_fom');
311 var i, a, b, c;
313 c = qosg.getAllData();
314 a = [];
315 for (i = 0; i < c.length; ++i) {
316 b = c[i].slice(0);
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]);
320 a.push(b.join('<'));
322 fom.qos_orules.value = a.join('>');
324 form.submit(fom, 1);
327 function init()
329 qosg.recolor();
331 </script>
333 </head>
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>
340 </td></tr>
341 <tr id='body'><td id='navi'><script type='text/javascript'>navi()</script></td>
342 <td id='content'>
343 <div id='ident'><% ident(); %></div>
345 <!-- / / / -->
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>
354 </div>
356 <script type='text/javascript'>
357 if (nvram.qos_enable != '1') {
358 W('<div class="note-disabled"><b>QoS disabled.</b> &nbsp; <a href="qos-settings.asp">Enable &raquo;</a></div>');
360 </script>
362 <!-- / / / -->
364 </td></tr>
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();'>
369 </td></tr>
370 </table>
371 </form>
372 <script type='text/javascript'>qosg.setup();</script>
373 </body>
374 </html>