Merge branch 'tomato-RT' into Toastman-RT
[tomato.git] / release / src / router / www / basic-static.asp
blobc70bad4d01b95a09dc152204f6286f8e3dbbe1cb
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,bwm_client,dhcpd_static_only,arpbind_static"); %>
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(4, name);
75 sg.inStatic = function(n) {
76 return this.exist(2, 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);
84 v.push((data[2].toString() != '0') ? 'Enabled' : '');
85 v.push(escapeHTML('' + data[3]));
86 v.push((data[4].toString() != '0') ? 'Enabled' : '');
87 v.push(escapeHTML('' + data[5]));
88 return v;
91 sg.dataToFieldValues = function (data) {
92 return ([data[0],
93 data[1],
94 (data[2].toString() != '0') ? 'checked' : '',
95 data[3],
96 (data[4].toString() != '0') ? 'checked' : '',
97 data[5]]);
100 sg.fieldValuesToData = function(row) {
101 var f = fields.getAll(row);
102 return ([f[0].value,
103 f[1].value,
104 f[2].checked ? '1' : '0',
105 f[3].value,
106 f[4].checked ? '1' : '0',
107 f[5].value]);
110 sg.sortCompare = function(a, b) {
111 var da = a.getRowData();
112 var db = b.getRowData();
113 var r = 0;
114 switch (this.sortColumn) {
115 case 0:
116 r = cmpText(da[0], db[0]);
117 break;
118 case 1:
119 r = cmpInt(da[2], db[2]);
120 break;
121 case 2:
122 r = cmpIP(da[3], db[3]);
123 break;
124 case 3:
125 r = cmpInt(da[4], db[4]);
126 break;
128 if (r == 0) r = cmpText(da[5], db[5]);
129 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 /* REMOVE-BEGIN
154 if(f[2].checked) {
155 // f[1].value = '00:00:00:00:00:00';
156 f[1].disabled = true;
157 } else {
158 f[1].disabled = false;
160 REMOVE-END */
161 f[1].disabled = f[2].checked;
163 for (i = 0; i < 2; ++i) {
164 if (this.existMAC(f[i].value)) {
165 ferror.set(f[i], 'Duplicate MAC address', quiet);
166 return 0;
170 if (f[2].value.indexOf('.') == -1) {
171 s = parseInt(f[3].value, 10)
172 if (isNaN(s) || (s <= 0) || (s >= 255)) {
173 ferror.set(f[3], 'Invalid IP address', quiet);
174 return 0;
176 f[2].value = ipp + s;
179 if ((!isMAC0(f[0].value)) && (this.inStatic(f[3].value))) {
180 ferror.set(f[3], 'Duplicate IP address', quiet);
181 return 0;
184 s = f[5].value.trim().replace(/\s+/g, ' ');
185 if (s.length > 0) {
186 if (s.search(/^[.a-zA-Z0-9_\- ]+$/) == -1) {
187 ferror.set(f[5], 'Invalid hostname. Only characters "A-Z 0-9 . - _" are allowed.', quiet);
188 return 0;
190 if (this.existName(s)) {
191 ferror.set(f[5], 'Duplicate hostname.', quiet);
192 return 0;
194 f[4].value = s;
197 if (isMAC0(f[0].value)) {
198 if (s == '') {
199 s = 'Both MAC address and name fields must not be empty.';
200 ferror.set(f[0], s, 1);
201 ferror.set(f[5], s, quiet);
202 return 0;
203 } else {
204 ferror.clear(f[0]);
205 ferror.clear(f[5]);
209 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)) {
210 f[2].disabled=1;
211 f[2].checked=0;
212 } else {
213 f[2].disabled=0;
216 return 1;
219 sg.resetNewEditor = function() {
220 var f, c, n;
222 f = fields.getAll(this.newEditor);
223 ferror.clearAll(f);
225 if ((c = cookie.get('addstatic')) != null) {
226 cookie.set('addstatic', '', 0);
227 c = c.split(',');
228 if (c.length == 3) {
229 f[0].value = c[0];
230 f[1].value = '00:00:00:00:00:00';
231 f[2].value = c[1];
232 f[5].value = c[2];
233 return;
237 f[0].value = '00:00:00:00:00:00';
238 f[1].value = '00:00:00:00:00:00';
239 f[2].disabled = 1;
240 f[5].value = '';
242 n = 10;
243 do {
244 if (--n < 0) {
245 f[2].value = '';
246 return;
248 autonum++;
249 } while (((c = fixIP(ntoa(autonum), 1)) == null) || (c == nvram.lan_ipaddr) || (this.inStatic(c)));
251 f[2].value = c;
254 sg.setup = function() {
255 this.init('bs-grid', 'sort', 250, [
256 { multi: [ { type: 'text', maxlen: 17 }, { type: 'text', maxlen: 17 } ] },
257 { type: 'checkbox', prefix: '<div class="centered">', suffix: '</div>' },
258 { type: 'text', maxlen: 15 },
259 { type: 'checkbox', prefix: '<div class="centered">', suffix: '</div>' },
260 { type: 'text', maxlen: 50 } ] );
262 this.headerSet(['MAC Address', 'Bound to', 'IP Address', 'BW Mon', 'Hostname' ]);
264 var s = nvram.dhcpd_static.split('>');
265 var asr = nvram.arpbind_static.split('>');
267 var bwr;
268 if (nvram.bwm_client.indexOf('>') > 0) {
269 bwr = nvram.bwm_client.split('>');
270 } else {
271 bwr = nvram.bwm_client.split(',');
274 for (var i = 0; i < s.length; ++i) {
275 var bwe = '0';
276 var ase = '0';
277 var t = s[i].split('<');
278 if (t.length < 3)
279 continue;
280 var ip = (t[1].indexOf('.') == -1) ? (ipp + t[1]) : t[1];
281 var d = t[0].split(',');
283 if (t.length == 3) {
284 for (var j = 0; j < bwr.length; ++j) {
285 var bwl = bwr[j].split('<');
286 if ((bwl.length == 2) && (bwl[0] == ip))
287 bwe = '1';
289 for (var k = 0; k < asr.length; ++k) {
290 var asl = asr[k].split('<');
291 if ((asl.length == 2) && (asl[1] == d))
292 ase = '1';
296 if (t.length == 4) {
297 for (var j = 0; j < bwr.length; ++j) {
298 if (ip == bwr[j]) {
299 bwe = '1';
300 break;
303 ase = t[3].toString();
306 this.insertData(-1, [ d[0], (d.length >= 2) ? d[1] : '00:00:00:00:00:00', ase, ip, bwe, t[2] ]);
310 this.sort(4);
311 this.showNewEditor();
312 this.resetNewEditor();
315 function save() {
316 if (sg.isEditing()) return;
318 var data = sg.getAllData();
319 var sdhcp = '';
320 var bwm = '';
321 var i;
323 for (i = 0; i < data.length; ++i) {
324 var d = data[i];
325 sdhcp += d[0];
326 if (!isMAC0(d[1])) sdhcp += ',' + d[1];
327 sdhcp += '<' + d[3] + '<' + d[5] + '<' + d[2] + '>';
329 if (d[4] == '1') bwm += ((bwm.length > 0) ? ',' : '') + d[3];
332 var fom = E('_fom');
333 fom.bwm_client.value = bwm;
334 fom.dhcpd_static.value = sdhcp;
335 fom.dhcpd_static_only.value = E('_f_dhcpd_static_only').checked ? '1' : '0';
337 form.submit(fom, 1);
340 function init() {
341 var c;
342 if (((c = cookie.get('basic_static_notes_vis')) != null) && (c == '1')) {
343 toggleVisibility("notes");
345 if (((c = cookie.get('basic_static_options_vis')) != null) && (c == '1')) {
346 toggleVisibility("options");
348 sg.recolor();
351 function toggleVisibility(whichone) {
352 if(E('sesdiv' + whichone).style.display=='') {
353 E('sesdiv' + whichone).style.display='none';
354 E('sesdiv' + whichone + 'showhide').innerHTML='(Click here to show)';
355 cookie.set('basic_static_' + whichone + '_vis', 0);
356 } else {
357 E('sesdiv' + whichone).style.display='';
358 E('sesdiv' + whichone + 'showhide').innerHTML='(Click here to hide)';
359 cookie.set('basic_static_' + whichone + '_vis', 1);
363 function verifyFields(focused, quiet) {
364 return 1;
367 </script>
368 </head>
369 <body onload='init()'>
370 <form id='_fom' method='post' action='tomato.cgi'>
371 <table id='container' cellspacing=0>
372 <tr><td colspan=2 id='header'>
373 <div class='title'>Tomato</div>
374 <div class='version'>Version <% version(); %></div>
375 </td></tr>
376 <tr id='body'><td id='navi'><script type='text/javascript'>navi()</script></td>
377 <td id='content'>
378 <div id='ident'><% ident(); %></div>
380 <!-- / / / -->
382 <input type='hidden' name='_nextpage' value='basic-static.asp'>
383 <input type='hidden' name='_service' value='dhcpd-restart,bwclimon-restart,arpbind-restart'>
385 <input type='hidden' name='bwm_client'>
386 <input type='hidden' name='dhcpd_static'>
387 <input type='hidden' name='dhcpd_static_only'>
388 <input type='hidden' name='arpbind_static'>
390 <div class='section-title'>Static DHCP/ARP &amp; Bandwidth Monitoring of LAN Clients</div>
391 <div class='section'>
392 <table class='tomato-grid' id='bs-grid'></table>
393 </div>
395 <!-- / / / -->
397 <div class='section-title'>Options <small><i><a href='javascript:toggleVisibility("options");'><span id='sesdivoptionsshowhide'>(Click here to show)</span></a></i></small></div>
398 <div class='section' id='sesdivoptions' style='display:none'>
399 <script type='text/javascript'>
400 createFieldTable('', [
401 { title: 'Ignore DHCP requests from unknown devices', name: 'f_dhcpd_static_only', type: 'checkbox', value: nvram.dhcpd_static_only == '1' }
403 </script>
404 </div>
406 <!-- / / / -->
408 <div class='section-title'>Notes <small><i><a href='javascript:toggleVisibility("notes");'><span id='sesdivnotesshowhide'>(Click here to show)</span></a></i></small></div>
409 <div class='section' id='sesdivnotes' style='display:none'>
410 <ul>
411 <li><b>MAC Address</b> - Unique identifier associated to a network interface on this particular device.</li>
412 <li><b>Bound to</b> - Enforce static ARP binding of this particular IP/MAC address pair.</li>
413 <li><b>IP Address</b> - Network address assigned to this device on the local network.</li>
414 <li><b>BW Mon</b> - Monitor volume of network traffic from/to this IP address that goes through the router.</li>
415 <li><b>Hostname</b> - Human-readable nickname/label assigned to this device on the network.</li>
416 </ul>
417 <ul>
418 <li><b>Ignore DHCP requests (...)</b> - Unlisted MAC addresses won't be able to obtain an IP address through DHCP.</li>
419 </ul>
420 <small>
421 <ul>
422 <li><b>Other relevant notes/hints:</b>
423 <ul>
424 <li>To specify multiple hostnames for a device, separate them with spaces.</li>
425 <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>
426 <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>
427 </ul>
428 </ul>
429 </small>
430 </div>
432 <!-- / / / -->
434 </td></tr>
435 <tr><td id='footer' colspan=2>
436 <span id='footer-msg'></span>
437 <input type='button' value='Save' id='save-button' onclick='save()'>
438 <input type='button' value='Cancel' id='cancel-button' onclick='javascript:reloadPage();'>
439 </td></tr>
440 </table>
441 </form>
442 <script type='text/javascript'>sg.setup();</script>
443 </body>
444 </html>