Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / www / basic-static.asp
blob2c623febab82d79a6e927968fea59f1597b22478
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 Enhancements by Teaman
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(); %>] Basic: Static DHCP/ARP &amp; Bandwidth Monitoring of LAN Clients</title>
19 <link rel='stylesheet' type='text/css' href='tomato.css'>
20 <% css(); %>
21 <script type='text/javascript' src='tomato.js'></script>
23 <!-- / / / -->
24 <style type='text/css'>
25 #bs-grid .co1 {
26 width: 120px;
27 text-align: center;
29 #bs-grid .co2 {
30 width: 80px;
31 text-align: center;
33 #bs-grid .co3 {
34 width: 120px;
36 #bs-grid .co4 {
37 width: 80px;
38 text-align: center;
40 #bs-grid .centered {
41 text-align: center;
43 </style>
45 <script type='text/javascript' src='debug.js'></script>
47 <script type='text/javascript'>
49 // <% nvram("lan_ipaddr,lan_netmask,dhcpd_static,dhcpd_startip,dhcpd_static_only,cstats_include,arpbind_listed"); %>
51 if (nvram.lan_ipaddr.match(/^(\d+\.\d+\.\d+)\.(\d+)$/)) ipp = RegExp.$1 + '.';
52 else ipp = '?.?.?.';
54 autonum = aton(nvram.lan_ipaddr) & aton(nvram.lan_netmask);
56 var sg = new TomatoGrid();
58 sg.exist = function(f, v) {
59 var data = this.getAllData();
60 for (var i = 0; i < data.length; ++i) {
61 if (data[i][f] == v) return true;
63 return false;
66 sg.existMAC = function(mac) {
67 if (isMAC0(mac)) return false;
68 return this.exist(0, mac) || this.exist(1, mac);
71 sg.existName = function(name) {
72 return this.exist(5, name);
75 sg.inStatic = function(n) {
76 return this.exist(3, n);
79 sg.dataToView = function(data) {
80 var v = [];
81 var s = (data[0] == '00:00:00:00:00:00') ? '' : data[0];
82 if (!isMAC0(data[1])) s += '<br>' + data[1];
83 v.push((s == '') ? '<center><small><i>(unset)</i></small></center>' : s);
85 v.push((data[2].toString() != '0') ? '<small><i>Enabled</i></small>' : '');
86 v.push(escapeHTML('' + data[3]));
87 v.push((data[4].toString() != '0') ? '<small><i>Enabled</i></small>' : '');
88 v.push(escapeHTML('' + data[5]));
89 return v;
92 sg.dataToFieldValues = function (data) {
93 return ([data[0],
94 data[1],
95 (data[2].toString() != '0') ? 'checked' : '',
96 data[3],
97 (data[4].toString() != '0') ? 'checked' : '',
98 data[5]]);
101 sg.fieldValuesToData = function(row) {
102 var f = fields.getAll(row);
103 return ([f[0].value,
104 f[1].value,
105 f[2].checked ? '1' : '0',
106 f[3].value,
107 f[4].checked ? '1' : '0',
108 f[5].value]);
111 sg.sortCompare = function(a, b) {
112 var da = a.getRowData();
113 var db = b.getRowData();
114 var r = 0;
115 switch (this.sortColumn) {
116 case 0:
117 r = cmpText(da[0], db[0]);
118 break;
119 case 1:
120 r = cmpInt(da[2], db[2]);
121 break;
122 case 2:
123 r = cmpIP(da[3], db[3]);
124 break;
125 case 3:
126 r = cmpInt(da[4], db[4]);
127 break;
129 if (r == 0) r = cmpText(da[5], db[5]);
130 return this.sortAscending ? r : -r;
133 sg.verifyFields = function(row, quiet) {
134 var f, s, i;
136 f = fields.getAll(row);
138 if (!v_macz(f[0], quiet)) return 0;
139 if (!v_macz(f[1], quiet)) return 0;
140 if (isMAC0(f[0].value)) {
141 f[0].value = f[1].value;
142 f[1].value = '00:00:00:00:00:00';
144 else if (f[0].value == f[1].value) {
145 f[1].value = '00:00:00:00:00:00';
147 else if ((!isMAC0(f[1].value)) && (f[0].value > f[1].value)) {
148 s = f[1].value;
149 f[1].value = f[0].value;
150 f[0].value = s;
153 f[1].disabled = f[2].checked;
155 for (i = 0; i < 2; ++i) {
156 if (this.existMAC(f[i].value)) {
157 ferror.set(f[i], 'Duplicate MAC address', quiet);
158 return 0;
162 if (f[3].value.indexOf('.') == -1) {
163 s = parseInt(f[3].value, 10)
164 if (isNaN(s) || (s <= 0) || (s >= 255)) {
165 ferror.set(f[3], 'Invalid IP address', quiet);
166 return 0;
168 f[3].value = ipp + s;
171 if ((!isMAC0(f[0].value)) && (this.inStatic(f[3].value))) {
172 ferror.set(f[3], 'Duplicate IP address', quiet);
173 return 0;
176 /* REMOVE-BEGIN
177 // if (!v_hostname(f[5], quiet, 5)) return 0;
178 // if (!v_nodelim(f[5], quiet, 'Hostname', 1)) return 0;
179 REMOVE-END */
180 s = f[5].value.trim().replace(/\s+/g, ' ');
182 if (s.length > 0) {
183 if (s.search(/^[.a-zA-Z0-9_\- ]+$/) == -1) {
184 ferror.set(f[5], 'Invalid hostname. Only characters "A-Z 0-9 . - _" are allowed.', quiet);
185 return 0;
187 if (this.existName(s)) {
188 ferror.set(f[5], 'Duplicate hostname.', quiet);
189 return 0;
191 f[5].value = s;
194 if (isMAC0(f[0].value)) {
195 if (s == '') {
196 s = 'Both MAC address and name fields must not be empty.';
197 ferror.set(f[0], s, 1);
198 ferror.set(f[5], s, quiet);
199 return 0;
200 } else {
201 ferror.clear(f[0]);
202 ferror.clear(f[5]);
206 if (((f[0].value == '00:00:00:00:00:00') || (f[1].value == '00:00:00:00:00:00')) && (f[0].value == f[1].value)) {
207 f[2].disabled=1;
208 f[2].checked=0;
209 } else {
210 f[2].disabled=0;
213 return 1;
216 sg.resetNewEditor = function() {
217 var f, c, n;
219 f = fields.getAll(this.newEditor);
220 ferror.clearAll(f);
222 if ((c = cookie.get('addstatic')) != null) {
223 cookie.set('addstatic', '', 0);
224 c = c.split(',');
225 if (c.length == 3) {
226 f[0].value = c[0];
227 f[1].value = '00:00:00:00:00:00';
228 f[3].value = c[1];
229 f[5].value = c[2];
230 return;
234 f[0].value = '00:00:00:00:00:00';
235 f[1].value = '00:00:00:00:00:00';
236 f[2].disabled = 1;
237 f[2].checked = 0;
238 f[4].checked = 0;
239 f[5].value = '';
241 n = 10;
242 do {
243 if (--n < 0) {
244 f[3].value = '';
245 return;
247 autonum++;
248 } while (((c = fixIP(ntoa(autonum), 1)) == null) || (c == nvram.lan_ipaddr) || (this.inStatic(c)));
250 f[3].value = c;
253 sg.setup = function() {
254 this.init('bs-grid', 'sort', 250, [
255 { multi: [ { type: 'text', maxlen: 17 }, { type: 'text', maxlen: 17 } ] },
256 { type: 'checkbox', prefix: '<div class="centered">', suffix: '</div>' },
257 { type: 'text', maxlen: 15 },
258 { type: 'checkbox', prefix: '<div class="centered">', suffix: '</div>' },
259 { type: 'text', maxlen: 50 } ] );
261 this.headerSet(['MAC Address', 'Bound to', 'IP Address', 'IPTraffic', 'Hostname']);
263 var ipt = nvram.cstats_include.split(',');
264 var s = nvram.dhcpd_static.split('>');
265 for (var i = 0; i < s.length; ++i) {
266 var h = '0';
267 var t = s[i].split('<');
268 if ((t.length == 3) || (t.length == 4)) {
269 var d = t[0].split(',');
270 var ip = (t[1].indexOf('.') == -1) ? (ipp + t[1]) : t[1];
271 for (var j = 0; j < ipt.length; ++j) {
272 if (ip == ipt[j]) {
273 h = '1';
274 break;
277 if (t.length == 3) {
278 t[3] = '0';
280 this.insertData(-1, [d[0], (d.length >= 2) ? d[1] : '00:00:00:00:00:00', t[3],
281 (t[1].indexOf('.') == -1) ? (ipp + t[1]) : t[1], h, t[2]]);
284 this.sort(4);
285 this.showNewEditor();
286 this.resetNewEditor();
289 function save() {
290 if (sg.isEditing()) return;
292 var data = sg.getAllData();
293 var sdhcp = '';
294 var ipt = '';
295 var i;
297 for (i = 0; i < data.length; ++i) {
298 var d = data[i];
299 sdhcp += d[0];
300 if (!isMAC0(d[1])) sdhcp += ',' + d[1];
301 sdhcp += '<' + d[3] + '<' + d[5] + '<' + d[2] + '>';
302 if (d[4] == '1') ipt += ((ipt.length > 0) ? ',' : '') + d[3];
305 var fom = E('_fom');
306 fom.dhcpd_static.value = sdhcp;
307 fom.arpbind_listed.value = E('_f_arpbind_listed').checked ? '1' : '0';
308 fom.dhcpd_static_only.value = E('_f_dhcpd_static_only').checked ? '1' : '0';
309 fom.cstats_include.value = ipt;
310 form.submit(fom, 1);
313 function init() {
314 var c;
315 if (((c = cookie.get('basic_static_notes_vis')) != null) && (c == '1')) {
316 toggleVisibility("notes");
319 if (((c = cookie.get('basic_static_options_vis')) != null) && (c == '1')) {
320 toggleVisibility("options");
323 sg.recolor();
326 function toggleVisibility(whichone) {
327 if(E('sesdiv' + whichone).style.display=='') {
328 E('sesdiv' + whichone).style.display='none';
329 E('sesdiv' + whichone + 'showhide').innerHTML='(Click here to show)';
330 cookie.set('basic_static_' + whichone + '_vis', 0);
331 } else {
332 E('sesdiv' + whichone).style.display='';
333 E('sesdiv' + whichone + 'showhide').innerHTML='(Click here to hide)';
334 cookie.set('basic_static_' + whichone + '_vis', 1);
338 function verifyFields(focused, quiet) {
339 return 1;
342 </script>
343 </head>
344 <body onload='init()'>
345 <form id='_fom' method='post' action='tomato.cgi'>
346 <table id='container' cellspacing=0>
347 <tr><td colspan=2 id='header'>
348 <div class='title'>Tomato</div>
349 <div class='version'>Version <% version(); %></div>
350 </td></tr>
351 <tr id='body'><td id='navi'><script type='text/javascript'>navi()</script></td>
352 <td id='content'>
353 <div id='ident'><% ident(); %></div>
355 <!-- / / / -->
357 <input type='hidden' name='_nextpage' value='basic-static.asp'>
358 <input type='hidden' name='_service' value='dhcpd-restart,arpbind-restart,cstats-restart'>
360 <input type='hidden' name='dhcpd_static'>
361 <input type='hidden' name='dhcpd_static_only'>
362 <input type='hidden' name='cstats_include'>
363 <input type='hidden' name='arpbind_listed'>
365 <div class='section-title'>Static DHCP/ARP &amp; Bandwidth Monitoring of LAN Clients</div>
366 <div class='section'>
367 <table class='tomato-grid' id='bs-grid'></table>
368 </div>
370 <!-- / / / -->
372 <div class='section-title'>Options <small><i><a href='javascript:toggleVisibility("options");'><span id='sesdivoptionsshowhide'>(Click here to show)</span></a></i></small></div>
373 <div class='section' id='sesdivoptions' style='display:none'>
374 <script type='text/javascript'>
375 createFieldTable('', [
376 { title: 'Enable static ARP for all devices on list ', name: 'f_arpbind_listed', type: 'checkbox', value: nvram.arpbind_listed == '1' },
377 { title: 'Ignore DHCP requests from unknown devices', name: 'f_dhcpd_static_only', type: 'checkbox', value: nvram.dhcpd_static_only == '1' }
379 </script>
380 </div>
382 <!-- / / / -->
384 <div class='section-title'>Notes <small><i><a href='javascript:toggleVisibility("notes");'><span id='sesdivnotesshowhide'>(Click here to show)</span></a></i></small></div>
385 <div class='section' id='sesdivnotes' style='display:none'>
386 <ul>
387 <li><b>MAC Address</b> - Unique identifier associated to a network interface on this particular device.</li>
388 <li><b>Bound to</b> - Enforce static ARP binding of this particular IP/MAC address pair.</li>
389 <li><b>IP Address</b> - Network address assigned to this device on the local network.</li>
390 <li><b>IPTraffic</b> - Keep track of bandwidth usage for this IP address.</li>
391 <li><b>Hostname</b> - Human-readable nickname/label assigned to this device on the network.</li>
392 </ul>
394 <ul>
395 <li><b>Enable static ARP for (...)</b> - Enforce static ARP binding for all IP/MAC address pairs listed above.</li>
396 <li><b>Ignore DHCP requests (...)</b> - Unlisted MAC addresses won't be able to obtain an IP address through DHCP.</li>
397 </ul>
399 <small>
400 <ul>
401 <li><b>Other relevant notes/hints:</b>
402 <ul>
403 <li>To specify multiple hostnames for a device, separate them with spaces.</li>
404 <li>To enable/enforce static ARP binding for a particular device, it must have only one MAC associated with that particular IP address (i.e. you can't have two MAC addresses linked to the same hostname/device in the table above).</li>
405 <li>When ARP binding is enabled for a particular MAC/IP address pair, that device will always be shown as "active" in the <a href="tools-wol.asp">Wake On LAN</a> table.</li>
406 <li>See also the <a href='advanced-dhcpdns.asp'>Advanced DHCP/DNS</a> settings page for more DHCP-related configuration options.</li>
407 </ul>
408 </ul>
409 </small>
410 </div>
413 <!-- / / / -->
415 </td></tr>
416 <tr><td id='footer' colspan=2>
417 <span id='footer-msg'></span>
418 <input type='button' value='Save' id='save-button' onclick='save()'>
419 <input type='button' value='Cancel' id='cancel-button' onclick='javascript:reloadPage();'>
420 </td></tr>
421 </table>
422 </form>
423 <script type='text/javascript'>sg.setup();</script>
424 </body>
425 </html>