Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 */
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 }
22 const SYSTEM_PROPERTY_KEY_MAX = 32;
23 const SYSTEM_PROPERTY_VALUE_MAX = 92;
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;
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 }
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)();
68 return {
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 },
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 }
102 };
103 })();
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 }
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),
183 // Constants for ifc_reset_connections.
184 // NOTE: Ignored in versions before ICS.
185 RESET_IPV4_ADDRESSES: 0x01,
186 RESET_IPV6_ADDRESSES: 0x02,
187 };
189 iface.RESET_ALL_ADDRESSES = iface.RESET_IPV4_ADDRESSES |
190 iface.RESET_IPV6_ADDRESSES;
192 return iface;
193 })();
195 /**
196 * Helpers for conversions.
197 */
198 this.netHelpers = {
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 },
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 },
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 },
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 },
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 },
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 },
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 };