malta: Remove kernel 5.15 configuration
[openwrt/openwrt.git] / package / network / services / hostapd / files / wdev.uc
1 #!/usr/bin/env ucode
2 'use strict';
3 import { vlist_new, is_equal, wdev_create, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
4 import { readfile, writefile, basename, readlink, glob } from "fs";
5 let libubus = require("ubus");
6
7 let keep_devices = {};
8 let phy = shift(ARGV);
9 let command = shift(ARGV);
10 let phydev;
11
12 function iface_stop(wdev)
13 {
14 if (keep_devices[wdev.ifname])
15 return;
16
17 wdev_remove(wdev.ifname);
18 }
19
20 function iface_start(wdev)
21 {
22 let ifname = wdev.ifname;
23
24 if (readfile(`/sys/class/net/${ifname}/ifindex`)) {
25 wdev_set_up(ifname, false);
26 wdev_remove(ifname);
27 }
28 let wdev_config = {};
29 for (let key in wdev)
30 wdev_config[key] = wdev[key];
31 if (!wdev_config.macaddr && wdev.mode != "monitor")
32 wdev_config.macaddr = phydev.macaddr_next();
33 wdev_create(phy, ifname, wdev_config);
34 wdev_set_up(ifname, true);
35 if (wdev.freq)
36 system(`iw dev ${ifname} set freq ${wdev.freq} ${wdev.htmode}`);
37 if (wdev.mode == "adhoc") {
38 let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, wdev.htmode, "fixed-freq" ];
39 if (wdev.bssid)
40 push(cmd, wdev.bssid);
41 for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ])
42 if (wdev[key])
43 push(cmd, key, wdev[key]);
44 system(cmd);
45 } else if (wdev.mode == "mesh") {
46 let cmd = [ "iw", "dev", ifname, "mesh", "join", wdev.ssid, "freq", wdev.freq, wdev.htmode ];
47 for (let key in [ "mcast-rate", "beacon-interval" ])
48 if (wdev[key])
49 push(cmd, key, wdev[key]);
50 system(cmd);
51
52 wdev_set_mesh_params(ifname, wdev);
53 }
54 }
55
56 function iface_cb(new_if, old_if)
57 {
58 if (old_if && new_if && is_equal(old_if, new_if))
59 return;
60
61 if (old_if)
62 iface_stop(old_if);
63 if (new_if)
64 iface_start(new_if);
65 }
66
67 function drop_inactive(config)
68 {
69 for (let key in config) {
70 if (!readfile(`/sys/class/net/${key}/ifindex`))
71 delete config[key];
72 }
73 }
74
75 function add_ifname(config)
76 {
77 for (let key in config)
78 config[key].ifname = key;
79 }
80
81 function delete_ifname(config)
82 {
83 for (let key in config)
84 delete config[key].ifname;
85 }
86
87 function add_existing(phy, config)
88 {
89 let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`);
90 wdevs = map(wdevs, (arg) => basename(arg));
91 for (let wdev in wdevs) {
92 if (config[wdev])
93 continue;
94
95 if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy)
96 continue;
97
98 if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
99 config[wdev] = {};
100 }
101 }
102
103 function usage()
104 {
105 warn(`Usage: ${basename(sourcepath())} <phy> <command> [<arguments>]
106
107 Commands:
108 set_config <config> [<device]...] - set phy configuration
109 get_macaddr <id> - get phy MAC address for vif index <id>
110 `);
111 exit(1);
112 }
113
114 const commands = {
115 set_config: function(args) {
116 let statefile = `/var/run/wdev-${phy}.json`;
117
118 let new_config = shift(args);
119 for (let dev in ARGV)
120 keep_devices[dev] = true;
121
122 if (!new_config)
123 usage();
124
125 new_config = json(new_config);
126 if (!new_config) {
127 warn("Invalid configuration\n");
128 exit(1);
129 }
130
131 let old_config = readfile(statefile);
132 if (old_config)
133 old_config = json(old_config);
134
135 let config = vlist_new(iface_cb);
136 if (type(old_config) == "object")
137 config.data = old_config;
138
139 add_existing(phy, config.data);
140 add_ifname(config.data);
141 drop_inactive(config.data);
142
143 let ubus = libubus.connect();
144 let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phy });
145 let macaddr_list = [];
146 if (type(data) == "object" && data.macaddr)
147 macaddr_list = data.macaddr;
148 ubus.disconnect();
149 phydev.macaddr_init(macaddr_list);
150
151 add_ifname(new_config);
152 config.update(new_config);
153
154 drop_inactive(config.data);
155 delete_ifname(config.data);
156 writefile(statefile, sprintf("%J", config.data));
157 },
158 get_macaddr: function(args) {
159 let data = {};
160
161 for (let arg in args) {
162 arg = split(arg, "=", 2);
163 data[arg[0]] = arg[1];
164 }
165
166 let macaddr = phydev.macaddr_generate(data);
167 if (!macaddr) {
168 warn(`Could not get MAC address for phy ${phy}\n`);
169 exit(1);
170 }
171
172 print(macaddr + "\n");
173 },
174 };
175
176 if (!phy || !command | !commands[command])
177 usage();
178
179 phydev = phy_open(phy);
180 if (!phydev) {
181 warn(`PHY ${phy} does not exist\n`);
182 exit(1);
183 }
184
185 commands[command](ARGV);