1 let libubus = require("ubus");
2 import { open, readfile } from "fs";
3 import { wdev_create, wdev_set_mesh_params, wdev_remove, is_equal, wdev_set_up, vlist_new, phy_open } from "common";
5 let ubus = libubus.connect();
8 wpas.data.iface_phy = {};
9 wpas.data.macaddr_list = {};
11 function iface_stop(iface)
13 let ifname = iface.config.iface;
18 delete wpas.data.iface_phy[ifname];
19 wpas.remove_iface(ifname);
21 iface.running = false;
24 function iface_start(phydev, iface, macaddr_list)
26 let phy = phydev.name;
31 let ifname = iface.config.iface;
33 for (let field in iface.config)
34 wdev_config[field] = iface.config[field];
35 if (!wdev_config.macaddr)
36 wdev_config.macaddr = phydev.macaddr_next();
38 wpas.data.iface_phy[ifname] = phy;
40 let ret = wdev_create(phy, ifname, wdev_config);
42 wpas.printf(`Failed to create device ${ifname}: ${ret}`);
43 wdev_set_up(ifname, true);
44 wpas.add_iface(iface.config);
48 function iface_cb(new_if, old_if)
50 if (old_if && new_if && is_equal(old_if.config, new_if.config)) {
51 new_if.running = old_if.running;
56 wpas.printf(`Update configuration for interface ${old_if.config.iface}`);
58 wpas.printf(`Remove interface ${old_if.config.iface}`);
64 function prepare_config(config)
66 config.config_data = readfile(config.config);
68 return { config: config };
71 function set_config(phy_name, config_list)
73 let phy = wpas.data.config[phy_name];
76 phy = vlist_new(iface_cb, false);
77 wpas.data.config[phy_name] = phy;
81 for (let config in config_list)
82 push(values, [ config.iface, prepare_config(config) ]);
87 function start_pending(phy_name)
89 let phy = wpas.data.config[phy_name];
90 let ubus = wpas.data.ubus;
92 if (!phy || !phy.data)
95 let phydev = phy_open(phy_name);
97 wpas.printf(`Could not open phy ${phy_name}`);
101 let macaddr_list = wpas.data.macaddr_list[phy_name];
102 phydev.macaddr_init(macaddr_list);
104 for (let ifname in phy.data)
105 iface_start(phydev, phy.data[ifname]);
114 call: function(req) {
115 if (!req.args.phy || req.args.stop == null)
116 return libubus.STATUS_INVALID_ARGUMENT;
118 let phy = wpas.data.config[req.args.phy];
120 return libubus.STATUS_NOT_FOUND;
124 for (let ifname in phy.data)
125 iface_stop(phy.data[ifname]);
127 start_pending(req.args.phy);
130 wpas.printf(`Error chaging state: ${e}\n${e.stacktrace[0].context}`);
131 return libubus.STATUS_INVALID_ARGUMENT;
136 phy_set_macaddr_list: {
141 call: function(req) {
142 let phy = req.args.phy;
144 return libubus.STATUS_INVALID_ARGUMENT;
146 wpas.data.macaddr_list[phy] = req.args.macaddr;
154 call: function(req) {
156 return libubus.STATUS_INVALID_ARGUMENT;
158 let phy = wpas.data.config[req.args.phy];
160 return libubus.STATUS_NOT_FOUND;
162 for (let ifname in phy.data) {
164 let iface = wpas.interfaces[ifname];
168 let status = iface.status();
172 if (status.state == "INTERFACE_DISABLED")
175 status.ifname = ifname;
182 return libubus.STATUS_NOT_FOUND;
191 call: function(req) {
193 return libubus.STATUS_INVALID_ARGUMENT;
195 wpas.printf(`Set new config for phy ${req.args.phy}`);
198 set_config(req.args.phy, req.args.config);
201 start_pending(req.args.phy);
203 wpas.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
204 return libubus.STATUS_INVALID_ARGUMENT;
221 call: function(req) {
222 if (!req.args.iface || !req.args.config)
223 return libubus.STATUS_INVALID_ARGUMENT;
225 if (wpas.add_iface(req.args) < 0)
226 return libubus.STATUS_INVALID_ARGUMENT;
237 call: function(req) {
239 return libubus.STATUS_INVALID_ARGUMENT;
241 wpas.remove_iface(req.args.iface);
247 wpas.data.ubus = ubus;
248 wpas.data.obj = ubus.publish("wpa_supplicant", main_obj);
249 wpas.udebug_set("wpa_supplicant", wpas.data.ubus);
251 function iface_event(type, name, data) {
252 let ubus = wpas.data.ubus;
256 wpas.data.obj.notify(`iface.${type}`, data, null, null, null, -1);
257 ubus.call("service", "event", { type: `wpa_supplicant.${name}.${type}`, data: {} });
260 function iface_hostapd_notify(phy, ifname, iface, state)
262 let ubus = wpas.data.ubus;
263 let status = iface.status();
264 let msg = { phy: phy };
268 case "AUTHENTICATING":
272 case "INTERFACE_DISABLED":
278 msg.frequency = status.frequency;
279 msg.sec_chan_offset = status.sec_chan_offset;
285 ubus.call("hostapd", "apsta_state", msg);
288 function iface_channel_switch(phy, ifname, iface, info)
294 csa_count: info.csa_count ? info.csa_count - 1 : 0,
295 frequency: info.frequency,
296 sec_chan_offset: info.sec_chan_offset,
298 ubus.call("hostapd", "apsta_state", msg);
302 shutdown: function() {
303 for (let phy in wpas.data.config)
305 wpas.ubus.disconnect();
307 iface_add: function(name, obj) {
308 iface_event("add", name);
310 iface_remove: function(name, obj) {
311 iface_event("remove", name);
313 state: function(ifname, iface, state) {
314 let phy = wpas.data.iface_phy[ifname];
316 wpas.printf(`no PHY for ifname ${ifname}`);
320 iface_hostapd_notify(phy, ifname, iface, state);
322 if (state != "COMPLETED")
325 let phy_data = wpas.data.config[phy];
329 let iface_data = phy_data.data[ifname];
333 let wdev_config = iface_data.config;
334 if (!wdev_config || wdev_config.mode != "mesh")
337 wdev_set_mesh_params(ifname, wdev_config);
339 event: function(ifname, iface, ev, info) {
340 let phy = wpas.data.iface_phy[ifname];
342 wpas.printf(`no PHY for ifname ${ifname}`);
346 if (ev == "CH_SWITCH_STARTED")
347 iface_channel_switch(phy, ifname, iface, info);