Merge remote-tracking branch 'remotes/origin/Toastman-RT' into Teaman-RT
[tomato.git] / release / src / router / www / qos-detailed.asp
blob53a13a949d913be9e37f1116f8db2c58a991ca96
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'>
43 // <% nvram('qos_classnames,lan_ipaddr,lan1_ipaddr,lan2_ipaddr,lan3_ipaddr,lan_netmask,lan1_netmask,lan2_netmask,lan3_netmask,t_hidelr'); %>
45 var Unclassified = ['Unclassified'];
46 var classNames = nvram.qos_classnames.split(' ');
47 var abc = Unclassified.concat(classNames);
49 var colors = ['F08080','E6E6FA','0066CC','8FBC8F','FAFAD2','ADD8E6','9ACD32','E0FFFF','90EE90','FF9933','FFF0F5'];
50 var filterip = [];
51 var filteripe = [];
53 if ((viewClass = '<% cgi_get("class"); %>') == '') {
54 viewClass = -1;
56 else if ((isNaN(viewClass *= 1)) || (viewClass < 0) || (viewClass > 10)) {
57 viewClass = 0;
60 var queue = [];
61 var xob = null;
62 var cache = [];
63 var lock = 0;
65 function resolve()
67 if ((queue.length == 0) || (xob)) return;
69 xob = new XmlHttp();
70 xob.onCompleted = function(text, xml) {
71 eval(text);
72 for (var i = 0; i < resolve_data.length; ++i) {
73 var r = resolve_data[i];
74 if (r[1] == '') r[1] = r[0];
75 cache[r[0]] = r[1];
76 if (lock == 0) grid.setName(r[0], r[1]);
78 if (queue.length == 0) {
79 if ((lock == 0) && (resolveCB) && (grid.sortColumn == 4)) grid.resort();
81 else setTimeout(resolve, 500);
82 xob = null;
84 xob.onError = function(ex) {
85 xob = null;
88 xob.post('resolve.cgi', 'ip=' + queue.splice(0, 20).join(','));
91 var resolveCB = 0;
92 var bcastCB = 0;
93 var mcastCB = 0;
95 function resolveChanged()
97 var b;
99 b = E('_f_autoresolve').checked ? 1 : 0;
100 if (b != resolveCB) {
101 resolveCB = b;
102 cookie.set('qos_resolve', b);
104 if (b) grid.resolveAll();
107 var grid = new TomatoGrid();
109 grid.dataToView = function(data) {
110 var s, v = [];
111 for (var col = 0; col < data.length; ++col) {
112 switch (col) {
113 case 5: // Class
114 s = abc[data[col]] || ('' + data[col]);
115 break;
116 case 6: // Rule #
117 s = (data[col] * 1 > 0) ? ('' + data[col]) : '';
118 break;
119 case 7: // Bytes out
120 case 8: // Bytes in
121 s = scaleSize(data[col] * 1);
122 break;
123 default:
124 s = '' + data[col];
125 break;
127 v.push(s);
129 return v;
132 grid.sortCompare = function(a, b) {
133 var obj = TGO(a);
134 var col = obj.sortColumn;
135 var da = a.getRowData();
136 var db = b.getRowData();
137 var r;
139 switch (col) {
140 case 0: // Proto
141 case 2: // S port
142 case 4: // D port
143 case 6: // Rule #
144 case 7: // Bytes out
145 case 8: // Bytes in
146 r = cmpInt(da[col], db[col]);
147 break;
148 case 5: // Class
149 r = cmpInt(da[col] ? da[col] : 10000, db[col] ? db[col] : 10000);
150 break;
151 case 1:
152 case 3:
153 var a = fixIP(da[col]);
154 var b = fixIP(db[col]);
155 if ((a != null) && (b != null)) {
156 r = aton(a) - aton(b);
157 break;
159 default:
160 r = cmpText(da[col], db[col]);
161 break;
163 return obj.sortAscending ? r : -r;
166 grid.onClick = function(cell) {
167 var row = PR(cell);
168 var ip = row.getRowData()[3];
169 if (this.lastClicked != row) {
170 this.lastClicked = row;
171 if (ip.indexOf('<') == -1) {
172 queue.push(ip);
173 row.style.cursor = 'wait';
174 resolve();
177 else {
178 this.resolveAll();
182 grid.resolveAll = function()
184 var i, ip, row, q, cols, j;
186 q = [];
187 cols = [1, 3];
188 for (i = 1; i < this.tb.rows.length; ++i) {
189 row = this.tb.rows[i];
190 for (j = cols.length-1; j >= 0; j--) {
191 ip = row.getRowData()[cols[j]];
192 if (ip.indexOf('<') == -1) {
193 if (!q[ip]) {
194 q[ip] = 1;
195 queue.push(ip);
197 row.style.cursor = 'wait';
201 q = null;
202 resolve();
205 grid.setName = function(ip, name) {
206 var i, row, data, cols, j;
208 cols = [1, 3];
209 for (i = this.tb.rows.length - 1; i > 0; --i) {
210 row = this.tb.rows[i];
211 data = row.getRowData();
212 for (j = cols.length-1; j >= 0; j--) {
213 if (data[cols[j]].indexOf(ip) != -1 ) {
214 data[cols[j]] = name + ((ip.indexOf(':') != -1) ? '<br>' : ' ') + '<small>(' + ip + ')</small>';
215 row.setRowData(data);
216 if (E('_f_shortcuts').checked)
217 data[cols[j]] = data[cols[j]] + ' <small><a href="javascript:addExcludeList(\'' + ip + '\')" title="Exclude from List">[Hide]</a></small>';
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) {
236 var i, b, d, cols, j;
238 ++lock;
240 numconntotal = 0;
241 numconnshown = 0;
243 try {
244 ctdump = [];
245 eval(text);
247 catch (ex) {
248 ctdump = [];
251 grid.lastClicked = null;
252 grid.removeAllData();
254 var c = [];
255 var q = [];
256 var cursor;
257 var ip;
259 var fskip;
261 cols = [2, 3];
263 for (i = 0; i < ctdump.length; ++i) {
264 fskip=0;
265 numconntotal++;
266 b = ctdump[i];
268 if (E('_f_excludegw').checked) {
269 if ((b[2] == nvram.lan_ipaddr) || (b[3] == nvram.lan_ipaddr) ||
270 (b[2] == nvram.lan1_ipaddr) || (b[3] == nvram.lan1_ipaddr) ||
271 (b[2] == nvram.lan2_ipaddr) || (b[3] == nvram.lan2_ipaddr) ||
272 (b[2] == nvram.lan3_ipaddr) || (b[3] == nvram.lan3_ipaddr) ||
273 (b[2] == '127.0.0.1') || (b[3] == '127.0.0.1')) {
274 continue;
278 if (E('_f_excludebcast').checked) {
279 if ((b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan_ipaddr,nvram.lan_netmask),nvram.lan_netmask)) ||
280 (b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan1_ipaddr,nvram.lan1_netmask),nvram.lan1_netmask)) ||
281 (b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan2_ipaddr,nvram.lan2_netmask),nvram.lan2_netmask)) ||
282 (b[3] == getBroadcastAddress(getNetworkAddress(nvram.lan3_ipaddr,nvram.lan3_netmask),nvram.lan3_netmask)) ||
283 (b[3] == '255.255.255.255') || (b[3] == '0.0.0.0')) {
284 continue;
288 if (E('_f_excludemcast').checked) {
289 var mmin = 3758096384; // aton('224.0.0.0')
290 var mmax = 4026531839; // aton('239.255.255.255')
291 if (((aton(b[2]) >= mmin) && (aton(b[2]) <= mmax)) ||
292 ((aton(b[3]) >= mmin) && (aton(b[3]) <= mmax))) {
293 continue;
297 if (filteripe.length>0) {
298 fskip = 0;
299 for (x = 0; x < filteripe.length; ++x) {
300 if ((b[2] == filteripe[x]) || (b[3] == filteripe[x])) {
301 fskip=1;
302 break;
305 if (fskip == 1) continue;
308 if (filterip.length>0) {
309 fskip = 1;
310 for (x = 0; x < filterip.length; ++x) {
311 if ((b[2] == filterip[x]) || (b[3] == filterip[x])) {
312 fskip=0;
313 break;
316 if (fskip == 1) continue;
319 for (j = cols.length-1; j >= 0; j--) {
320 ip = b[cols[j]];
321 if (cache[ip] != null) {
322 c[ip] = cache[ip];
323 b[cols[j]] = cache[ip] + ((ip.indexOf(':') != -1) ? '<br>' : ' ') + '<small>(' + ip + ')</small>';
324 cursor = 'default';
326 else {
327 if (resolveCB) {
328 if (!q[ip]) {
329 q[ip] = 1;
330 queue.push(ip);
332 cursor = 'wait';
334 else cursor = null;
336 if (E('_f_shortcuts').checked) {
337 if (cache[ip] == null) {
338 b[cols[j]] = b[cols[j]] + ' <small><a href="javascript:addToResolveQueue(\'' + ip + '\')" title="Resolve the hostname of this address">[resolve]</a></small>';
340 b[cols[j]] = b[cols[j]] + ' <small><a href="javascript:addExcludeList(\'' + ip + '\')" title="Filter out this IP">[hide]</a></small>';
344 numconnshown++;
345 d = [protocols[b[0]] || b[0], b[2], b[4], b[3], b[5], b[8], b[9], b[6], b[7]];
346 var row = grid.insertData(-1, d);
347 if (cursor) row.style.cursor = cursor;
349 cache = c;
350 c = null;
351 q = null;
353 grid.resort();
354 setTimeout(function() { E('loading').style.visibility = 'hidden'; }, 100);
356 --lock;
358 if (resolveCB) resolve();
359 if (numconnshown != numconntotal)
360 E('numtotalconn').innerHTML='<small><i>(showing ' + numconnshown + ' out of ' + numconntotal + ' connections)</i></small>';
361 else
362 E('numtotalconn').innerHTML='<small><i>(' + numconntotal + ' connections)</i></small>';
365 function addExcludeList(address) {
366 if (E('_f_filter_ipe').value.length<6) {
367 E('_f_filter_ipe').value = address;
368 } else {
369 if (E('_f_filter_ipe').value.indexOf(address) < 0) {
370 E('_f_filter_ipe').value = E('_f_filter_ipe').value + ',' + address;
373 dofilter();
376 function addToResolveQueue(ip) {
377 queue.push(ip);
378 resolve();
381 function init() {
382 var c;
384 if ((c = cookie.get('qos_filterip')) != null) {
385 cookie.set('qos_filterip', '', 0);
386 if (c.length>6) {
387 E('_f_filter_ip').value = c;
388 filterip = c.split(',');
392 if (((c = cookie.get('qos_resolve')) != null) && (c == '1')) {
393 E('_f_autoresolve').checked = resolveCB = 1;
396 if (((c = cookie.get('qos_bcast')) != null) && (c == '1')) {
397 E('_f_excludebcast').checked = bcastCB = 1;
400 if (((c = cookie.get('qos_mcast')) != null) && (c == '1')) {
401 E('_f_excludemcast').checked = mcastCB = 1;
404 if (((c = cookie.get('qos_details_filters_vis')) != null) && (c == '1')) {
405 toggleVisibility("filters");
408 if (viewClass != -1) E('stitle').innerHTML = 'Details: ' + abc[viewClass] + ' <span id=\'numtotalconn\'></span>';
410 E('_f_shortcuts').checked = (((c = cookie.get('qos_detailed_shortcuts')) != null) && (c == '1'));
412 grid.setup();
413 ref.postData = 'exec=ctdump&arg0=' + viewClass;
414 ref.initPage(250);
416 if (!ref.running) ref.once = 1;
417 ref.start();
420 function dofilter() {
421 if (E('_f_filter_ip').value.length>6) {
422 filterip = E('_f_filter_ip').value.split(',');
423 } else {
424 filterip = [];
427 if (E('_f_filter_ipe').value.length>6) {
428 filteripe = E('_f_filter_ipe').value.split(',');
429 } else {
430 filteripe = [];
433 if (!ref.running) ref.once = 1;
434 ref.start();
437 function toggleVisibility(whichone) {
438 if(E('sesdiv' + whichone).style.display=='') {
439 E('sesdiv' + whichone).style.display='none';
440 E('sesdiv' + whichone + 'showhide').innerHTML='(Click here to show)';
441 cookie.set('qos_details_' + whichone + '_vis', 0);
442 } else {
443 E('sesdiv' + whichone).style.display='';
444 E('sesdiv' + whichone + 'showhide').innerHTML='(Click here to hide)';
445 cookie.set('qos_details_' + whichone + '_vis', 1);
449 function verifyFields(focused, quiet)
451 var b;
453 b = E('_f_excludebcast').checked ? 1 : 0;
454 if (b != bcastCB) {
455 bcastCB = b;
456 cookie.set('qos_bcast', b);
459 b = E('_f_excludemcast').checked ? 1 : 0;
460 if (b != mcastCB) {
461 mcastCB = b;
462 cookie.set('qos_mcast', b);
465 cookie.set('qos_detailed_shortcuts', (E('_f_shortcuts').checked ? '1' : '0'), 1);
467 dofilter();
468 resolveChanged();
469 return 1;
472 </script>
473 </head>
474 <body onload='init()'>
475 <form id='_fom' action='javascript:{}'>
476 <table id='container' cellspacing=0>
477 <tr><td colspan=2 id='header'>
478 <div class='title'>Tomato</div>
479 <div class='version'>Version <% version(); %></div>
480 </td></tr>
481 <tr id='body'><td id='navi'><script type='text/javascript'>navi()</script></td>
482 <td id='content'>
483 <div id='ident'><% ident(); %></div>
485 <!-- / / / -->
487 <div class='section-title' id='stitle' onclick='document.location="qos-graphs.asp"' style='cursor:pointer'>Details <span id='numtotalconn'></span></div>
488 <div class='section'>
489 <table id='grid' class='tomato-grid' style="float:left" cellspacing=1></table>
491 <div id='loading'><br><b>Loading...</b></div>
492 </div>
494 <!-- / / / -->
496 <div class='section-title'>Filters <small><i><a href='javascript:toggleVisibility("filters");'><span id='sesdivfiltersshowhide'>(Click here to show)</span></a></i></small></div>
497 <div class='section' id='sesdivfilters' style='display:none'>
498 <script type='text/javascript'>
499 var c;
500 c = [];
501 c.push({ title: 'Only these IPs', name: 'f_filter_ip', size: 50, maxlen: 255, type: 'text', suffix: ' <small>(Comma separated list)</small>' });
502 c.push({ title: 'Exclude these IPs', name: 'f_filter_ipe', size: 50, maxlen: 255, type: 'text', suffix: ' <small>(Comma separated list)</small>' });
503 c.push({ title: 'Exclude gateway traffic', name: 'f_excludegw', type: 'checkbox', value: ((nvram.t_hidelr) == '1' ? 1 : 0) });
504 c.push({ title: 'Exclude IPv4 broadcast', name: 'f_excludebcast', type: 'checkbox' });
505 c.push({ title: 'Exclude IPv4 multicast', name: 'f_excludemcast', type: 'checkbox' });
506 c.push({ title: 'Auto resolve addresses', name: 'f_autoresolve', type: 'checkbox' });
507 c.push({ title: 'Show shortcuts', name: 'f_shortcuts', type: 'checkbox' });
508 createFieldTable('',c);
509 </script>
510 </div>
512 <!-- / / / -->
514 </td></tr>
515 <tr><td id='footer' colspan=2>
516 <script type='text/javascript'>genStdRefresh(1,1,'ref.toggle()');</script>
517 </td></tr>
518 </table>
519 </form>
520 </body>
521 </html>