0eea2d5f194c10771111cf3dbbf76194c4a1fa1c
[plewww.git] / planetlab / nodes / interface.js
1 /* $Id$ */
2
3 /* using prototype.js */
4
5 ////////////////////
6 // basic IP arithmetic
7 /* a is assumed to be a 4-items array text.split('.') */
8 function arr_to_int (as) {
9   /*a=as.map(parseInt);*/
10   a=as.map( function (x) { return parseInt(x) & 0xff;} );
11   return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
12 }
13 function int_to_arr (n) {
14   var a=[];
15   a[0]=(n&0xff000000)>>>24;
16   a[1]=(n&0x00ff0000)>>>16;
17   a[2]=(n&0x0000ff00)>>>8;
18   a[3]=(n&0x000000ff)>>>0;
19   return a;
20 }
21
22 function int_to_bits (n) {
23   var a=[];
24   for (var i=0; i<32; i++) {
25     a[31-i]=n&1;
26     n=n>>>1;
27   }
28   return a;
29 }
30
31 function mask (masklen) {
32   return ( 0xffffffff<<(32-masklen));
33 }
34
35 // input is the user-typed text
36 // return the number of bits in the mask (like 24 for a /24) or -1 if the mask is wrong
37 function get_masklen (netmask) {
38   var a = netmask.split('.');
39   if ( IPCheckerAtom (netmask,'netmask')) return -1;
40   var n = arr_to_int (a);
41   var bits = int_to_bits (n);
42   var masklen=0;
43   while (bits[masklen] && masklen<32 ) masklen++;
44   // masklen holds the number of consecutive bits; just need to check
45   var n_mask = mask(masklen);
46   return (n == n_mask) ? masklen : -1;
47 }
48
49 // returns network and broadcast from ip and masklen
50 function get_derived (n,masklen) {
51   var n_mask = mask(masklen);
52   var r=[];
53   r[0]=int_to_arr(n&n_mask).join(".");
54   r[1]=int_to_arr(n|~n_mask).join(".");
55   return r;
56 }
57
58 function same_subnet (ip1,ip2,masklen) {
59   var n1=arr_to_int(ip1.split("."));
60   var n2=arr_to_int(ip2.split("."));
61   return (n1&mask(masklen)) == (n2 & mask(masklen));
62 }
63
64 //////////////////// basic chackers
65 function IPCheckerAtom (ip,id) {
66   if ( ! ip ) return "Empty field " + id;
67   ip_a = ip.split('.');
68   if ( ip_a.length != 4) return "Invalid IP (" + id + ") "+ ip;
69   for (var i=0; i<4; i++) if (ip_a[i]<0 || ip_a[i]>256) return "Invalid IP (" + id + ") "+ ip;
70   return "";
71 }
72   
73 function IPCheckerSilent (id) { return IPCheckerAtom ( $(id).value, id); }
74
75 function netmaskCheckerSilent (id) {
76   var netmask=$(id).value;
77   var check_ip = IPCheckerAtom (netmask,'netmask');
78   if (check_ip) return check_ip;
79   var masklen = get_masklen (netmask);
80   if (masklen <= 0) return "Invalid netmask " + netmask;
81   return "";
82 }
83
84 // focus on the field to check, other ones checked already
85 function subnetChecker(id, optional) {
86   var error= subnetCheckerSilent($(id).value);
87   if (error) {
88     Form.Element.focus($(id));
89     alert(error);
90   }
91 }
92
93 function subnetCheckerSilent (id, optional) {
94
95   var subnet=$(id).value;
96   // skip this field if optional
97   if (optional && (subnet=="")) return "";
98   var check_ip = IPCheckerAtom (subnet,id);
99   if (check_ip) return check_ip;
100
101   var masklen = get_masklen ($('netmask').value);
102   if (masklen < 0) return "Could not check " + id;
103
104   var ip=$('ip').value;
105
106   if ( ! same_subnet (ip,subnet,masklen) ) 
107     return id + ' ' + subnet + ' is not in the /' + masklen + ' subnet range';
108   
109   return "";
110 }
111
112 function macChecker(id, optional) {
113   var error= macCheckerSilent($(id).value);
114   if (error) {
115     Form.Element.focus($(id));
116     alert(error);
117   }
118 }
119
120 function macCheckerSilent(macAdd) {
121   var RegExPattern = /^[0-9a-fA-F:]+$/;
122   
123   if (!(macAdd.match(RegExPattern)) || macAdd.length != 17) {
124     return "Invalid MAC Address";
125   } else {
126     return "";
127   }
128 }
129
130 ////////////////////
131 // updates broadcast & network from IP and netmask, as long as they are reasonably set 
132 function networkHelper () {
133   var ip=$('ip').value;
134   var netmask=$('netmask').value;
135
136   /* don't trigger if the input does not make sense */
137   if (IPCheckerAtom (ip,'ip')) return;
138   if (IPCheckerAtom (netmask,'netmask')) return;
139   
140   /*check netmask*/
141   var masklen=get_masklen (netmask);
142   if (masklen <= 0) return;
143
144   var ip_a = ip.split('.');
145   var ip_n=arr_to_int(ip_a);
146   var derived = get_derived(ip_n,masklen);
147
148   $('network').value=derived[0];
149   $('broadcast').value=derived[1];
150 }
151
152 // disable/enable input fields according to the selected method
153 function updateMethodFields() {
154   var method=$('method');
155   var index = method.selectedIndex;
156   var selectedText = method[index].text;
157   var is_static = selectedText == 'Static';
158   var is_tap = selectedText == 'TUN/TAP';
159
160   $('netmask').disabled= !is_static;
161   $('network').disabled= !is_static;
162   $('gateway').disabled= !is_static && !is_tap;
163   $('broadcast').disabled= !is_static;
164   $('dns1').disabled= !is_static;
165   $('dns2').disabled= !is_static;
166 }
167
168 // check inputs and prevent submit in case s/t is wrong
169 function interfaceSubmit () {
170
171   var method=$('method');
172   var index = method.selectedIndex;
173   var selectedText = method[index].text;
174   var is_static = selectedText == 'Static';
175   var is_tap = selectedText == 'TUN/TAP';
176
177   var errors="";
178   var counter=0;
179   var error;
180   error = IPCheckerSilent ('ip'); if (error) errors += error + "\n" ;
181   if ( ! $('netmask').disabled ) { error = netmaskCheckerSilent ('netmask'); if (error) errors += error + "\n" ; }
182   if ( ! $('network').disabled ) { error = IPCheckerSilent ('network'); if (error) errors += error + "\n" ; }
183   if ( ! $('gateway').disabled ) { error = subnetCheckerSilent ('gateway',false); if (error) errors += error + "\n" ; }
184   if ( ! $('broadcast').disabled ) { error = subnetCheckerSilent ('broadcast',false); if (error) errors += error + "\n" ; }
185
186   if ( ! errors.length) {
187     return true;
188   } else {
189     alert("-- Cannot create interface --\n" + errors);
190     return false;
191   }
192 }
193
194