Merge branch 'Toastman-RT' into Toastman-VLAN
[tomato.git] / release / src / router / www / qos-detailed.asp
blob9647649cb498bb3ba2cfe44e2036f5b7c0b45490
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 Filtering/Extensions on this QoS/Connection Details page
8 Copyright (C) 2011 Augusto Bott
9 http://code.google.com/p/tomato-sdhc-vlan/
11 For use with Tomato Firmware only.
12 No part of this file may be used without permission.
13 -->
14 <html>
15 <head>
16 <meta http-equiv='content-type' content='text/html;charset=utf-8'>
17 <meta name='robots' content='noindex,nofollow'>
18 <title>[<% ident(); %>] QoS: View Details</title>
19 <link rel='stylesheet' type='text/css' href='tomato.css'>
20 <% css(); %>
21 <script type='text/javascript' src='tomato.js'></script>
23 <!-- / / / -->
25 <style type='text/css'>
26 #grid .co7 {
27 width: 20px;
29 #grid .co8 {
30 text-align: right;
32 #grid .co9 {
33 text-align: right;
35 </style>
37 <script type='text/javascript' src='debug.js'></script>
38 <script type='text/javascript' src='protocols.js'></script>
39 <script type='text/javascript' src='interfaces.js'></script>
41 <script type='text/javascript'>
44 // <% nvram('qos_classnames,lan_ipaddr,lan1_ipaddr,lan2_ipaddr,lan3_ipaddr,lan_ifname,lan1_ifname,lan2_ifname,lan3_ifname,wan_proto,lan_netmask,lan1_netmask,lan2_netmask,lan3_netmask'); %>
47 var Unclassified = ['Unclassified'];
48 var classNames = nvram.qos_classnames.split(' ');
49 var abc = Unclassified.concat(classNames);
51 var colors = ['F08080','E6E6FA','0066CC','8FBC8F','FAFAD2','ADD8E6','9ACD32','E0FFFF','90EE90','FF9933','FFF0F5'];
52 var filterip = [];
53 var filteripe = [];
55 if ((viewClass = '<% cgi_get("class"); %>') == '') {
56 viewClass = -1;
58 else if ((isNaN(viewClass *= 1)) || (viewClass < 0) || (viewClass > 10)) {
59 viewClass = 0;
62 var queue = [];
63 var xob = null;
64 var cache = [];
65 var lock = 0;
67 function resolve()
69 if ((queue.length == 0) || (xob)) return;
71 xob = new XmlHttp();
72 xob.onCompleted = function(text, xml) {
73 eval(text);
74 for (var i = 0; i < resolve_data.length; ++i) {
75 var r = resolve_data[i];
76 if (r[1] == '') r[1] = r[0];
77 cache[r[0]] = r[1];
78 if (lock == 0) grid.setName(r[0], r[1]);
80 if (queue.length == 0) {
81 if ((lock == 0) && (resolveCB) && (grid.sortColumn == 4)) grid.resort();
83 else setTimeout(resolve, 500);
84 xob = null;
86 xob.onError = function(ex) {
87 xob = null;
90 xob.post('resolve.cgi', 'ip=' + queue.splice(0, 20).join(','));
93 var resolveCB = 0;
94 var bcastCB = 0;
95 var mcastCB = 0;
97 function resolveChanged()
99 var b;
101 b = E('_f_autoresolve').checked ? 1 : 0;
102 if (b != resolveCB) {
103 resolveCB = b;
104 cookie.set('qos_resolve', b);
106 if (b) grid.resolveAll();
109 var grid = new TomatoGrid();
111 grid.dataToView = function(data) {
112 var s, v = [];
113 for (var col = 0; col < data.length; ++col) {
114 switch (col) {
115 case 5: // Class
116 s = abc[data[col]] || ('' + data[col]);
117 break;
118 case 6: // Rule #
119 s = (data[col] * 1 > 0) ? ('' + data[col]) : '';
120 break;
121 case 7: // Bytes out
122 case 8: // Bytes in
123 s = scaleSize(data[col] * 1);
124 break;
125 default:
126 s = '' + data[col];
127 break;
129 v.push(s);
131 return v;
134 grid.sortCompare = function(a, b) {
135 var obj = TGO(a);
136 var col = obj.sortColumn;
137 var da = a.getRowData();
138 var db = b.getRowData();
139 var r;
141 switch (col) {
142 case 0: // Proto
143 case 2: // S port
144 case 4: // D port
145 case 6: // Rule #
146 case 7: // Bytes out
147 case 8: // Bytes in
148 r = cmpInt(da[col], db[col]);
149 break;
150 case 5: // Class
151 r = cmpInt(da[col] ? da[col] : 10000, db[col] ? db[col] : 10000);
152 break;
153 case 1:
154 case 3:
155 var a = fixIP(da[col]);
156 var b = fixIP(db[col]);
157 if ((a != null) && (b != null)) {
158 r = aton(a) - aton(b);
159 break;
161 default:
162 r = cmpText(da[col], db[col]);
163 break;
165 return obj.sortAscending ? r : -r;
168 grid.onClick = function(cell) {
169 var row = PR(cell);
170 var ip = row.getRowData()[3];
171 if (this.lastClicked != row) {
172 this.lastClicked = row;
173 if (ip.indexOf('<') == -1) {
174 queue.push(ip);
175 row.style.cursor = 'wait';
176 resolve();
179 else {
180 this.resolveAll();
184 grid.resolveAll = function()
186 var i, ip, row, q, cols, j;
188 q = [];
189 cols = [1, 3];
190 for (i = 1; i < this.tb.rows.length; ++i) {
191 row = this.tb.rows[i];
192 for (j = cols.length-1; j >= 0; j--) {
193 ip = row.getRowData()[cols[j]];
194 if (ip.indexOf('<') == -1) {
195 if (!q[ip]) {
196 q[ip] = 1;
197 queue.push(ip);
199 row.style.cursor = 'wait';
203 q = null;
204 resolve();
207 grid.setName = function(ip, name) {
208 var i, row, data, cols, j;
210 cols = [1, 3];
211 for (i = this.tb.rows.length - 1; i > 0; --i) {
212 row = this.tb.rows[i];
213 data = row.getRowData();
214 for (j = cols.length-1; j >= 0; j--) {
215 if (data[cols[j]] == ip) {
216 data[cols[j]] = name + ((ip.indexOf(':') != -1) ? '<br>' : ' ') + '<small>(' + ip + ')</small>';
217 row.setRowData(data);
218 row.cells[cols[j]].innerHTML = data[cols[j]];
219 row.style.cursor = 'default';
225 grid.setup = function() {
226 this.init('grid', 'sort');
227 this.headerSet(['Proto', 'Source', 'S Port', 'Destination', 'D Port', 'Class', 'Rule', 'Bytes Out', 'Bytes In']);
230 var ref = new TomatoRefresh('update.cgi', '', 0, 'qos_detailed');
232 var numconntotal = 0;
233 var numconnshown = 0;
235 ref.refresh = function(text)
237 var i, b, d, cols, j;
239 ++lock;
241 numconntotal = 0;
242 numconnshown = 0;
244 try {
245 ctdump = [];
246 eval(text);
248 catch (ex) {
249 ctdump = [];
252 grid.lastClicked = null;
253 grid.removeAllData();
255 var c = [];
256 var q = [];
257 var cursor;
258 var ip;
260 var fskip;
262 cols = [2, 3];
264 for (i = 0; i < ctdump.length; ++i) {
265 fskip=0;
266 numconntotal++;
267 b = ctdump[i];
269 if (E('_f_excludegw').checked) {
270 if ((b[2] == nvram.lan_ipaddr) || (b[3] == nvram.lan_ipaddr) ||
271 (b[2] == nvram.lan1_ipaddr) || (b[3] == nvram.lan1_ipaddr) ||
272 (b[2] == nvram.lan2_ipaddr) || (b[3] == nvram.lan2_ipaddr) ||
273 (b[2] == nvram.lan3_ipaddr) || (b[3] == nvram.lan3_ipaddr) ||
274 (b[2] == '127.0.0.1') || (b[3] == '127.0.0.1')) {
275 continue;
279 if (E('_f_excludebcast').checked) {
280 if ((b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan_ipaddr,nvram.lan_netmask),nvram.lan_netmask)) ||
281 (b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan1_ipaddr,nvram.lan1_netmask),nvram.lan1_netmask)) ||
282 (b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan2_ipaddr,nvram.lan2_netmask),nvram.lan2_netmask)) ||
283 (b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan3_ipaddr,nvram.lan3_netmask),nvram.lan3_netmask)) ||
284 (b[3] == '255.255.255.255') || (b[3] == '0.0.0.0')) {
285 continue;
289 if (E('_f_excludemcast').checked) {
290 var mmin = 3758096384; // aton('224.0.0.0')
291 var mmax = 4026531839; // aton('239.255.255.255')
292 if (((aton(b[2]) >= mmin) && (aton(b[2]) <= mmax)) ||
293 ((aton(b[3]) >= mmin) && (aton(b[3]) <= mmax))) {
294 continue;
298 if (filteripe.length>0) {
299 fskip = 0;
300 for (x = 0; x < filteripe.length; ++x) {
301 if ((b[2] == filteripe[x]) || (b[3] == filteripe[x])) {
302 fskip=1;
303 break;
306 if (fskip == 1) continue;
309 if (filterip.length>0) {
310 fskip = 1;
311 for (x = 0; x < filterip.length; ++x) {
312 if ((b[2] == filterip[x]) || (b[3] == filterip[x])) {
313 fskip=0;
314 break;
317 if (fskip == 1) continue;
320 for (j = cols.length-1; j >= 0; j--) {
321 ip = b[cols[j]];
322 if (cache[ip] != null) {
323 c[ip] = cache[ip];
324 b[cols[j]] = cache[ip] + ((ip.indexOf(':') != -1) ? '<br>' : ' ') + '<small>(' + ip + ')</small>';
325 cursor = 'default';
327 else {
328 if (resolveCB) {
329 if (!q[ip]) {
330 q[ip] = 1;
331 queue.push(ip);
333 cursor = 'wait';
335 else cursor = null;
339 numconnshown++;
340 d = [protocols[b[0]] || b[0], b[2], b[4], b[3], b[5], b[8], b[9], b[6], b[7]];
341 var row = grid.insertData(-1, d);
342 if (cursor) row.style.cursor = cursor;
344 cache = c;
345 c = null;
346 q = null;
348 grid.resort();
349 setTimeout(function() { E('loading').style.visibility = 'hidden'; }, 100);
351 --lock;
353 if (resolveCB) resolve();
354 if (numconnshown != numconntotal)
355 E('numtotalconn').innerHTML='<small><i>(showing ' + numconnshown + ' out of ' + numconntotal + ' connections)</i></small>';
356 else
357 E('numtotalconn').innerHTML='<small><i>(' + numconntotal + ' connections)</i></small>';
360 function init()
362 var c;
364 if (((c = cookie.get('qos_resolve')) != null) && (c == '1')) {
365 E('_f_autoresolve').checked = resolveCB = 1;
368 if (((c = cookie.get('qos_bcast')) != null) && (c == '1')) {
369 E('_f_excludebcast').checked = bcastCB = 1;
372 if (((c = cookie.get('qos_mcast')) != null) && (c == '1')) {
373 E('_f_excludemcast').checked = mcastCB = 1;
376 if (((c = cookie.get('qos_filters')) != null) && (c == '1')) {
377 E('sesdivfilters').style.display='';
380 if (viewClass != -1) E('stitle').innerHTML = 'View Details: ' + abc[viewClass] + ' <span id=\'numtotalconn\'></span>';
381 grid.setup();
382 ref.postData = 'exec=ctdump&arg0=' + viewClass;
383 ref.initPage(250);
385 if (!ref.running) ref.once = 1;
386 ref.start();
389 function dofilter() {
390 if (E('_f_filter_ip').value.length>6) {
391 filterip = E('_f_filter_ip').value.split(',');
392 } else {
393 filterip = [];
396 if (E('_f_filter_ipe').value.length>6) {
397 filteripe = E('_f_filter_ipe').value.split(',');
398 } else {
399 filteripe = [];
402 if (!ref.running) ref.once = 1;
403 ref.start();
406 function toggleFiltersVisibility(){
407 if(E('sesdivfilters').style.display=='') {
408 E('sesdivfilters').style.display='none';
409 cookie.set('qos_filters', 0);
410 } else {
411 E('sesdivfilters').style.display='';
412 cookie.set('qos_filters', 1);
416 function verifyFields(focused, quiet)
418 var b;
420 b = E('_f_excludebcast').checked ? 1 : 0;
421 if (b != bcastCB) {
422 bcastCB = b;
423 cookie.set('qos_bcast', b);
426 b = E('_f_excludemcast').checked ? 1 : 0;
427 if (b != mcastCB) {
428 mcastCB = b;
429 cookie.set('qos_mcast', b);
432 dofilter();
433 resolveChanged();
434 return 1;
437 </script>
438 </head>
439 <body onload='init()'>
440 <form id='_fom' action='javascript:{}'>
441 <table id='container' cellspacing=0>
442 <tr><td colspan=2 id='header'>
443 <div class='title'>Tomato</div>
444 <div class='version'>Version <% version(); %></div>
445 </td></tr>
446 <tr id='body'><td id='navi'><script type='text/javascript'>navi()</script></td>
447 <td id='content'>
448 <div id='ident'><% ident(); %></div>
451 <!-- / / / -->
454 <div class='section-title' id='stitle' onclick='document.location="qos-graphs.asp"' style='cursor:pointer'>View Details: <span id='numtotalconn'></span></div>
455 <div class='section'>
456 <table id='grid' class='tomato-grid' style="float:left" cellspacing=1></table>
458 <div id='loading'><br><b>Loading...</b></div>
459 </div>
462 <!-- / / / -->
465 <div class='section-title'>Filters: <small><i><a href='javascript:toggleFiltersVisibility();'>(Toggle Visibility)</a></i></small></div>
466 <div class='section' id='sesdivfilters' style='display:none'>
467 <script type='text/javascript'>
468 var c;
469 c = [];
470 c.push({ title: 'Only these IPs', name: 'f_filter_ip', size: 50, maxlen: 255, type: 'text', suffix: ' <small>(Comma separated list)</small>' });
471 c.push({ title: 'Exclude these IPs', name: 'f_filter_ipe', size: 50, maxlen: 255, type: 'text', suffix: ' <small>(Comma separated list)</small>' });
472 c.push({ title: 'Exclude gateway traffic', name: 'f_excludegw', type: 'checkbox', value: ((nvram.t_hidelr) == '1' ? 1 : 0) });
473 c.push({ title: 'Exclude broadcasts', name: 'f_excludebcast', type: 'checkbox' });
474 c.push({ title: 'Exclude multicast', name: 'f_excludemcast', type: 'checkbox' });
475 c.push({ title: 'Auto resolve addresses', name: 'f_autoresolve', type: 'checkbox' });
476 createFieldTable('',c);
477 </script>
478 </div>
481 <!-- / / / -->
484 </td></tr>
485 <tr><td id='footer' colspan=2>
486 <script type='text/javascript'>genStdRefresh(1,1,'ref.toggle()');</script>
487 </td></tr>
488 </table>
489 </form>
490 </body>
491 </html>