|
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 "use strict"; |
|
8 |
|
9 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; |
|
10 |
|
11 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
12 Cu.import("resource://gre/modules/systemlibs.js"); |
|
13 |
|
14 XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService", |
|
15 "@mozilla.org/network/service;1", |
|
16 "nsINetworkService"); |
|
17 |
|
18 this.EXPORTED_SYMBOLS = ["WifiNetUtil"]; |
|
19 |
|
20 const DHCP_PROP = "init.svc.dhcpcd"; |
|
21 const DHCP = "dhcpcd"; |
|
22 const DEBUG = false; |
|
23 |
|
24 this.WifiNetUtil = function(controlMessage) { |
|
25 function debug(msg) { |
|
26 if (DEBUG) { |
|
27 dump('-------------- NetUtil: ' + msg); |
|
28 } |
|
29 } |
|
30 |
|
31 var util = {}; |
|
32 |
|
33 util.configureInterface = function(cfg, callback) { |
|
34 let message = { cmd: "ifc_configure", |
|
35 ifname: cfg.ifname, |
|
36 ipaddr: cfg.ipaddr, |
|
37 mask: cfg.mask, |
|
38 gateway: cfg.gateway, |
|
39 dns1: cfg.dns1, |
|
40 dns2: cfg.dns2 }; |
|
41 |
|
42 controlMessage(message, function(data) { |
|
43 callback(!data.status); |
|
44 }); |
|
45 }; |
|
46 |
|
47 util.runDhcp = function (ifname, callback) { |
|
48 controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) { |
|
49 var dhcpInfo = data.status ? null : data; |
|
50 util.runIpConfig(ifname, dhcpInfo, callback); |
|
51 }); |
|
52 }; |
|
53 |
|
54 util.stopDhcp = function (ifname, callback) { |
|
55 // This function does exactly what dhcp_stop does. Unforunately, if we call |
|
56 // this function twice before the previous callback is returned. We may block |
|
57 // our self waiting for the callback. It slows down the wifi startup procedure. |
|
58 // Therefore, we have to roll our own version here. |
|
59 let dhcpService = DHCP_PROP + "_" + ifname; |
|
60 let suffix = (ifname.substr(0, 3) === "p2p") ? "p2p" : ifname; |
|
61 let processName = DHCP + "_" + suffix; |
|
62 stopProcess(dhcpService, processName, callback); |
|
63 }; |
|
64 |
|
65 util.enableInterface = function (ifname, callback) { |
|
66 controlMessage({ cmd: "ifc_enable", ifname: ifname }, function (data) { |
|
67 callback(!data.status); |
|
68 }); |
|
69 }; |
|
70 |
|
71 util.disableInterface = function (ifname, callback) { |
|
72 controlMessage({ cmd: "ifc_disable", ifname: ifname }, function (data) { |
|
73 callback(!data.status); |
|
74 }); |
|
75 }; |
|
76 |
|
77 util.startDhcpServer = function (config, callback) { |
|
78 gNetworkService.setDhcpServer(true, config, function (error) { |
|
79 callback(!error); |
|
80 }); |
|
81 }; |
|
82 |
|
83 util.stopDhcpServer = function (callback) { |
|
84 gNetworkService.setDhcpServer(false, null, function (error) { |
|
85 callback(!error); |
|
86 }); |
|
87 }; |
|
88 |
|
89 util.addHostRoute = function (ifname, route, callback) { |
|
90 controlMessage({ cmd: "ifc_add_host_route", ifname: ifname, route: route }, function(data) { |
|
91 callback(!data.status); |
|
92 }); |
|
93 }; |
|
94 |
|
95 util.removeHostRoutes = function (ifname, callback) { |
|
96 controlMessage({ cmd: "ifc_remove_host_routes", ifname: ifname }, function(data) { |
|
97 callback(!data.status); |
|
98 }); |
|
99 }; |
|
100 |
|
101 util.setDefaultRoute = function (ifname, route, callback) { |
|
102 controlMessage({ cmd: "ifc_set_default_route", ifname: ifname, route: route }, function(data) { |
|
103 callback(!data.status); |
|
104 }); |
|
105 }; |
|
106 |
|
107 util.getDefaultRoute = function (ifname, callback) { |
|
108 controlMessage({ cmd: "ifc_get_default_route", ifname: ifname }, function(data) { |
|
109 callback(!data.route); |
|
110 }); |
|
111 }; |
|
112 |
|
113 util.removeDefaultRoute = function (ifname, callback) { |
|
114 controlMessage({ cmd: "ifc_remove_default_route", ifname: ifname }, function(data) { |
|
115 callback(!data.status); |
|
116 }); |
|
117 }; |
|
118 |
|
119 util.resetConnections = function (ifname, callback) { |
|
120 controlMessage({ cmd: "ifc_reset_connections", ifname: ifname }, function(data) { |
|
121 callback(!data.status); |
|
122 }); |
|
123 }; |
|
124 |
|
125 util.releaseDhcpLease = function (ifname, callback) { |
|
126 controlMessage({ cmd: "dhcp_release_lease", ifname: ifname }, function(data) { |
|
127 callback(!data.status); |
|
128 }); |
|
129 }; |
|
130 |
|
131 util.getDhcpError = function (callback) { |
|
132 controlMessage({ cmd: "dhcp_get_errmsg" }, function(data) { |
|
133 callback(data.error); |
|
134 }); |
|
135 }; |
|
136 |
|
137 util.runDhcpRenew = function (ifname, callback) { |
|
138 controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) { |
|
139 callback(data.status ? null : data); |
|
140 }); |
|
141 }; |
|
142 |
|
143 util.runIpConfig = function (name, data, callback) { |
|
144 if (!data) { |
|
145 debug("IP config failed to run"); |
|
146 callback({ info: data }); |
|
147 return; |
|
148 } |
|
149 |
|
150 setProperty("net." + name + ".dns1", ipToString(data.dns1), |
|
151 function(ok) { |
|
152 if (!ok) { |
|
153 debug("Unable to set net.<ifname>.dns1"); |
|
154 return; |
|
155 } |
|
156 setProperty("net." + name + ".dns2", ipToString(data.dns2), |
|
157 function(ok) { |
|
158 if (!ok) { |
|
159 debug("Unable to set net.<ifname>.dns2"); |
|
160 return; |
|
161 } |
|
162 setProperty("net." + name + ".gw", ipToString(data.gateway), |
|
163 function(ok) { |
|
164 if (!ok) { |
|
165 debug("Unable to set net.<ifname>.gw"); |
|
166 return; |
|
167 } |
|
168 callback({ info: data }); |
|
169 }); |
|
170 }); |
|
171 }); |
|
172 }; |
|
173 |
|
174 //-------------------------------------------------- |
|
175 // Helper functions. |
|
176 //-------------------------------------------------- |
|
177 |
|
178 function stopProcess(service, process, callback) { |
|
179 var count = 0; |
|
180 var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
|
181 function tick() { |
|
182 let result = libcutils.property_get(service); |
|
183 if (result === null) { |
|
184 callback(); |
|
185 return; |
|
186 } |
|
187 if (result === "stopped" || ++count >= 5) { |
|
188 // Either we succeeded or ran out of time. |
|
189 timer = null; |
|
190 callback(); |
|
191 return; |
|
192 } |
|
193 |
|
194 // Else it's still running, continue waiting. |
|
195 timer.initWithCallback(tick, 1000, Ci.nsITimer.TYPE_ONE_SHOT); |
|
196 } |
|
197 |
|
198 setProperty("ctl.stop", process, tick); |
|
199 } |
|
200 |
|
201 // Wrapper around libcutils.property_set that returns true if setting the |
|
202 // value was successful. |
|
203 // Note that the callback is not called asynchronously. |
|
204 function setProperty(key, value, callback) { |
|
205 let ok = true; |
|
206 try { |
|
207 libcutils.property_set(key, value); |
|
208 } catch(e) { |
|
209 ok = false; |
|
210 } |
|
211 callback(ok); |
|
212 } |
|
213 |
|
214 function ipToString(n) { |
|
215 return String((n >> 0) & 0xFF) + "." + |
|
216 ((n >> 8) & 0xFF) + "." + |
|
217 ((n >> 16) & 0xFF) + "." + |
|
218 ((n >> 24) & 0xFF); |
|
219 } |
|
220 |
|
221 return util; |
|
222 }; |