1 let libubus = require("ubus");
2 import { open, readfile } from "fs";
3 import { wdev_create, wdev_remove, is_equal, vlist_new } from "common";
5 let ubus = libubus.connect();
8 wpas.data.iface_phy = {};
10 function iface_stop(iface)
12 let ifname = iface.config.iface;
17 delete wpas.data.iface_phy[ifname];
18 wpas.remove_iface(ifname);
20 iface.running = false;
23 function iface_start(phy, iface)
28 let ifname = iface.config.iface;
30 wpas.data.iface_phy[ifname] = phy;
32 let ret = wdev_create(phy, ifname, iface.config);
34 wpas.printf(`Failed to create device ${ifname}: ${ret}`);
35 wpas.add_iface(iface.config);
39 function iface_cb(new_if, old_if)
41 if (old_if && new_if && is_equal(old_if.config, new_if.config)) {
42 new_if.running = old_if.running;
50 function prepare_config(config)
52 config.config_data = readfile(config.config);
54 return { config: config };
57 function set_config(phy_name, config_list)
59 let phy = wpas.data.config[phy_name];
62 phy = vlist_new(iface_cb, false);
63 wpas.data.config[phy_name] = phy;
67 for (let config in config_list)
68 push(values, [ config.iface, prepare_config(config) ]);
73 function start_pending(phy_name)
75 let phy = wpas.data.config[phy_name];
77 for (let ifname in phy.data)
78 iface_start(phy_name, phy.data[ifname]);
88 if (!req.args.phy || req.args.stop == null)
89 return libubus.STATUS_INVALID_ARGUMENT;
91 let phy = wpas.data.config[req.args.phy];
93 return libubus.STATUS_NOT_FOUND;
97 for (let ifname in phy.data)
98 iface_stop(phy.data[ifname]);
100 start_pending(req.args.phy);
103 wpas.printf(`Error chaging state: ${e}\n${e.stacktrace[0].context}`);
104 return libubus.STATUS_INVALID_ARGUMENT;
115 call: function(req) {
117 return libubus.STATUS_INVALID_ARGUMENT;
121 set_config(req.args.phy, req.args.config);
124 start_pending(req.args.phy);
126 wpas.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
127 return libubus.STATUS_INVALID_ARGUMENT;
144 call: function(req) {
145 if (!req.args.iface || !req.args.config)
146 return libubus.STATUS_INVALID_ARGUMENT;
148 if (wpas.add_iface(req.args) < 0)
149 return libubus.STATUS_INVALID_ARGUMENT;
160 call: function(req) {
162 return libubus.STATUS_INVALID_ARGUMENT;
164 wpas.remove_iface(req.args.iface);
170 wpas.data.ubus = ubus;
171 wpas.data.obj = ubus.publish("wpa_supplicant", main_obj);
173 function iface_event(type, name, data) {
174 let ubus = wpas.data.ubus;
178 wpas.data.obj.notify(`iface.${type}`, data, null, null, null, -1);
179 ubus.call("service", "event", { type: `wpa_supplicant.${name}.${type}`, data: {} });
182 function iface_hostapd_notify(phy, ifname, iface, state)
184 let ubus = wpas.data.ubus;
185 let status = iface.status();
186 let msg = { phy: phy };
190 case "AUTHENTICATING":
194 case "INTERFACE_DISABLED":
200 msg.frequency = status.frequency;
201 msg.sec_chan_offset = status.sec_chan_offset;
207 ubus.call("hostapd", "apsta_state", msg);
210 function iface_channel_switch(phy, ifname, iface, info)
216 csa_count: info.csa_count ? info.csa_count - 1 : 0,
217 frequency: info.frequency,
218 sec_chan_offset: info.sec_chan_offset,
220 ubus.call("hostapd", "apsta_state", msg);
224 shutdown: function() {
225 for (let phy in wpas.data.config)
227 wpas.ubus.disconnect();
229 iface_add: function(name, obj) {
230 iface_event("add", name);
232 iface_remove: function(name, obj) {
233 iface_event("remove", name);
235 state: function(ifname, iface, state) {
236 let phy = wpas.data.iface_phy[ifname];
238 wpas.printf(`no PHY for ifname ${ifname}`);
242 iface_hostapd_notify(phy, ifname, iface, state);
244 event: function(ifname, iface, ev, info) {
245 let phy = wpas.data.iface_phy[ifname];
247 wpas.printf(`no PHY for ifname ${ifname}`);
251 if (ev == "CH_SWITCH_STARTED")
252 iface_channel_switch(phy, ifname, iface, info);