|
1 /* Copyright 2012 Mozilla Foundation and Mozilla contributors |
|
2 * |
|
3 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 * you may not use this file except in compliance with the License. |
|
5 * You may obtain a copy of the License at |
|
6 * |
|
7 * http://www.apache.org/licenses/LICENSE-2.0 |
|
8 * |
|
9 * Unless required by applicable law or agreed to in writing, software |
|
10 * distributed under the License is distributed on an "AS IS" BASIS, |
|
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 * See the License for the specific language governing permissions and |
|
13 * limitations under the License. |
|
14 */ |
|
15 |
|
16 if (!this.ctypes) { |
|
17 // We're likely being loaded as a JSM. |
|
18 this.EXPORTED_SYMBOLS = [ "libcutils", "libnetutils", "netHelpers" ]; |
|
19 Components.utils.import("resource://gre/modules/ctypes.jsm"); |
|
20 } |
|
21 |
|
22 const SYSTEM_PROPERTY_KEY_MAX = 32; |
|
23 const SYSTEM_PROPERTY_VALUE_MAX = 92; |
|
24 |
|
25 // We leave this as 'undefined' instead of setting it to 'false'. That |
|
26 // way a file that includes us can have it defined already without us |
|
27 // overriding the value here. |
|
28 let DEBUG; |
|
29 |
|
30 /** |
|
31 * Expose some system-level functions. |
|
32 */ |
|
33 this.libcutils = (function() { |
|
34 let lib; |
|
35 try { |
|
36 lib = ctypes.open("libcutils.so"); |
|
37 } catch(ex) { |
|
38 // Return a fallback option in case libcutils.so isn't present (e.g. |
|
39 // when building Firefox with MOZ_B2G_RIL. |
|
40 if (DEBUG) { |
|
41 dump("Could not load libcutils.so. Using fake propdb.\n"); |
|
42 } |
|
43 let fake_propdb = Object.create(null); |
|
44 return { |
|
45 property_get: function(key, defaultValue) { |
|
46 if (key in fake_propdb) { |
|
47 return fake_propdb[key]; |
|
48 } |
|
49 return defaultValue === undefined ? null : defaultValue; |
|
50 }, |
|
51 property_set: function(key, value) { |
|
52 fake_propdb[key] = value; |
|
53 } |
|
54 }; |
|
55 } |
|
56 |
|
57 let c_property_get = lib.declare("property_get", ctypes.default_abi, |
|
58 ctypes.int, // return value: length |
|
59 ctypes.char.ptr, // key |
|
60 ctypes.char.ptr, // value |
|
61 ctypes.char.ptr); // default |
|
62 let c_property_set = lib.declare("property_set", ctypes.default_abi, |
|
63 ctypes.int, // return value: success |
|
64 ctypes.char.ptr, // key |
|
65 ctypes.char.ptr); // value |
|
66 let c_value_buf = ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)(); |
|
67 |
|
68 return { |
|
69 |
|
70 /** |
|
71 * Get a system property. |
|
72 * |
|
73 * @param key |
|
74 * Name of the property |
|
75 * @param defaultValue [optional] |
|
76 * Default value to return if the property isn't set (default: null) |
|
77 */ |
|
78 property_get: function(key, defaultValue) { |
|
79 if (defaultValue === undefined) { |
|
80 defaultValue = null; |
|
81 } |
|
82 c_property_get(key, c_value_buf, defaultValue); |
|
83 return c_value_buf.readString(); |
|
84 }, |
|
85 |
|
86 /** |
|
87 * Set a system property |
|
88 * |
|
89 * @param key |
|
90 * Name of the property |
|
91 * @param value |
|
92 * Value to set the property to. |
|
93 */ |
|
94 property_set: function(key, value) { |
|
95 let rv = c_property_set(key, value); |
|
96 if (rv) { |
|
97 throw Error('libcutils.property_set("' + key + '", "' + value + |
|
98 '") failed with error ' + rv); |
|
99 } |
|
100 } |
|
101 |
|
102 }; |
|
103 })(); |
|
104 |
|
105 /** |
|
106 * Network-related functions from libnetutils. |
|
107 */ |
|
108 this.libnetutils = (function() { |
|
109 let library; |
|
110 try { |
|
111 library = ctypes.open("libnetutils.so"); |
|
112 } catch(ex) { |
|
113 if (DEBUG) { |
|
114 dump("Could not load libnetutils.so!\n"); |
|
115 } |
|
116 // For now we just fake the ctypes library interfacer to return |
|
117 // no-op functions when library.declare() is called. |
|
118 library = { |
|
119 declare: function() { |
|
120 return function fake_libnetutils_function() {}; |
|
121 } |
|
122 }; |
|
123 } |
|
124 |
|
125 let iface = { |
|
126 ifc_enable: library.declare("ifc_enable", ctypes.default_abi, |
|
127 ctypes.int, |
|
128 ctypes.char.ptr), |
|
129 ifc_disable: library.declare("ifc_disable", ctypes.default_abi, |
|
130 ctypes.int, |
|
131 ctypes.char.ptr), |
|
132 ifc_add_host_route: library.declare("ifc_add_host_route", |
|
133 ctypes.default_abi, |
|
134 ctypes.int, |
|
135 ctypes.char.ptr, |
|
136 ctypes.int), |
|
137 ifc_remove_host_routes: library.declare("ifc_remove_host_routes", |
|
138 ctypes.default_abi, |
|
139 ctypes.int, |
|
140 ctypes.char.ptr), |
|
141 ifc_set_default_route: library.declare("ifc_set_default_route", |
|
142 ctypes.default_abi, |
|
143 ctypes.int, |
|
144 ctypes.char.ptr, |
|
145 ctypes.int), |
|
146 ifc_get_default_route: library.declare("ifc_get_default_route", |
|
147 ctypes.default_abi, |
|
148 ctypes.int, |
|
149 ctypes.char.ptr), |
|
150 ifc_remove_default_route: library.declare("ifc_remove_default_route", |
|
151 ctypes.default_abi, |
|
152 ctypes.int, |
|
153 ctypes.char.ptr), |
|
154 ifc_configure: library.declare("ifc_configure", ctypes.default_abi, |
|
155 ctypes.int, |
|
156 ctypes.char.ptr, |
|
157 ctypes.int, |
|
158 ctypes.int, |
|
159 ctypes.int, |
|
160 ctypes.int, |
|
161 ctypes.int), |
|
162 ifc_add_route: library.declare("ifc_add_route", ctypes.default_abi, |
|
163 ctypes.int, // return value |
|
164 ctypes.char.ptr, // ifname |
|
165 ctypes.char.ptr, // dst |
|
166 ctypes.int, // prefix_length |
|
167 ctypes.char.ptr), // gw |
|
168 ifc_remove_route: library.declare("ifc_remove_route", ctypes.default_abi, |
|
169 ctypes.int, // return value |
|
170 ctypes.char.ptr, // ifname |
|
171 ctypes.char.ptr, // dst |
|
172 ctypes.int, // prefix_length |
|
173 ctypes.char.ptr), // gw |
|
174 dhcp_stop: library.declare("dhcp_stop", ctypes.default_abi, |
|
175 ctypes.int, |
|
176 ctypes.char.ptr), |
|
177 dhcp_release_lease: library.declare("dhcp_release_lease", ctypes.default_abi, |
|
178 ctypes.int, |
|
179 ctypes.char.ptr), |
|
180 dhcp_get_errmsg: library.declare("dhcp_get_errmsg", ctypes.default_abi, |
|
181 ctypes.char.ptr), |
|
182 |
|
183 // Constants for ifc_reset_connections. |
|
184 // NOTE: Ignored in versions before ICS. |
|
185 RESET_IPV4_ADDRESSES: 0x01, |
|
186 RESET_IPV6_ADDRESSES: 0x02, |
|
187 }; |
|
188 |
|
189 iface.RESET_ALL_ADDRESSES = iface.RESET_IPV4_ADDRESSES | |
|
190 iface.RESET_IPV6_ADDRESSES; |
|
191 |
|
192 return iface; |
|
193 })(); |
|
194 |
|
195 /** |
|
196 * Helpers for conversions. |
|
197 */ |
|
198 this.netHelpers = { |
|
199 |
|
200 /** |
|
201 * Swap byte orders for 32-bit value |
|
202 */ |
|
203 swap32: function(n) { |
|
204 return (((n >> 24) & 0xFF) << 0) | |
|
205 (((n >> 16) & 0xFF) << 8) | |
|
206 (((n >> 8) & 0xFF) << 16) | |
|
207 (((n >> 0) & 0xFF) << 24); |
|
208 }, |
|
209 |
|
210 /** |
|
211 * Convert network byte order to host byte order |
|
212 * Note: Assume that the system is little endian |
|
213 */ |
|
214 ntohl: function(n) { |
|
215 return this.swap32(n); |
|
216 }, |
|
217 |
|
218 /** |
|
219 * Convert host byte order to network byte order |
|
220 * Note: Assume that the system is little endian |
|
221 */ |
|
222 htonl: function(n) { |
|
223 return this.swap32(n); |
|
224 }, |
|
225 |
|
226 /** |
|
227 * Convert integer representation of an IP address to the string |
|
228 * representation. |
|
229 * |
|
230 * @param ip |
|
231 * IP address in number format. |
|
232 */ |
|
233 ipToString: function(ip) { |
|
234 return ((ip >> 0) & 0xFF) + "." + |
|
235 ((ip >> 8) & 0xFF) + "." + |
|
236 ((ip >> 16) & 0xFF) + "." + |
|
237 ((ip >> 24) & 0xFF); |
|
238 }, |
|
239 |
|
240 /** |
|
241 * Convert string representation of an IP address to the integer |
|
242 * representation (network byte order). |
|
243 * |
|
244 * @param string |
|
245 * String containing the IP address. |
|
246 */ |
|
247 stringToIP: function(string) { |
|
248 if (!string) { |
|
249 return null; |
|
250 } |
|
251 let ip = 0; |
|
252 let start, end = -1; |
|
253 for (let i = 0; i < 4; i++) { |
|
254 start = end + 1; |
|
255 end = string.indexOf(".", start); |
|
256 if (end == -1) { |
|
257 end = string.length; |
|
258 } |
|
259 let num = parseInt(string.slice(start, end), 10); |
|
260 if (isNaN(num)) { |
|
261 return null; |
|
262 } |
|
263 ip |= num << (i * 8); |
|
264 } |
|
265 return ip; |
|
266 }, |
|
267 |
|
268 /** |
|
269 * Make a subnet mask. |
|
270 */ |
|
271 makeMask: function(len) { |
|
272 let mask = 0; |
|
273 for (let i = 0; i < len; ++i) { |
|
274 mask |= (0x80000000 >> i); |
|
275 } |
|
276 return this.ntohl(mask); |
|
277 }, |
|
278 |
|
279 /** |
|
280 * Get Mask length from given mask address |
|
281 */ |
|
282 getMaskLength: function(mask) { |
|
283 let len = 0; |
|
284 let netmask = this.ntohl(mask); |
|
285 while (netmask & 0x80000000) { |
|
286 len++; |
|
287 netmask = netmask << 1; |
|
288 } |
|
289 return len; |
|
290 } |
|
291 }; |