ramips: mt7620: Add support for the devolo WiFi Repeater ac (MT 2767, 2779)
[openwrt/openwrt.git] / package / network / services / hostapd / src / src / ap / ubus.c
1 /*
2 * hostapd / ubus support
3 * Copyright (c) 2013, Felix Fietkau <nbd@nbd.name>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10 #include "utils/common.h"
11 #include "utils/eloop.h"
12 #include "utils/wpabuf.h"
13 #include "common/ieee802_11_defs.h"
14 #include "common/hw_features_common.h"
15 #include "hostapd.h"
16 #include "neighbor_db.h"
17 #include "wps_hostapd.h"
18 #include "sta_info.h"
19 #include "ubus.h"
20 #include "ap_drv_ops.h"
21 #include "beacon.h"
22 #include "rrm.h"
23 #include "wnm_ap.h"
24 #include "taxonomy.h"
25 #include "airtime_policy.h"
26 #include "hw_features.h"
27
28 static struct ubus_context *ctx;
29 static struct blob_buf b;
30 static int ctx_ref;
31
32 static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj)
33 {
34 return container_of(obj, struct hostapd_data, ubus.obj);
35 }
36
37 struct ubus_banned_client {
38 struct avl_node avl;
39 u8 addr[ETH_ALEN];
40 };
41
42 static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
43 {
44 if (ubus_reconnect(ctx, NULL)) {
45 eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
46 return;
47 }
48
49 ubus_add_uloop(ctx);
50 }
51
52 static void hostapd_ubus_connection_lost(struct ubus_context *ctx)
53 {
54 uloop_fd_delete(&ctx->sock);
55 eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
56 }
57
58 static bool hostapd_ubus_init(void)
59 {
60 if (ctx)
61 return true;
62
63 eloop_add_uloop();
64 ctx = ubus_connect(NULL);
65 if (!ctx)
66 return false;
67
68 ctx->connection_lost = hostapd_ubus_connection_lost;
69 ubus_add_uloop(ctx);
70
71 return true;
72 }
73
74 static void hostapd_ubus_ref_inc(void)
75 {
76 ctx_ref++;
77 }
78
79 static void hostapd_ubus_ref_dec(void)
80 {
81 ctx_ref--;
82 if (!ctx)
83 return;
84
85 if (ctx_ref)
86 return;
87
88 uloop_fd_delete(&ctx->sock);
89 ubus_free(ctx);
90 ctx = NULL;
91 }
92
93 void hostapd_ubus_add_iface(struct hostapd_iface *iface)
94 {
95 if (!hostapd_ubus_init())
96 return;
97 }
98
99 void hostapd_ubus_free_iface(struct hostapd_iface *iface)
100 {
101 if (!ctx)
102 return;
103 }
104
105 static void hostapd_notify_ubus(struct ubus_object *obj, char *bssname, char *event)
106 {
107 char *event_type;
108
109 if (!ctx || !obj)
110 return;
111
112 if (asprintf(&event_type, "bss.%s", event) < 0)
113 return;
114
115 blob_buf_init(&b, 0);
116 blobmsg_add_string(&b, "name", bssname);
117 ubus_notify(ctx, obj, event_type, b.head, -1);
118 free(event_type);
119 }
120
121 static void
122 hostapd_bss_del_ban(void *eloop_data, void *user_ctx)
123 {
124 struct ubus_banned_client *ban = eloop_data;
125 struct hostapd_data *hapd = user_ctx;
126
127 avl_delete(&hapd->ubus.banned, &ban->avl);
128 free(ban);
129 }
130
131 static void
132 hostapd_bss_ban_client(struct hostapd_data *hapd, u8 *addr, int time)
133 {
134 struct ubus_banned_client *ban;
135
136 if (time < 0)
137 time = 0;
138
139 ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl);
140 if (!ban) {
141 if (!time)
142 return;
143
144 ban = os_zalloc(sizeof(*ban));
145 memcpy(ban->addr, addr, sizeof(ban->addr));
146 ban->avl.key = ban->addr;
147 avl_insert(&hapd->ubus.banned, &ban->avl);
148 } else {
149 eloop_cancel_timeout(hostapd_bss_del_ban, ban, hapd);
150 if (!time) {
151 hostapd_bss_del_ban(ban, hapd);
152 return;
153 }
154 }
155
156 eloop_register_timeout(0, time * 1000, hostapd_bss_del_ban, ban, hapd);
157 }
158
159 static int
160 hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
161 struct ubus_request_data *req, const char *method,
162 struct blob_attr *msg)
163 {
164 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
165
166 return hostapd_reload_config(hapd->iface);
167 }
168
169
170 static void
171 hostapd_parse_vht_map_blobmsg(uint16_t map)
172 {
173 char label[4];
174 int16_t val;
175 int i;
176
177 for (i = 0; i < 8; i++) {
178 snprintf(label, 4, "%dss", i + 1);
179
180 val = (map & (BIT(1) | BIT(0))) + 7;
181 blobmsg_add_u16(&b, label, val == 10 ? -1 : val);
182 map = map >> 2;
183 }
184 }
185
186 static void
187 hostapd_parse_vht_capab_blobmsg(struct ieee80211_vht_capabilities *vhtc)
188 {
189 void *supported_mcs;
190 void *map;
191 int i;
192
193 static const struct {
194 const char *name;
195 uint32_t flag;
196 } vht_capas[] = {
197 { "su_beamformee", VHT_CAP_SU_BEAMFORMEE_CAPABLE },
198 { "mu_beamformee", VHT_CAP_MU_BEAMFORMEE_CAPABLE },
199 };
200
201 for (i = 0; i < ARRAY_SIZE(vht_capas); i++)
202 blobmsg_add_u8(&b, vht_capas[i].name,
203 !!(vhtc->vht_capabilities_info & vht_capas[i].flag));
204
205 supported_mcs = blobmsg_open_table(&b, "mcs_map");
206
207 /* RX map */
208 map = blobmsg_open_table(&b, "rx");
209 hostapd_parse_vht_map_blobmsg(le_to_host16(vhtc->vht_supported_mcs_set.rx_map));
210 blobmsg_close_table(&b, map);
211
212 /* TX map */
213 map = blobmsg_open_table(&b, "tx");
214 hostapd_parse_vht_map_blobmsg(le_to_host16(vhtc->vht_supported_mcs_set.tx_map));
215 blobmsg_close_table(&b, map);
216
217 blobmsg_close_table(&b, supported_mcs);
218 }
219
220 static void
221 hostapd_parse_capab_blobmsg(struct sta_info *sta)
222 {
223 void *r, *v;
224
225 v = blobmsg_open_table(&b, "capabilities");
226
227 if (sta->vht_capabilities) {
228 r = blobmsg_open_table(&b, "vht");
229 hostapd_parse_vht_capab_blobmsg(sta->vht_capabilities);
230 blobmsg_close_table(&b, r);
231 }
232
233 /* ToDo: Add HT / HE capability parsing */
234
235 blobmsg_close_table(&b, v);
236 }
237
238 static int
239 hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
240 struct ubus_request_data *req, const char *method,
241 struct blob_attr *msg)
242 {
243 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
244 struct hostap_sta_driver_data sta_driver_data;
245 struct sta_info *sta;
246 void *list, *c;
247 char mac_buf[20];
248 static const struct {
249 const char *name;
250 uint32_t flag;
251 } sta_flags[] = {
252 { "auth", WLAN_STA_AUTH },
253 { "assoc", WLAN_STA_ASSOC },
254 { "authorized", WLAN_STA_AUTHORIZED },
255 { "preauth", WLAN_STA_PREAUTH },
256 { "wds", WLAN_STA_WDS },
257 { "wmm", WLAN_STA_WMM },
258 { "ht", WLAN_STA_HT },
259 { "vht", WLAN_STA_VHT },
260 { "he", WLAN_STA_HE },
261 { "wps", WLAN_STA_WPS },
262 { "mfp", WLAN_STA_MFP },
263 };
264
265 blob_buf_init(&b, 0);
266 blobmsg_add_u32(&b, "freq", hapd->iface->freq);
267 list = blobmsg_open_table(&b, "clients");
268 for (sta = hapd->sta_list; sta; sta = sta->next) {
269 void *r;
270 int i;
271
272 sprintf(mac_buf, MACSTR, MAC2STR(sta->addr));
273 c = blobmsg_open_table(&b, mac_buf);
274 for (i = 0; i < ARRAY_SIZE(sta_flags); i++)
275 blobmsg_add_u8(&b, sta_flags[i].name,
276 !!(sta->flags & sta_flags[i].flag));
277
278 #ifdef CONFIG_MBO
279 blobmsg_add_u8(&b, "mbo", !!(sta->cell_capa));
280 #endif
281
282 r = blobmsg_open_array(&b, "rrm");
283 for (i = 0; i < ARRAY_SIZE(sta->rrm_enabled_capa); i++)
284 blobmsg_add_u32(&b, "", sta->rrm_enabled_capa[i]);
285 blobmsg_close_array(&b, r);
286
287 r = blobmsg_open_array(&b, "extended_capabilities");
288 /* Check if client advertises extended capabilities */
289 if (sta->ext_capability && sta->ext_capability[0] > 0) {
290 for (i = 0; i < sta->ext_capability[0]; i++) {
291 blobmsg_add_u32(&b, "", sta->ext_capability[1 + i]);
292 }
293 }
294 blobmsg_close_array(&b, r);
295
296 blobmsg_add_u32(&b, "aid", sta->aid);
297 #ifdef CONFIG_TAXONOMY
298 r = blobmsg_alloc_string_buffer(&b, "signature", 1024);
299 if (retrieve_sta_taxonomy(hapd, sta, r, 1024) > 0)
300 blobmsg_add_string_buffer(&b);
301 #endif
302
303 /* Driver information */
304 if (hostapd_drv_read_sta_data(hapd, &sta_driver_data, sta->addr) >= 0) {
305 r = blobmsg_open_table(&b, "bytes");
306 blobmsg_add_u64(&b, "rx", sta_driver_data.rx_bytes);
307 blobmsg_add_u64(&b, "tx", sta_driver_data.tx_bytes);
308 blobmsg_close_table(&b, r);
309 r = blobmsg_open_table(&b, "airtime");
310 blobmsg_add_u64(&b, "rx", sta_driver_data.rx_airtime);
311 blobmsg_add_u64(&b, "tx", sta_driver_data.tx_airtime);
312 blobmsg_close_table(&b, r);
313 r = blobmsg_open_table(&b, "packets");
314 blobmsg_add_u32(&b, "rx", sta_driver_data.rx_packets);
315 blobmsg_add_u32(&b, "tx", sta_driver_data.tx_packets);
316 blobmsg_close_table(&b, r);
317 r = blobmsg_open_table(&b, "rate");
318 /* Rate in kbits */
319 blobmsg_add_u32(&b, "rx", sta_driver_data.current_rx_rate * 100);
320 blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100);
321 blobmsg_close_table(&b, r);
322 blobmsg_add_u32(&b, "signal", sta_driver_data.signal);
323 }
324
325 hostapd_parse_capab_blobmsg(sta);
326
327 blobmsg_close_table(&b, c);
328 }
329 blobmsg_close_array(&b, list);
330 ubus_send_reply(ctx, req, b.head);
331
332 return 0;
333 }
334
335 static int
336 hostapd_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj,
337 struct ubus_request_data *req, const char *method,
338 struct blob_attr *msg)
339 {
340 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
341
342 blob_buf_init(&b, 0);
343 blobmsg_add_u8(&b, "ht_supported", ht_supported(hapd->iface->hw_features));
344 blobmsg_add_u8(&b, "vht_supported", vht_supported(hapd->iface->hw_features));
345 ubus_send_reply(ctx, req, b.head);
346
347 return 0;
348 }
349
350 static int
351 hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
352 struct ubus_request_data *req, const char *method,
353 struct blob_attr *msg)
354 {
355 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
356 void *airtime_table, *dfs_table, *rrm_table, *wnm_table;
357 struct os_reltime now;
358 char ssid[SSID_MAX_LEN + 1];
359 char phy_name[17];
360 size_t ssid_len = SSID_MAX_LEN;
361 u8 channel = 0, op_class = 0;
362
363 if (hapd->conf->ssid.ssid_len < SSID_MAX_LEN)
364 ssid_len = hapd->conf->ssid.ssid_len;
365
366 ieee80211_freq_to_channel_ext(hapd->iface->freq,
367 hapd->iconf->secondary_channel,
368 hostapd_get_oper_chwidth(hapd->iconf),
369 &op_class, &channel);
370
371 blob_buf_init(&b, 0);
372 blobmsg_add_string(&b, "driver", hapd->driver->name);
373 blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state));
374 blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid));
375
376 memset(ssid, 0, SSID_MAX_LEN + 1);
377 memcpy(ssid, hapd->conf->ssid.ssid, ssid_len);
378 blobmsg_add_string(&b, "ssid", ssid);
379
380 blobmsg_add_u32(&b, "freq", hapd->iface->freq);
381 blobmsg_add_u32(&b, "channel", channel);
382 blobmsg_add_u32(&b, "op_class", op_class);
383 blobmsg_add_u32(&b, "beacon_interval", hapd->iconf->beacon_int);
384 #ifdef CONFIG_IEEE80211AX
385 blobmsg_add_u32(&b, "bss_color", hapd->iface->conf->he_op.he_bss_color_disabled ? -1 :
386 hapd->iface->conf->he_op.he_bss_color);
387 #else
388 blobmsg_add_u32(&b, "bss_color", -1);
389 #endif
390
391 snprintf(phy_name, 17, "%s", hapd->iface->phy);
392 blobmsg_add_string(&b, "phy", phy_name);
393
394 /* RRM */
395 rrm_table = blobmsg_open_table(&b, "rrm");
396 blobmsg_add_u64(&b, "neighbor_report_tx", hapd->openwrt_stats.rrm.neighbor_report_tx);
397 blobmsg_close_table(&b, rrm_table);
398
399 /* WNM */
400 wnm_table = blobmsg_open_table(&b, "wnm");
401 blobmsg_add_u64(&b, "bss_transition_query_rx", hapd->openwrt_stats.wnm.bss_transition_query_rx);
402 blobmsg_add_u64(&b, "bss_transition_request_tx", hapd->openwrt_stats.wnm.bss_transition_request_tx);
403 blobmsg_add_u64(&b, "bss_transition_response_rx", hapd->openwrt_stats.wnm.bss_transition_response_rx);
404 blobmsg_close_table(&b, wnm_table);
405
406 /* Airtime */
407 airtime_table = blobmsg_open_table(&b, "airtime");
408 blobmsg_add_u64(&b, "time", hapd->iface->last_channel_time);
409 blobmsg_add_u64(&b, "time_busy", hapd->iface->last_channel_time_busy);
410 blobmsg_add_u16(&b, "utilization", hapd->iface->channel_utilization);
411 blobmsg_close_table(&b, airtime_table);
412
413 /* DFS */
414 dfs_table = blobmsg_open_table(&b, "dfs");
415 blobmsg_add_u32(&b, "cac_seconds", hapd->iface->dfs_cac_ms / 1000);
416 blobmsg_add_u8(&b, "cac_active", !!(hapd->iface->cac_started));
417 os_reltime_age(&hapd->iface->dfs_cac_start, &now);
418 blobmsg_add_u32(&b, "cac_seconds_left",
419 hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0);
420 blobmsg_close_table(&b, dfs_table);
421
422 ubus_send_reply(ctx, req, b.head);
423
424 return 0;
425 }
426
427 enum {
428 NOTIFY_RESPONSE,
429 __NOTIFY_MAX
430 };
431
432 static const struct blobmsg_policy notify_policy[__NOTIFY_MAX] = {
433 [NOTIFY_RESPONSE] = { "notify_response", BLOBMSG_TYPE_INT32 },
434 };
435
436 static int
437 hostapd_notify_response(struct ubus_context *ctx, struct ubus_object *obj,
438 struct ubus_request_data *req, const char *method,
439 struct blob_attr *msg)
440 {
441 struct blob_attr *tb[__NOTIFY_MAX];
442 struct hostapd_data *hapd = get_hapd_from_object(obj);
443 struct wpabuf *elems;
444 const char *pos;
445 size_t len;
446
447 blobmsg_parse(notify_policy, __NOTIFY_MAX, tb,
448 blob_data(msg), blob_len(msg));
449
450 if (!tb[NOTIFY_RESPONSE])
451 return UBUS_STATUS_INVALID_ARGUMENT;
452
453 hapd->ubus.notify_response = blobmsg_get_u32(tb[NOTIFY_RESPONSE]);
454
455 return UBUS_STATUS_OK;
456 }
457
458 enum {
459 DEL_CLIENT_ADDR,
460 DEL_CLIENT_REASON,
461 DEL_CLIENT_DEAUTH,
462 DEL_CLIENT_BAN_TIME,
463 __DEL_CLIENT_MAX
464 };
465
466 static const struct blobmsg_policy del_policy[__DEL_CLIENT_MAX] = {
467 [DEL_CLIENT_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
468 [DEL_CLIENT_REASON] = { "reason", BLOBMSG_TYPE_INT32 },
469 [DEL_CLIENT_DEAUTH] = { "deauth", BLOBMSG_TYPE_INT8 },
470 [DEL_CLIENT_BAN_TIME] = { "ban_time", BLOBMSG_TYPE_INT32 },
471 };
472
473 static int
474 hostapd_bss_del_client(struct ubus_context *ctx, struct ubus_object *obj,
475 struct ubus_request_data *req, const char *method,
476 struct blob_attr *msg)
477 {
478 struct blob_attr *tb[__DEL_CLIENT_MAX];
479 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
480 struct sta_info *sta;
481 bool deauth = false;
482 int reason;
483 u8 addr[ETH_ALEN];
484
485 blobmsg_parse(del_policy, __DEL_CLIENT_MAX, tb, blob_data(msg), blob_len(msg));
486
487 if (!tb[DEL_CLIENT_ADDR])
488 return UBUS_STATUS_INVALID_ARGUMENT;
489
490 if (hwaddr_aton(blobmsg_data(tb[DEL_CLIENT_ADDR]), addr))
491 return UBUS_STATUS_INVALID_ARGUMENT;
492
493 if (tb[DEL_CLIENT_REASON])
494 reason = blobmsg_get_u32(tb[DEL_CLIENT_REASON]);
495
496 if (tb[DEL_CLIENT_DEAUTH])
497 deauth = blobmsg_get_bool(tb[DEL_CLIENT_DEAUTH]);
498
499 sta = ap_get_sta(hapd, addr);
500 if (sta) {
501 if (deauth) {
502 hostapd_drv_sta_deauth(hapd, addr, reason);
503 ap_sta_deauthenticate(hapd, sta, reason);
504 } else {
505 hostapd_drv_sta_disassoc(hapd, addr, reason);
506 ap_sta_disassociate(hapd, sta, reason);
507 }
508 }
509
510 if (tb[DEL_CLIENT_BAN_TIME])
511 hostapd_bss_ban_client(hapd, addr, blobmsg_get_u32(tb[DEL_CLIENT_BAN_TIME]));
512
513 return 0;
514 }
515
516 static void
517 blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const u8 *addr)
518 {
519 char *s;
520
521 s = blobmsg_alloc_string_buffer(buf, name, 20);
522 sprintf(s, MACSTR, MAC2STR(addr));
523 blobmsg_add_string_buffer(buf);
524 }
525
526 static int
527 hostapd_bss_list_bans(struct ubus_context *ctx, struct ubus_object *obj,
528 struct ubus_request_data *req, const char *method,
529 struct blob_attr *msg)
530 {
531 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
532 struct ubus_banned_client *ban;
533 void *c;
534
535 blob_buf_init(&b, 0);
536 c = blobmsg_open_array(&b, "clients");
537 avl_for_each_element(&hapd->ubus.banned, ban, avl)
538 blobmsg_add_macaddr(&b, NULL, ban->addr);
539 blobmsg_close_array(&b, c);
540 ubus_send_reply(ctx, req, b.head);
541
542 return 0;
543 }
544
545 #ifdef CONFIG_WPS
546 static int
547 hostapd_bss_wps_start(struct ubus_context *ctx, struct ubus_object *obj,
548 struct ubus_request_data *req, const char *method,
549 struct blob_attr *msg)
550 {
551 int rc;
552 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
553
554 rc = hostapd_wps_button_pushed(hapd, NULL);
555
556 if (rc != 0)
557 return UBUS_STATUS_NOT_SUPPORTED;
558
559 return 0;
560 }
561
562
563 static const char * pbc_status_enum_str(enum pbc_status status)
564 {
565 switch (status) {
566 case WPS_PBC_STATUS_DISABLE:
567 return "Disabled";
568 case WPS_PBC_STATUS_ACTIVE:
569 return "Active";
570 case WPS_PBC_STATUS_TIMEOUT:
571 return "Timed-out";
572 case WPS_PBC_STATUS_OVERLAP:
573 return "Overlap";
574 default:
575 return "Unknown";
576 }
577 }
578
579 static int
580 hostapd_bss_wps_status(struct ubus_context *ctx, struct ubus_object *obj,
581 struct ubus_request_data *req, const char *method,
582 struct blob_attr *msg)
583 {
584 int rc;
585 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
586
587 blob_buf_init(&b, 0);
588
589 blobmsg_add_string(&b, "pbc_status", pbc_status_enum_str(hapd->wps_stats.pbc_status));
590 blobmsg_add_string(&b, "last_wps_result",
591 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
592 "Success":
593 (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
594 "Failed" : "None")));
595
596 /* If status == Failure - Add possible Reasons */
597 if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
598 hapd->wps_stats.failure_reason > 0)
599 blobmsg_add_string(&b, "reason", wps_ei_str(hapd->wps_stats.failure_reason));
600
601 if (hapd->wps_stats.status)
602 blobmsg_printf(&b, "peer_address", MACSTR, MAC2STR(hapd->wps_stats.peer_addr));
603
604 ubus_send_reply(ctx, req, b.head);
605
606 return 0;
607 }
608
609 static int
610 hostapd_bss_wps_cancel(struct ubus_context *ctx, struct ubus_object *obj,
611 struct ubus_request_data *req, const char *method,
612 struct blob_attr *msg)
613 {
614 int rc;
615 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
616
617 rc = hostapd_wps_cancel(hapd);
618
619 if (rc != 0)
620 return UBUS_STATUS_NOT_SUPPORTED;
621
622 return 0;
623 }
624 #endif /* CONFIG_WPS */
625
626 static int
627 hostapd_bss_update_beacon(struct ubus_context *ctx, struct ubus_object *obj,
628 struct ubus_request_data *req, const char *method,
629 struct blob_attr *msg)
630 {
631 int rc;
632 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
633
634 rc = ieee802_11_set_beacon(hapd);
635
636 if (rc != 0)
637 return UBUS_STATUS_NOT_SUPPORTED;
638
639 return 0;
640 }
641
642 enum {
643 CONFIG_IFACE,
644 CONFIG_FILE,
645 __CONFIG_MAX
646 };
647
648 enum {
649 CSA_FREQ,
650 CSA_BCN_COUNT,
651 CSA_CENTER_FREQ1,
652 CSA_CENTER_FREQ2,
653 CSA_BANDWIDTH,
654 CSA_SEC_CHANNEL_OFFSET,
655 CSA_HT,
656 CSA_VHT,
657 CSA_HE,
658 CSA_BLOCK_TX,
659 CSA_FORCE,
660 __CSA_MAX
661 };
662
663 static const struct blobmsg_policy csa_policy[__CSA_MAX] = {
664 [CSA_FREQ] = { "freq", BLOBMSG_TYPE_INT32 },
665 [CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 },
666 [CSA_CENTER_FREQ1] = { "center_freq1", BLOBMSG_TYPE_INT32 },
667 [CSA_CENTER_FREQ2] = { "center_freq2", BLOBMSG_TYPE_INT32 },
668 [CSA_BANDWIDTH] = { "bandwidth", BLOBMSG_TYPE_INT32 },
669 [CSA_SEC_CHANNEL_OFFSET] = { "sec_channel_offset", BLOBMSG_TYPE_INT32 },
670 [CSA_HT] = { "ht", BLOBMSG_TYPE_BOOL },
671 [CSA_VHT] = { "vht", BLOBMSG_TYPE_BOOL },
672 [CSA_HE] = { "he", BLOBMSG_TYPE_BOOL },
673 [CSA_BLOCK_TX] = { "block_tx", BLOBMSG_TYPE_BOOL },
674 [CSA_FORCE] = { "force", BLOBMSG_TYPE_BOOL },
675 };
676
677
678 static void switch_chan_fallback_cb(void *eloop_data, void *user_ctx)
679 {
680 struct hostapd_iface *iface = eloop_data;
681 struct hostapd_freq_params *freq_params = user_ctx;
682
683 hostapd_switch_channel_fallback(iface, freq_params);
684 }
685
686 #ifdef NEED_AP_MLME
687 static int
688 hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj,
689 struct ubus_request_data *req, const char *method,
690 struct blob_attr *msg)
691 {
692 struct blob_attr *tb[__CSA_MAX];
693 struct hostapd_data *hapd = get_hapd_from_object(obj);
694 struct hostapd_config *iconf = hapd->iface->conf;
695 struct hostapd_freq_params *freq_params;
696 struct hostapd_hw_modes *mode = hapd->iface->current_mode;
697 struct csa_settings css = {
698 .freq_params = {
699 .ht_enabled = iconf->ieee80211n,
700 .vht_enabled = iconf->ieee80211ac,
701 .he_enabled = iconf->ieee80211ax,
702 .sec_channel_offset = iconf->secondary_channel,
703 }
704 };
705 u8 chwidth = hostapd_get_oper_chwidth(iconf);
706 u8 seg0 = 0, seg1 = 0;
707 int ret = UBUS_STATUS_OK;
708 int i;
709
710 blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg));
711
712 if (!tb[CSA_FREQ])
713 return UBUS_STATUS_INVALID_ARGUMENT;
714
715 switch (iconf->vht_oper_chwidth) {
716 case CHANWIDTH_USE_HT:
717 if (iconf->secondary_channel)
718 css.freq_params.bandwidth = 40;
719 else
720 css.freq_params.bandwidth = 20;
721 break;
722 case CHANWIDTH_160MHZ:
723 css.freq_params.bandwidth = 160;
724 break;
725 default:
726 css.freq_params.bandwidth = 80;
727 break;
728 }
729
730 css.freq_params.freq = blobmsg_get_u32(tb[CSA_FREQ]);
731
732 #define SET_CSA_SETTING(name, field, type) \
733 do { \
734 if (tb[name]) \
735 css.field = blobmsg_get_ ## type(tb[name]); \
736 } while(0)
737
738 SET_CSA_SETTING(CSA_BCN_COUNT, cs_count, u32);
739 SET_CSA_SETTING(CSA_CENTER_FREQ1, freq_params.center_freq1, u32);
740 SET_CSA_SETTING(CSA_CENTER_FREQ2, freq_params.center_freq2, u32);
741 SET_CSA_SETTING(CSA_BANDWIDTH, freq_params.bandwidth, u32);
742 SET_CSA_SETTING(CSA_SEC_CHANNEL_OFFSET, freq_params.sec_channel_offset, u32);
743 SET_CSA_SETTING(CSA_HT, freq_params.ht_enabled, bool);
744 SET_CSA_SETTING(CSA_VHT, freq_params.vht_enabled, bool);
745 SET_CSA_SETTING(CSA_HE, freq_params.he_enabled, bool);
746 SET_CSA_SETTING(CSA_BLOCK_TX, block_tx, bool);
747
748 css.freq_params.channel = hostapd_hw_get_channel(hapd, css.freq_params.freq);
749 if (!css.freq_params.channel)
750 return UBUS_STATUS_NOT_SUPPORTED;
751
752 switch (css.freq_params.bandwidth) {
753 case 160:
754 chwidth = CHANWIDTH_160MHZ;
755 break;
756 case 80:
757 chwidth = css.freq_params.center_freq2 ? CHANWIDTH_80P80MHZ : CHANWIDTH_80MHZ;
758 break;
759 default:
760 chwidth = CHANWIDTH_USE_HT;
761 break;
762 }
763
764 hostapd_set_freq_params(&css.freq_params, iconf->hw_mode,
765 css.freq_params.freq,
766 css.freq_params.channel, iconf->enable_edmg,
767 iconf->edmg_channel,
768 css.freq_params.ht_enabled,
769 css.freq_params.vht_enabled,
770 css.freq_params.he_enabled,
771 css.freq_params.eht_enabled,
772 css.freq_params.sec_channel_offset,
773 chwidth, seg0, seg1,
774 iconf->vht_capab,
775 mode ? &mode->he_capab[IEEE80211_MODE_AP] :
776 NULL,
777 mode ? &mode->eht_capab[IEEE80211_MODE_AP] :
778 NULL,
779 hostapd_get_punct_bitmap(hapd));
780
781 for (i = 0; i < hapd->iface->num_bss; i++) {
782 struct hostapd_data *bss = hapd->iface->bss[i];
783
784 if (hostapd_switch_channel(bss, &css) != 0)
785 ret = UBUS_STATUS_NOT_SUPPORTED;
786 }
787
788 if (!ret || !tb[CSA_FORCE] || !blobmsg_get_bool(tb[CSA_FORCE]))
789 return ret;
790
791 freq_params = malloc(sizeof(*freq_params));
792 memcpy(freq_params, &css.freq_params, sizeof(*freq_params));
793 eloop_register_timeout(0, 1, switch_chan_fallback_cb,
794 hapd->iface, freq_params);
795
796 return 0;
797 #undef SET_CSA_SETTING
798 }
799 #endif
800
801 enum {
802 VENDOR_ELEMENTS,
803 __VENDOR_ELEMENTS_MAX
804 };
805
806 static const struct blobmsg_policy ve_policy[__VENDOR_ELEMENTS_MAX] = {
807 /* vendor elements are provided as hex-string */
808 [VENDOR_ELEMENTS] = { "vendor_elements", BLOBMSG_TYPE_STRING },
809 };
810
811 static int
812 hostapd_vendor_elements(struct ubus_context *ctx, struct ubus_object *obj,
813 struct ubus_request_data *req, const char *method,
814 struct blob_attr *msg)
815 {
816 struct blob_attr *tb[__VENDOR_ELEMENTS_MAX];
817 struct hostapd_data *hapd = get_hapd_from_object(obj);
818 struct hostapd_bss_config *bss = hapd->conf;
819 struct wpabuf *elems;
820 const char *pos;
821 size_t len;
822
823 blobmsg_parse(ve_policy, __VENDOR_ELEMENTS_MAX, tb,
824 blob_data(msg), blob_len(msg));
825
826 if (!tb[VENDOR_ELEMENTS])
827 return UBUS_STATUS_INVALID_ARGUMENT;
828
829 pos = blobmsg_data(tb[VENDOR_ELEMENTS]);
830 len = os_strlen(pos);
831 if (len & 0x01)
832 return UBUS_STATUS_INVALID_ARGUMENT;
833
834 len /= 2;
835 if (len == 0) {
836 wpabuf_free(bss->vendor_elements);
837 bss->vendor_elements = NULL;
838 return 0;
839 }
840
841 elems = wpabuf_alloc(len);
842 if (elems == NULL)
843 return 1;
844
845 if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
846 wpabuf_free(elems);
847 return UBUS_STATUS_INVALID_ARGUMENT;
848 }
849
850 wpabuf_free(bss->vendor_elements);
851 bss->vendor_elements = elems;
852
853 /* update beacons if vendor elements were set successfully */
854 if (ieee802_11_update_beacons(hapd->iface) != 0)
855 return UBUS_STATUS_NOT_SUPPORTED;
856 return UBUS_STATUS_OK;
857 }
858
859 static void
860 hostapd_rrm_print_nr(struct hostapd_neighbor_entry *nr)
861 {
862 const u8 *data;
863 char *str;
864 int len;
865
866 blobmsg_printf(&b, "", MACSTR, MAC2STR(nr->bssid));
867
868 str = blobmsg_alloc_string_buffer(&b, "", nr->ssid.ssid_len + 1);
869 memcpy(str, nr->ssid.ssid, nr->ssid.ssid_len);
870 str[nr->ssid.ssid_len] = 0;
871 blobmsg_add_string_buffer(&b);
872
873 len = wpabuf_len(nr->nr);
874 str = blobmsg_alloc_string_buffer(&b, "", 2 * len + 1);
875 wpa_snprintf_hex(str, 2 * len + 1, wpabuf_head_u8(nr->nr), len);
876 blobmsg_add_string_buffer(&b);
877 }
878
879 enum {
880 BSS_MGMT_EN_NEIGHBOR,
881 BSS_MGMT_EN_BEACON,
882 BSS_MGMT_EN_LINK_MEASUREMENT,
883 #ifdef CONFIG_WNM_AP
884 BSS_MGMT_EN_BSS_TRANSITION,
885 #endif
886 __BSS_MGMT_EN_MAX
887 };
888
889 static bool
890 __hostapd_bss_mgmt_enable_f(struct hostapd_data *hapd, int flag)
891 {
892 struct hostapd_bss_config *bss = hapd->conf;
893 uint32_t flags;
894
895 switch (flag) {
896 case BSS_MGMT_EN_NEIGHBOR:
897 if (bss->radio_measurements[0] &
898 WLAN_RRM_CAPS_NEIGHBOR_REPORT)
899 return false;
900
901 bss->radio_measurements[0] |=
902 WLAN_RRM_CAPS_NEIGHBOR_REPORT;
903 hostapd_neighbor_set_own_report(hapd);
904 return true;
905 case BSS_MGMT_EN_BEACON:
906 flags = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
907 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
908 WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
909
910 if (bss->radio_measurements[0] & flags == flags)
911 return false;
912
913 bss->radio_measurements[0] |= (u8) flags;
914 return true;
915 case BSS_MGMT_EN_LINK_MEASUREMENT:
916 flags = WLAN_RRM_CAPS_LINK_MEASUREMENT;
917
918 if (bss->radio_measurements[0] & flags == flags)
919 return false;
920
921 bss->radio_measurements[0] |= (u8) flags;
922 return true;
923 #ifdef CONFIG_WNM_AP
924 case BSS_MGMT_EN_BSS_TRANSITION:
925 if (bss->bss_transition)
926 return false;
927
928 bss->bss_transition = 1;
929 return true;
930 #endif
931 }
932 }
933
934 static void
935 __hostapd_bss_mgmt_enable(struct hostapd_data *hapd, uint32_t flags)
936 {
937 bool update = false;
938 int i;
939
940 for (i = 0; i < __BSS_MGMT_EN_MAX; i++) {
941 if (!(flags & (1 << i)))
942 continue;
943
944 update |= __hostapd_bss_mgmt_enable_f(hapd, i);
945 }
946
947 if (update)
948 ieee802_11_update_beacons(hapd->iface);
949 }
950
951
952 static const struct blobmsg_policy bss_mgmt_enable_policy[__BSS_MGMT_EN_MAX] = {
953 [BSS_MGMT_EN_NEIGHBOR] = { "neighbor_report", BLOBMSG_TYPE_BOOL },
954 [BSS_MGMT_EN_BEACON] = { "beacon_report", BLOBMSG_TYPE_BOOL },
955 [BSS_MGMT_EN_LINK_MEASUREMENT] = { "link_measurement", BLOBMSG_TYPE_BOOL },
956 #ifdef CONFIG_WNM_AP
957 [BSS_MGMT_EN_BSS_TRANSITION] = { "bss_transition", BLOBMSG_TYPE_BOOL },
958 #endif
959 };
960
961 static int
962 hostapd_bss_mgmt_enable(struct ubus_context *ctx, struct ubus_object *obj,
963 struct ubus_request_data *req, const char *method,
964 struct blob_attr *msg)
965
966 {
967 struct hostapd_data *hapd = get_hapd_from_object(obj);
968 struct blob_attr *tb[__BSS_MGMT_EN_MAX];
969 struct blob_attr *cur;
970 uint32_t flags = 0;
971 int i;
972 bool neigh = false, beacon = false;
973
974 blobmsg_parse(bss_mgmt_enable_policy, __BSS_MGMT_EN_MAX, tb, blob_data(msg), blob_len(msg));
975
976 for (i = 0; i < ARRAY_SIZE(tb); i++) {
977 if (!tb[i] || !blobmsg_get_bool(tb[i]))
978 continue;
979
980 flags |= (1 << i);
981 }
982
983 __hostapd_bss_mgmt_enable(hapd, flags);
984
985 return 0;
986 }
987
988
989 static void
990 hostapd_rrm_nr_enable(struct hostapd_data *hapd)
991 {
992 __hostapd_bss_mgmt_enable(hapd, 1 << BSS_MGMT_EN_NEIGHBOR);
993 }
994
995 static int
996 hostapd_rrm_nr_get_own(struct ubus_context *ctx, struct ubus_object *obj,
997 struct ubus_request_data *req, const char *method,
998 struct blob_attr *msg)
999 {
1000 struct hostapd_data *hapd = get_hapd_from_object(obj);
1001 struct hostapd_neighbor_entry *nr;
1002 void *c;
1003
1004 hostapd_rrm_nr_enable(hapd);
1005
1006 nr = hostapd_neighbor_get(hapd, hapd->own_addr, NULL);
1007 if (!nr)
1008 return UBUS_STATUS_NOT_FOUND;
1009
1010 blob_buf_init(&b, 0);
1011
1012 c = blobmsg_open_array(&b, "value");
1013 hostapd_rrm_print_nr(nr);
1014 blobmsg_close_array(&b, c);
1015
1016 ubus_send_reply(ctx, req, b.head);
1017
1018 return 0;
1019 }
1020
1021 static int
1022 hostapd_rrm_nr_list(struct ubus_context *ctx, struct ubus_object *obj,
1023 struct ubus_request_data *req, const char *method,
1024 struct blob_attr *msg)
1025 {
1026 struct hostapd_data *hapd = get_hapd_from_object(obj);
1027 struct hostapd_neighbor_entry *nr;
1028 void *c;
1029
1030 hostapd_rrm_nr_enable(hapd);
1031 blob_buf_init(&b, 0);
1032
1033 c = blobmsg_open_array(&b, "list");
1034 dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list) {
1035 void *cur;
1036
1037 if (!memcmp(nr->bssid, hapd->own_addr, ETH_ALEN))
1038 continue;
1039
1040 cur = blobmsg_open_array(&b, NULL);
1041 hostapd_rrm_print_nr(nr);
1042 blobmsg_close_array(&b, cur);
1043 }
1044 blobmsg_close_array(&b, c);
1045
1046 ubus_send_reply(ctx, req, b.head);
1047
1048 return 0;
1049 }
1050
1051 enum {
1052 NR_SET_LIST,
1053 __NR_SET_LIST_MAX
1054 };
1055
1056 static const struct blobmsg_policy nr_set_policy[__NR_SET_LIST_MAX] = {
1057 [NR_SET_LIST] = { "list", BLOBMSG_TYPE_ARRAY },
1058 };
1059
1060
1061 static void
1062 hostapd_rrm_nr_clear(struct hostapd_data *hapd)
1063 {
1064 struct hostapd_neighbor_entry *nr;
1065
1066 restart:
1067 dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list) {
1068 if (!memcmp(nr->bssid, hapd->own_addr, ETH_ALEN))
1069 continue;
1070
1071 hostapd_neighbor_remove(hapd, nr->bssid, &nr->ssid);
1072 goto restart;
1073 }
1074 }
1075
1076 static int
1077 hostapd_rrm_nr_set(struct ubus_context *ctx, struct ubus_object *obj,
1078 struct ubus_request_data *req, const char *method,
1079 struct blob_attr *msg)
1080 {
1081 static const struct blobmsg_policy nr_e_policy[] = {
1082 { .type = BLOBMSG_TYPE_STRING },
1083 { .type = BLOBMSG_TYPE_STRING },
1084 { .type = BLOBMSG_TYPE_STRING },
1085 };
1086 struct hostapd_data *hapd = get_hapd_from_object(obj);
1087 struct blob_attr *tb_l[__NR_SET_LIST_MAX];
1088 struct blob_attr *tb[ARRAY_SIZE(nr_e_policy)];
1089 struct blob_attr *cur;
1090 int rem;
1091
1092 hostapd_rrm_nr_enable(hapd);
1093
1094 blobmsg_parse(nr_set_policy, __NR_SET_LIST_MAX, tb_l, blob_data(msg), blob_len(msg));
1095 if (!tb_l[NR_SET_LIST])
1096 return UBUS_STATUS_INVALID_ARGUMENT;
1097
1098 hostapd_rrm_nr_clear(hapd);
1099 blobmsg_for_each_attr(cur, tb_l[NR_SET_LIST], rem) {
1100 struct wpa_ssid_value ssid;
1101 struct wpabuf *data;
1102 u8 bssid[ETH_ALEN];
1103 char *s, *nr_s;
1104
1105 blobmsg_parse_array(nr_e_policy, ARRAY_SIZE(nr_e_policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
1106 if (!tb[0] || !tb[1] || !tb[2])
1107 goto invalid;
1108
1109 /* Neighbor Report binary */
1110 nr_s = blobmsg_get_string(tb[2]);
1111 data = wpabuf_parse_bin(nr_s);
1112 if (!data)
1113 goto invalid;
1114
1115 /* BSSID */
1116 s = blobmsg_get_string(tb[0]);
1117 if (strlen(s) == 0) {
1118 /* Copy BSSID from neighbor report */
1119 if (hwaddr_compact_aton(nr_s, bssid))
1120 goto invalid;
1121 } else if (hwaddr_aton(s, bssid)) {
1122 goto invalid;
1123 }
1124
1125 /* SSID */
1126 s = blobmsg_get_string(tb[1]);
1127 if (strlen(s) == 0) {
1128 /* Copy SSID from hostapd BSS conf */
1129 memcpy(&ssid, &hapd->conf->ssid, sizeof(ssid));
1130 } else {
1131 ssid.ssid_len = strlen(s);
1132 if (ssid.ssid_len > sizeof(ssid.ssid))
1133 goto invalid;
1134
1135 memcpy(&ssid, s, ssid.ssid_len);
1136 }
1137
1138 hostapd_neighbor_set(hapd, bssid, &ssid, data, NULL, NULL, 0, 0);
1139 wpabuf_free(data);
1140 continue;
1141
1142 invalid:
1143 return UBUS_STATUS_INVALID_ARGUMENT;
1144 }
1145
1146 return 0;
1147 }
1148
1149 enum {
1150 BEACON_REQ_ADDR,
1151 BEACON_REQ_MODE,
1152 BEACON_REQ_OP_CLASS,
1153 BEACON_REQ_CHANNEL,
1154 BEACON_REQ_DURATION,
1155 BEACON_REQ_BSSID,
1156 BEACON_REQ_SSID,
1157 __BEACON_REQ_MAX,
1158 };
1159
1160 static const struct blobmsg_policy beacon_req_policy[__BEACON_REQ_MAX] = {
1161 [BEACON_REQ_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
1162 [BEACON_REQ_OP_CLASS] { "op_class", BLOBMSG_TYPE_INT32 },
1163 [BEACON_REQ_CHANNEL] { "channel", BLOBMSG_TYPE_INT32 },
1164 [BEACON_REQ_DURATION] { "duration", BLOBMSG_TYPE_INT32 },
1165 [BEACON_REQ_MODE] { "mode", BLOBMSG_TYPE_INT32 },
1166 [BEACON_REQ_BSSID] { "bssid", BLOBMSG_TYPE_STRING },
1167 [BEACON_REQ_SSID] { "ssid", BLOBMSG_TYPE_STRING },
1168 };
1169
1170 static int
1171 hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj,
1172 struct ubus_request_data *ureq, const char *method,
1173 struct blob_attr *msg)
1174 {
1175 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1176 struct blob_attr *tb[__BEACON_REQ_MAX];
1177 struct blob_attr *cur;
1178 struct wpabuf *req;
1179 u8 bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1180 u8 addr[ETH_ALEN];
1181 int mode, rem, ret;
1182 int buf_len = 13;
1183
1184 blobmsg_parse(beacon_req_policy, __BEACON_REQ_MAX, tb, blob_data(msg), blob_len(msg));
1185
1186 if (!tb[BEACON_REQ_ADDR] || !tb[BEACON_REQ_MODE] || !tb[BEACON_REQ_DURATION] ||
1187 !tb[BEACON_REQ_OP_CLASS] || !tb[BEACON_REQ_CHANNEL])
1188 return UBUS_STATUS_INVALID_ARGUMENT;
1189
1190 if (tb[BEACON_REQ_SSID])
1191 buf_len += blobmsg_data_len(tb[BEACON_REQ_SSID]) + 2 - 1;
1192
1193 mode = blobmsg_get_u32(tb[BEACON_REQ_MODE]);
1194 if (hwaddr_aton(blobmsg_data(tb[BEACON_REQ_ADDR]), addr))
1195 return UBUS_STATUS_INVALID_ARGUMENT;
1196
1197 if (tb[BEACON_REQ_BSSID] &&
1198 hwaddr_aton(blobmsg_data(tb[BEACON_REQ_BSSID]), bssid))
1199 return UBUS_STATUS_INVALID_ARGUMENT;
1200
1201 req = wpabuf_alloc(buf_len);
1202 if (!req)
1203 return UBUS_STATUS_UNKNOWN_ERROR;
1204
1205 /* 1: regulatory class */
1206 wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_OP_CLASS]));
1207
1208 /* 2: channel number */
1209 wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_CHANNEL]));
1210
1211 /* 3-4: randomization interval */
1212 wpabuf_put_le16(req, 0);
1213
1214 /* 5-6: duration */
1215 wpabuf_put_le16(req, blobmsg_get_u32(tb[BEACON_REQ_DURATION]));
1216
1217 /* 7: mode */
1218 wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_MODE]));
1219
1220 /* 8-13: BSSID */
1221 wpabuf_put_data(req, bssid, ETH_ALEN);
1222
1223 if ((cur = tb[BEACON_REQ_SSID]) != NULL) {
1224 wpabuf_put_u8(req, WLAN_EID_SSID);
1225 wpabuf_put_u8(req, blobmsg_data_len(cur) - 1);
1226 wpabuf_put_data(req, blobmsg_data(cur), blobmsg_data_len(cur) - 1);
1227 }
1228
1229 ret = hostapd_send_beacon_req(hapd, addr, 0, req);
1230 if (ret < 0)
1231 return -ret;
1232
1233 return 0;
1234 }
1235
1236 enum {
1237 LM_REQ_ADDR,
1238 LM_REQ_TX_POWER_USED,
1239 LM_REQ_TX_POWER_MAX,
1240 __LM_REQ_MAX,
1241 };
1242
1243 static const struct blobmsg_policy lm_req_policy[__LM_REQ_MAX] = {
1244 [LM_REQ_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
1245 [LM_REQ_TX_POWER_USED] = { "tx-power-used", BLOBMSG_TYPE_INT32 },
1246 [LM_REQ_TX_POWER_MAX] = { "tx-power-max", BLOBMSG_TYPE_INT32 },
1247 };
1248
1249 static int
1250 hostapd_rrm_lm_req(struct ubus_context *ctx, struct ubus_object *obj,
1251 struct ubus_request_data *ureq, const char *method,
1252 struct blob_attr *msg)
1253 {
1254 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1255 struct blob_attr *tb[__LM_REQ_MAX];
1256 struct wpabuf *buf;
1257 u8 addr[ETH_ALEN];
1258 int ret;
1259 int8_t txp_used, txp_max;
1260
1261 txp_used = 0;
1262 txp_max = 0;
1263
1264 blobmsg_parse(lm_req_policy, __LM_REQ_MAX, tb, blob_data(msg), blob_len(msg));
1265
1266 if (!tb[LM_REQ_ADDR])
1267 return UBUS_STATUS_INVALID_ARGUMENT;
1268
1269 if (tb[LM_REQ_TX_POWER_USED])
1270 txp_used = (int8_t) blobmsg_get_u32(tb[LM_REQ_TX_POWER_USED]);
1271
1272 if (tb[LM_REQ_TX_POWER_MAX])
1273 txp_max = (int8_t) blobmsg_get_u32(tb[LM_REQ_TX_POWER_MAX]);
1274
1275 if (hwaddr_aton(blobmsg_data(tb[LM_REQ_ADDR]), addr))
1276 return UBUS_STATUS_INVALID_ARGUMENT;
1277
1278 buf = wpabuf_alloc(5);
1279 if (!buf)
1280 return UBUS_STATUS_UNKNOWN_ERROR;
1281
1282 wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
1283 wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REQUEST);
1284 wpabuf_put_u8(buf, 1);
1285 /* TX-Power used */
1286 wpabuf_put_u8(buf, txp_used);
1287 /* Max TX Power */
1288 wpabuf_put_u8(buf, txp_max);
1289
1290 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
1291 wpabuf_head(buf), wpabuf_len(buf));
1292
1293 wpabuf_free(buf);
1294 if (ret < 0)
1295 return -ret;
1296
1297 return 0;
1298 }
1299
1300
1301 void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len)
1302 {
1303 const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) data;
1304 const u8 *pos, *end;
1305 u8 token;
1306
1307 end = data + len;
1308 token = mgmt->u.action.u.rrm.dialog_token;
1309 pos = mgmt->u.action.u.rrm.variable;
1310
1311 if (end - pos < 8)
1312 return;
1313
1314 if (!hapd->ubus.obj.has_subscribers)
1315 return;
1316
1317 blob_buf_init(&b, 0);
1318 blobmsg_add_macaddr(&b, "address", mgmt->sa);
1319 blobmsg_add_u16(&b, "dialog-token", token);
1320 blobmsg_add_u16(&b, "rx-antenna-id", pos[4]);
1321 blobmsg_add_u16(&b, "tx-antenna-id", pos[5]);
1322 blobmsg_add_u16(&b, "rcpi", pos[6]);
1323 blobmsg_add_u16(&b, "rsni", pos[7]);
1324
1325 ubus_notify(ctx, &hapd->ubus.obj, "link-measurement-report", b.head, -1);
1326 }
1327
1328
1329 #ifdef CONFIG_WNM_AP
1330
1331 static int
1332 hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, bool abridged,
1333 u16 disassoc_timer, u8 validity_period, u8 dialog_token,
1334 struct blob_attr *neighbors, u8 mbo_reason, u8 cell_pref, u8 reassoc_delay)
1335 {
1336 struct blob_attr *cur;
1337 struct sta_info *sta;
1338 int nr_len = 0;
1339 int rem;
1340 u8 *nr = NULL;
1341 u8 req_mode = 0;
1342 u8 mbo[10];
1343 size_t mbo_len = 0;
1344
1345 sta = ap_get_sta(hapd, addr);
1346 if (!sta)
1347 return UBUS_STATUS_NOT_FOUND;
1348
1349 if (neighbors) {
1350 u8 *nr_cur;
1351
1352 if (blobmsg_check_array(neighbors,
1353 BLOBMSG_TYPE_STRING) < 0)
1354 return UBUS_STATUS_INVALID_ARGUMENT;
1355
1356 blobmsg_for_each_attr(cur, neighbors, rem) {
1357 int len = strlen(blobmsg_get_string(cur));
1358
1359 if (len % 2)
1360 return UBUS_STATUS_INVALID_ARGUMENT;
1361
1362 nr_len += (len / 2) + 2;
1363 }
1364
1365 if (nr_len) {
1366 nr = os_zalloc(nr_len);
1367 if (!nr)
1368 return UBUS_STATUS_UNKNOWN_ERROR;
1369 }
1370
1371 nr_cur = nr;
1372 blobmsg_for_each_attr(cur, neighbors, rem) {
1373 int len = strlen(blobmsg_get_string(cur)) / 2;
1374
1375 *nr_cur++ = WLAN_EID_NEIGHBOR_REPORT;
1376 *nr_cur++ = (u8) len;
1377 if (hexstr2bin(blobmsg_data(cur), nr_cur, len)) {
1378 free(nr);
1379 return UBUS_STATUS_INVALID_ARGUMENT;
1380 }
1381
1382 nr_cur += len;
1383 }
1384 }
1385
1386 if (nr)
1387 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
1388
1389 if (abridged)
1390 req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
1391
1392 if (disassoc_imminent)
1393 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
1394
1395 #ifdef CONFIG_MBO
1396 u8 *mbo_pos = mbo;
1397
1398 if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP)
1399 return UBUS_STATUS_INVALID_ARGUMENT;
1400
1401 if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255)
1402 return UBUS_STATUS_INVALID_ARGUMENT;
1403
1404 if (reassoc_delay > 65535 || (reassoc_delay && !disassoc_imminent))
1405 return UBUS_STATUS_INVALID_ARGUMENT;
1406
1407 *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
1408 *mbo_pos++ = 1;
1409 *mbo_pos++ = mbo_reason;
1410 *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
1411 *mbo_pos++ = 1;
1412 *mbo_pos++ = cell_pref;
1413
1414 if (reassoc_delay) {
1415 *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
1416 *mbo_pos++ = 2;
1417 WPA_PUT_LE16(mbo_pos, reassoc_delay);
1418 mbo_pos += 2;
1419 }
1420
1421 mbo_len = mbo_pos - mbo;
1422 #endif
1423
1424 if (wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, validity_period, NULL,
1425 dialog_token, NULL, nr, nr_len, mbo_len ? mbo : NULL, mbo_len))
1426 return UBUS_STATUS_UNKNOWN_ERROR;
1427
1428 return 0;
1429 }
1430
1431 enum {
1432 BSS_TR_ADDR,
1433 BSS_TR_DA_IMMINENT,
1434 BSS_TR_DA_TIMER,
1435 BSS_TR_VALID_PERIOD,
1436 BSS_TR_NEIGHBORS,
1437 BSS_TR_ABRIDGED,
1438 BSS_TR_DIALOG_TOKEN,
1439 #ifdef CONFIG_MBO
1440 BSS_TR_MBO_REASON,
1441 BSS_TR_CELL_PREF,
1442 BSS_TR_REASSOC_DELAY,
1443 #endif
1444 __BSS_TR_DISASSOC_MAX
1445 };
1446
1447 static const struct blobmsg_policy bss_tr_policy[__BSS_TR_DISASSOC_MAX] = {
1448 [BSS_TR_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
1449 [BSS_TR_DA_IMMINENT] = { "disassociation_imminent", BLOBMSG_TYPE_BOOL },
1450 [BSS_TR_DA_TIMER] = { "disassociation_timer", BLOBMSG_TYPE_INT32 },
1451 [BSS_TR_VALID_PERIOD] = { "validity_period", BLOBMSG_TYPE_INT32 },
1452 [BSS_TR_NEIGHBORS] = { "neighbors", BLOBMSG_TYPE_ARRAY },
1453 [BSS_TR_ABRIDGED] = { "abridged", BLOBMSG_TYPE_BOOL },
1454 [BSS_TR_DIALOG_TOKEN] = { "dialog_token", BLOBMSG_TYPE_INT32 },
1455 #ifdef CONFIG_MBO
1456 [BSS_TR_MBO_REASON] = { "mbo_reason", BLOBMSG_TYPE_INT32 },
1457 [BSS_TR_CELL_PREF] = { "cell_pref", BLOBMSG_TYPE_INT32 },
1458 [BSS_TR_REASSOC_DELAY] = { "reassoc_delay", BLOBMSG_TYPE_INT32 },
1459 #endif
1460 };
1461
1462 static int
1463 hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj,
1464 struct ubus_request_data *ureq, const char *method,
1465 struct blob_attr *msg)
1466 {
1467 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1468 struct blob_attr *tb[__BSS_TR_DISASSOC_MAX];
1469 struct sta_info *sta;
1470 u32 da_timer = 0;
1471 u32 valid_period = 0;
1472 u8 addr[ETH_ALEN];
1473 u32 dialog_token = 1;
1474 bool abridged;
1475 bool da_imminent;
1476 u8 mbo_reason;
1477 u8 cell_pref;
1478 u8 reassoc_delay;
1479
1480 blobmsg_parse(bss_tr_policy, __BSS_TR_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
1481
1482 if (!tb[BSS_TR_ADDR])
1483 return UBUS_STATUS_INVALID_ARGUMENT;
1484
1485 if (hwaddr_aton(blobmsg_data(tb[BSS_TR_ADDR]), addr))
1486 return UBUS_STATUS_INVALID_ARGUMENT;
1487
1488 if (tb[BSS_TR_DA_TIMER])
1489 da_timer = blobmsg_get_u32(tb[BSS_TR_DA_TIMER]);
1490
1491 if (tb[BSS_TR_VALID_PERIOD])
1492 valid_period = blobmsg_get_u32(tb[BSS_TR_VALID_PERIOD]);
1493
1494 if (tb[BSS_TR_DIALOG_TOKEN])
1495 dialog_token = blobmsg_get_u32(tb[BSS_TR_DIALOG_TOKEN]);
1496
1497 da_imminent = !!(tb[BSS_TR_DA_IMMINENT] && blobmsg_get_bool(tb[BSS_TR_DA_IMMINENT]));
1498 abridged = !!(tb[BSS_TR_ABRIDGED] && blobmsg_get_bool(tb[BSS_TR_ABRIDGED]));
1499
1500 #ifdef CONFIG_MBO
1501 if (tb[BSS_TR_MBO_REASON])
1502 mbo_reason = blobmsg_get_u32(tb[BSS_TR_MBO_REASON]);
1503
1504 if (tb[BSS_TR_CELL_PREF])
1505 cell_pref = blobmsg_get_u32(tb[BSS_TR_CELL_PREF]);
1506
1507 if (tb[BSS_TR_REASSOC_DELAY])
1508 reassoc_delay = blobmsg_get_u32(tb[BSS_TR_REASSOC_DELAY]);
1509 #endif
1510
1511 return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period,
1512 dialog_token, tb[BSS_TR_NEIGHBORS], mbo_reason, cell_pref, reassoc_delay);
1513 }
1514 #endif
1515
1516 #ifdef CONFIG_AIRTIME_POLICY
1517 enum {
1518 UPDATE_AIRTIME_STA,
1519 UPDATE_AIRTIME_WEIGHT,
1520 __UPDATE_AIRTIME_MAX,
1521 };
1522
1523
1524 static const struct blobmsg_policy airtime_policy[__UPDATE_AIRTIME_MAX] = {
1525 [UPDATE_AIRTIME_STA] = { "sta", BLOBMSG_TYPE_STRING },
1526 [UPDATE_AIRTIME_WEIGHT] = { "weight", BLOBMSG_TYPE_INT32 },
1527 };
1528
1529 static int
1530 hostapd_bss_update_airtime(struct ubus_context *ctx, struct ubus_object *obj,
1531 struct ubus_request_data *ureq, const char *method,
1532 struct blob_attr *msg)
1533 {
1534 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1535 struct blob_attr *tb[__UPDATE_AIRTIME_MAX];
1536 struct sta_info *sta = NULL;
1537 u8 addr[ETH_ALEN];
1538 int weight;
1539
1540 blobmsg_parse(airtime_policy, __UPDATE_AIRTIME_MAX, tb, blob_data(msg), blob_len(msg));
1541
1542 if (!tb[UPDATE_AIRTIME_WEIGHT])
1543 return UBUS_STATUS_INVALID_ARGUMENT;
1544
1545 weight = blobmsg_get_u32(tb[UPDATE_AIRTIME_WEIGHT]);
1546
1547 if (!tb[UPDATE_AIRTIME_STA]) {
1548 if (!weight)
1549 return UBUS_STATUS_INVALID_ARGUMENT;
1550
1551 hapd->conf->airtime_weight = weight;
1552 return 0;
1553 }
1554
1555 if (hwaddr_aton(blobmsg_data(tb[UPDATE_AIRTIME_STA]), addr))
1556 return UBUS_STATUS_INVALID_ARGUMENT;
1557
1558 sta = ap_get_sta(hapd, addr);
1559 if (!sta)
1560 return UBUS_STATUS_NOT_FOUND;
1561
1562 sta->dyn_airtime_weight = weight;
1563 airtime_policy_new_sta(hapd, sta);
1564
1565 return 0;
1566 }
1567 #endif
1568
1569 #ifdef CONFIG_TAXONOMY
1570 static const struct blobmsg_policy addr_policy[] = {
1571 { "address", BLOBMSG_TYPE_STRING }
1572 };
1573
1574 static bool
1575 hostapd_add_b64_data(const char *name, const struct wpabuf *buf)
1576 {
1577 char *str;
1578
1579 if (!buf)
1580 return false;
1581
1582 str = blobmsg_alloc_string_buffer(&b, name, B64_ENCODE_LEN(wpabuf_len(buf)));
1583 b64_encode(wpabuf_head(buf), wpabuf_len(buf), str, B64_ENCODE_LEN(wpabuf_len(buf)));
1584 blobmsg_add_string_buffer(&b);
1585
1586 return true;
1587 }
1588
1589 static int
1590 hostapd_bss_get_sta_ies(struct ubus_context *ctx, struct ubus_object *obj,
1591 struct ubus_request_data *req, const char *method,
1592 struct blob_attr *msg)
1593 {
1594 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1595 struct blob_attr *tb;
1596 struct sta_info *sta;
1597 u8 addr[ETH_ALEN];
1598
1599 blobmsg_parse(addr_policy, 1, &tb, blobmsg_data(msg), blobmsg_len(msg));
1600
1601 if (!tb || hwaddr_aton(blobmsg_data(tb), addr))
1602 return UBUS_STATUS_INVALID_ARGUMENT;
1603
1604 sta = ap_get_sta(hapd, addr);
1605 if (!sta || (!sta->probe_ie_taxonomy && !sta->assoc_ie_taxonomy))
1606 return UBUS_STATUS_NOT_FOUND;
1607
1608 blob_buf_init(&b, 0);
1609 hostapd_add_b64_data("probe_ie", sta->probe_ie_taxonomy);
1610 hostapd_add_b64_data("assoc_ie", sta->assoc_ie_taxonomy);
1611 ubus_send_reply(ctx, req, b.head);
1612
1613 return 0;
1614 }
1615 #endif
1616
1617
1618 static const struct ubus_method bss_methods[] = {
1619 UBUS_METHOD_NOARG("reload", hostapd_bss_reload),
1620 UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients),
1621 #ifdef CONFIG_TAXONOMY
1622 UBUS_METHOD("get_sta_ies", hostapd_bss_get_sta_ies, addr_policy),
1623 #endif
1624 UBUS_METHOD_NOARG("get_status", hostapd_bss_get_status),
1625 UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy),
1626 #ifdef CONFIG_AIRTIME_POLICY
1627 UBUS_METHOD("update_airtime", hostapd_bss_update_airtime, airtime_policy),
1628 #endif
1629 UBUS_METHOD_NOARG("list_bans", hostapd_bss_list_bans),
1630 #ifdef CONFIG_WPS
1631 UBUS_METHOD_NOARG("wps_start", hostapd_bss_wps_start),
1632 UBUS_METHOD_NOARG("wps_status", hostapd_bss_wps_status),
1633 UBUS_METHOD_NOARG("wps_cancel", hostapd_bss_wps_cancel),
1634 #endif
1635 UBUS_METHOD_NOARG("update_beacon", hostapd_bss_update_beacon),
1636 UBUS_METHOD_NOARG("get_features", hostapd_bss_get_features),
1637 #ifdef NEED_AP_MLME
1638 UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy),
1639 #endif
1640 UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy),
1641 UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy),
1642 UBUS_METHOD("bss_mgmt_enable", hostapd_bss_mgmt_enable, bss_mgmt_enable_policy),
1643 UBUS_METHOD_NOARG("rrm_nr_get_own", hostapd_rrm_nr_get_own),
1644 UBUS_METHOD_NOARG("rrm_nr_list", hostapd_rrm_nr_list),
1645 UBUS_METHOD("rrm_nr_set", hostapd_rrm_nr_set, nr_set_policy),
1646 UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy),
1647 UBUS_METHOD("link_measurement_req", hostapd_rrm_lm_req, lm_req_policy),
1648 #ifdef CONFIG_WNM_AP
1649 UBUS_METHOD("bss_transition_request", hostapd_bss_transition_request, bss_tr_policy),
1650 #endif
1651 };
1652
1653 static struct ubus_object_type bss_object_type =
1654 UBUS_OBJECT_TYPE("hostapd_bss", bss_methods);
1655
1656 static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr)
1657 {
1658 return memcmp(k1, k2, ETH_ALEN);
1659 }
1660
1661 static int
1662 hostapd_wired_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
1663 struct ubus_request_data *req, const char *method,
1664 struct blob_attr *msg)
1665 {
1666 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1667 struct hostap_sta_driver_data sta_driver_data;
1668 struct sta_info *sta;
1669 void *list, *c;
1670 char mac_buf[20];
1671 static const struct {
1672 const char *name;
1673 uint32_t flag;
1674 } sta_flags[] = {
1675 { "authorized", WLAN_STA_AUTHORIZED },
1676 };
1677
1678 blob_buf_init(&b, 0);
1679 list = blobmsg_open_table(&b, "clients");
1680 for (sta = hapd->sta_list; sta; sta = sta->next) {
1681 void *r;
1682 int i;
1683
1684 sprintf(mac_buf, MACSTR, MAC2STR(sta->addr));
1685 c = blobmsg_open_table(&b, mac_buf);
1686 for (i = 0; i < ARRAY_SIZE(sta_flags); i++)
1687 blobmsg_add_u8(&b, sta_flags[i].name,
1688 !!(sta->flags & sta_flags[i].flag));
1689
1690 blobmsg_close_table(&b, c);
1691 }
1692 blobmsg_close_array(&b, list);
1693 ubus_send_reply(ctx, req, b.head);
1694
1695 return 0;
1696 }
1697
1698 static int
1699 hostapd_wired_get_status(struct ubus_context *ctx, struct ubus_object *obj,
1700 struct ubus_request_data *req, const char *method,
1701 struct blob_attr *msg)
1702 {
1703 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1704 char iface_name[17];
1705
1706 blob_buf_init(&b, 0);
1707 blobmsg_add_string(&b, "driver", hapd->driver->name);
1708 blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state));
1709
1710 snprintf(iface_name, 17, "%s", hapd->iface->phy);
1711 blobmsg_add_string(&b, "iface", iface_name);
1712
1713 ubus_send_reply(ctx, req, b.head);
1714
1715 return 0;
1716 }
1717
1718 static int
1719 hostapd_wired_del_clients(struct ubus_context *ctx, struct ubus_object *obj,
1720 struct ubus_request_data *req, const char *method,
1721 struct blob_attr *msg)
1722 {
1723 struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
1724
1725 hostapd_free_stas(hapd);
1726
1727 return 0;
1728 }
1729
1730 static const struct ubus_method wired_methods[] = {
1731 UBUS_METHOD_NOARG("reload", hostapd_bss_reload),
1732 UBUS_METHOD_NOARG("get_clients", hostapd_wired_get_clients),
1733 UBUS_METHOD_NOARG("del_clients", hostapd_wired_del_clients),
1734 UBUS_METHOD_NOARG("get_status", hostapd_wired_get_status),
1735 };
1736
1737 static struct ubus_object_type wired_object_type =
1738 UBUS_OBJECT_TYPE("hostapd_wired", wired_methods);
1739
1740 void hostapd_ubus_add_bss(struct hostapd_data *hapd)
1741 {
1742 struct ubus_object *obj = &hapd->ubus.obj;
1743 char *name;
1744 int ret;
1745
1746 #ifdef CONFIG_MESH
1747 if (hapd->conf->mesh & MESH_ENABLED)
1748 return;
1749 #endif
1750
1751 if (!hostapd_ubus_init())
1752 return;
1753
1754 if (asprintf(&name, "hostapd.%s", hapd->conf->iface) < 0)
1755 return;
1756
1757 avl_init(&hapd->ubus.banned, avl_compare_macaddr, false, NULL);
1758 obj->name = name;
1759 if (!strcmp(hapd->driver->name, "wired")) {
1760 obj->type = &wired_object_type;
1761 obj->methods = wired_object_type.methods;
1762 obj->n_methods = wired_object_type.n_methods;
1763 } else {
1764 obj->type = &bss_object_type;
1765 obj->methods = bss_object_type.methods;
1766 obj->n_methods = bss_object_type.n_methods;
1767 }
1768 ret = ubus_add_object(ctx, obj);
1769 hostapd_ubus_ref_inc();
1770 }
1771
1772 void hostapd_ubus_free_bss(struct hostapd_data *hapd)
1773 {
1774 struct ubus_object *obj = &hapd->ubus.obj;
1775 char *name = (char *) obj->name;
1776
1777 #ifdef CONFIG_MESH
1778 if (hapd->conf->mesh & MESH_ENABLED)
1779 return;
1780 #endif
1781
1782 if (!ctx)
1783 return;
1784
1785 if (obj->id) {
1786 ubus_remove_object(ctx, obj);
1787 hostapd_ubus_ref_dec();
1788 }
1789
1790 free(name);
1791 }
1792
1793 static void
1794 hostapd_ubus_vlan_action(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
1795 const char *action)
1796 {
1797 struct vlan_description *desc = &vlan->vlan_desc;
1798 void *c;
1799 int i;
1800
1801 if (!hapd->ubus.obj.has_subscribers)
1802 return;
1803
1804 blob_buf_init(&b, 0);
1805 blobmsg_add_string(&b, "ifname", vlan->ifname);
1806 blobmsg_add_string(&b, "bridge", vlan->bridge);
1807 blobmsg_add_u32(&b, "vlan_id", vlan->vlan_id);
1808
1809 if (desc->notempty) {
1810 blobmsg_add_u32(&b, "untagged", desc->untagged);
1811 c = blobmsg_open_array(&b, "tagged");
1812 for (i = 0; i < ARRAY_SIZE(desc->tagged) && desc->tagged[i]; i++)
1813 blobmsg_add_u32(&b, "", desc->tagged[i]);
1814 blobmsg_close_array(&b, c);
1815 }
1816
1817 ubus_notify(ctx, &hapd->ubus.obj, action, b.head, -1);
1818 }
1819
1820 void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
1821 {
1822 hostapd_ubus_vlan_action(hapd, vlan, "vlan_add");
1823 }
1824
1825 void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
1826 {
1827 hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove");
1828 }
1829
1830 struct ubus_event_req {
1831 struct ubus_notify_request nreq;
1832 int resp;
1833 };
1834
1835 static void
1836 ubus_event_cb(struct ubus_notify_request *req, int idx, int ret)
1837 {
1838 struct ubus_event_req *ureq = container_of(req, struct ubus_event_req, nreq);
1839
1840 ureq->resp = ret;
1841 }
1842
1843 int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req)
1844 {
1845 struct ubus_banned_client *ban;
1846 const char *types[HOSTAPD_UBUS_TYPE_MAX] = {
1847 [HOSTAPD_UBUS_PROBE_REQ] = "probe",
1848 [HOSTAPD_UBUS_AUTH_REQ] = "auth",
1849 [HOSTAPD_UBUS_ASSOC_REQ] = "assoc",
1850 };
1851 const char *type = "mgmt";
1852 struct ubus_event_req ureq = {};
1853 const u8 *addr;
1854
1855 if (req->mgmt_frame)
1856 addr = req->mgmt_frame->sa;
1857 else
1858 addr = req->addr;
1859
1860 ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl);
1861 if (ban)
1862 return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1863
1864 if (!hapd->ubus.obj.has_subscribers)
1865 return WLAN_STATUS_SUCCESS;
1866
1867 if (req->type < ARRAY_SIZE(types))
1868 type = types[req->type];
1869
1870 blob_buf_init(&b, 0);
1871 blobmsg_add_macaddr(&b, "address", addr);
1872 blobmsg_add_string(&b, "ifname", hapd->conf->iface);
1873 if (req->mgmt_frame)
1874 blobmsg_add_macaddr(&b, "target", req->mgmt_frame->da);
1875 if (req->ssi_signal)
1876 blobmsg_add_u32(&b, "signal", req->ssi_signal);
1877 blobmsg_add_u32(&b, "freq", hapd->iface->freq);
1878
1879 if (req->elems) {
1880 if(req->elems->ht_capabilities)
1881 {
1882 struct ieee80211_ht_capabilities *ht_capabilities;
1883 void *ht_cap, *ht_cap_mcs_set, *mcs_set;
1884
1885
1886 ht_capabilities = (struct ieee80211_ht_capabilities*) req->elems->ht_capabilities;
1887 ht_cap = blobmsg_open_table(&b, "ht_capabilities");
1888 blobmsg_add_u16(&b, "ht_capabilities_info", ht_capabilities->ht_capabilities_info);
1889 ht_cap_mcs_set = blobmsg_open_table(&b, "supported_mcs_set");
1890 blobmsg_add_u16(&b, "a_mpdu_params", ht_capabilities->a_mpdu_params);
1891 blobmsg_add_u16(&b, "ht_extended_capabilities", ht_capabilities->ht_extended_capabilities);
1892 blobmsg_add_u32(&b, "tx_bf_capability_info", ht_capabilities->tx_bf_capability_info);
1893 blobmsg_add_u16(&b, "asel_capabilities", ht_capabilities->asel_capabilities);
1894 mcs_set = blobmsg_open_array(&b, "supported_mcs_set");
1895 for (int i = 0; i < 16; i++) {
1896 blobmsg_add_u16(&b, NULL, (u16) ht_capabilities->supported_mcs_set[i]);
1897 }
1898 blobmsg_close_array(&b, mcs_set);
1899 blobmsg_close_table(&b, ht_cap_mcs_set);
1900 blobmsg_close_table(&b, ht_cap);
1901 }
1902 if(req->elems->vht_capabilities)
1903 {
1904 struct ieee80211_vht_capabilities *vht_capabilities;
1905 void *vht_cap, *vht_cap_mcs_set;
1906
1907 vht_capabilities = (struct ieee80211_vht_capabilities*) req->elems->vht_capabilities;
1908 vht_cap = blobmsg_open_table(&b, "vht_capabilities");
1909 blobmsg_add_u32(&b, "vht_capabilities_info", vht_capabilities->vht_capabilities_info);
1910 vht_cap_mcs_set = blobmsg_open_table(&b, "vht_supported_mcs_set");
1911 blobmsg_add_u16(&b, "rx_map", vht_capabilities->vht_supported_mcs_set.rx_map);
1912 blobmsg_add_u16(&b, "rx_highest", vht_capabilities->vht_supported_mcs_set.rx_highest);
1913 blobmsg_add_u16(&b, "tx_map", vht_capabilities->vht_supported_mcs_set.tx_map);
1914 blobmsg_add_u16(&b, "tx_highest", vht_capabilities->vht_supported_mcs_set.tx_highest);
1915 blobmsg_close_table(&b, vht_cap_mcs_set);
1916 blobmsg_close_table(&b, vht_cap);
1917 }
1918 }
1919
1920 if (!hapd->ubus.notify_response) {
1921 ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
1922 return WLAN_STATUS_SUCCESS;
1923 }
1924
1925 if (ubus_notify_async(ctx, &hapd->ubus.obj, type, b.head, &ureq.nreq))
1926 return WLAN_STATUS_SUCCESS;
1927
1928 ureq.nreq.status_cb = ubus_event_cb;
1929 ubus_complete_request(ctx, &ureq.nreq.req, 100);
1930
1931 if (ureq.resp)
1932 return ureq.resp;
1933
1934 return WLAN_STATUS_SUCCESS;
1935 }
1936
1937 void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *addr)
1938 {
1939 if (!hapd->ubus.obj.has_subscribers)
1940 return;
1941
1942 if (!addr)
1943 return;
1944
1945 blob_buf_init(&b, 0);
1946 blobmsg_add_macaddr(&b, "address", addr);
1947 blobmsg_add_string(&b, "ifname", hapd->conf->iface);
1948
1949 ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
1950 }
1951
1952 void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
1953 const char *auth_alg)
1954 {
1955 if (!hapd->ubus.obj.has_subscribers)
1956 return;
1957
1958 blob_buf_init(&b, 0);
1959 blobmsg_add_macaddr(&b, "address", sta->addr);
1960 if (sta->vlan_id)
1961 blobmsg_add_u32(&b, "vlan", sta->vlan_id);
1962 blobmsg_add_string(&b, "ifname", hapd->conf->iface);
1963 if (auth_alg)
1964 blobmsg_add_string(&b, "auth-alg", auth_alg);
1965 if (sta->bandwidth[0] || sta->bandwidth[1]) {
1966 void *r = blobmsg_open_array(&b, "rate-limit");
1967
1968 blobmsg_add_u32(&b, "", sta->bandwidth[0]);
1969 blobmsg_add_u32(&b, "", sta->bandwidth[1]);
1970 blobmsg_close_array(&b, r);
1971 }
1972
1973 ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1);
1974 }
1975
1976 void hostapd_ubus_notify_beacon_report(
1977 struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode,
1978 struct rrm_measurement_beacon_report *rep, size_t len)
1979 {
1980 if (!hapd->ubus.obj.has_subscribers)
1981 return;
1982
1983 if (!addr || !rep)
1984 return;
1985
1986 blob_buf_init(&b, 0);
1987 blobmsg_add_macaddr(&b, "address", addr);
1988 blobmsg_add_u16(&b, "op-class", rep->op_class);
1989 blobmsg_add_u16(&b, "channel", rep->channel);
1990 blobmsg_add_u64(&b, "start-time", rep->start_time);
1991 blobmsg_add_u16(&b, "duration", rep->duration);
1992 blobmsg_add_u16(&b, "report-info", rep->report_info);
1993 blobmsg_add_u16(&b, "rcpi", rep->rcpi);
1994 blobmsg_add_u16(&b, "rsni", rep->rsni);
1995 blobmsg_add_macaddr(&b, "bssid", rep->bssid);
1996 blobmsg_add_u16(&b, "antenna-id", rep->antenna_id);
1997 blobmsg_add_u16(&b, "parent-tsf", rep->parent_tsf);
1998 blobmsg_add_u16(&b, "rep-mode", rep_mode);
1999
2000 ubus_notify(ctx, &hapd->ubus.obj, "beacon-report", b.head, -1);
2001 }
2002
2003 void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
2004 int chan_width, int cf1, int cf2)
2005 {
2006 struct hostapd_data *hapd;
2007 int i;
2008
2009 if (!ctx)
2010 return;
2011
2012 blob_buf_init(&b, 0);
2013 blobmsg_add_u16(&b, "frequency", frequency);
2014 blobmsg_add_u16(&b, "width", chan_width);
2015 blobmsg_add_u16(&b, "center1", cf1);
2016 blobmsg_add_u16(&b, "center2", cf2);
2017
2018 for (i = 0; i < iface->num_bss; i++) {
2019 hapd = iface->bss[i];
2020 ubus_notify(ctx, &hapd->ubus.obj, "radar-detected", b.head, -1);
2021 }
2022 }
2023
2024 #ifdef CONFIG_WNM_AP
2025 static void hostapd_ubus_notify_bss_transition_add_candidate_list(
2026 const u8 *candidate_list, u16 candidate_list_len)
2027 {
2028 char *cl_str;
2029 int i;
2030
2031 if (candidate_list_len == 0)
2032 return;
2033
2034 cl_str = blobmsg_alloc_string_buffer(&b, "candidate-list", candidate_list_len * 2 + 1);
2035 for (i = 0; i < candidate_list_len; i++)
2036 snprintf(&cl_str[i*2], 3, "%02X", candidate_list[i]);
2037 blobmsg_add_string_buffer(&b);
2038
2039 }
2040 #endif
2041
2042 void hostapd_ubus_notify_bss_transition_response(
2043 struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
2044 u8 bss_termination_delay, const u8 *target_bssid,
2045 const u8 *candidate_list, u16 candidate_list_len)
2046 {
2047 #ifdef CONFIG_WNM_AP
2048 u16 i;
2049
2050 if (!hapd->ubus.obj.has_subscribers)
2051 return;
2052
2053 if (!addr)
2054 return;
2055
2056 blob_buf_init(&b, 0);
2057 blobmsg_add_macaddr(&b, "address", addr);
2058 blobmsg_add_u8(&b, "dialog-token", dialog_token);
2059 blobmsg_add_u8(&b, "status-code", status_code);
2060 blobmsg_add_u8(&b, "bss-termination-delay", bss_termination_delay);
2061 if (target_bssid)
2062 blobmsg_add_macaddr(&b, "target-bssid", target_bssid);
2063
2064 hostapd_ubus_notify_bss_transition_add_candidate_list(candidate_list, candidate_list_len);
2065
2066 ubus_notify(ctx, &hapd->ubus.obj, "bss-transition-response", b.head, -1);
2067 #endif
2068 }
2069
2070 int hostapd_ubus_notify_bss_transition_query(
2071 struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
2072 const u8 *candidate_list, u16 candidate_list_len)
2073 {
2074 #ifdef CONFIG_WNM_AP
2075 struct ubus_event_req ureq = {};
2076 char *cl_str;
2077 u16 i;
2078
2079 if (!hapd->ubus.obj.has_subscribers)
2080 return 0;
2081
2082 if (!addr)
2083 return 0;
2084
2085 blob_buf_init(&b, 0);
2086 blobmsg_add_macaddr(&b, "address", addr);
2087 blobmsg_add_u8(&b, "dialog-token", dialog_token);
2088 blobmsg_add_u8(&b, "reason", reason);
2089 hostapd_ubus_notify_bss_transition_add_candidate_list(candidate_list, candidate_list_len);
2090
2091 if (!hapd->ubus.notify_response) {
2092 ubus_notify(ctx, &hapd->ubus.obj, "bss-transition-query", b.head, -1);
2093 return 0;
2094 }
2095
2096 if (ubus_notify_async(ctx, &hapd->ubus.obj, "bss-transition-query", b.head, &ureq.nreq))
2097 return 0;
2098
2099 ureq.nreq.status_cb = ubus_event_cb;
2100 ubus_complete_request(ctx, &ureq.nreq.req, 100);
2101
2102 return ureq.resp;
2103 #endif
2104 }
2105
2106 #ifdef CONFIG_APUP
2107 void hostapd_ubus_notify_apup_newpeer(
2108 struct hostapd_data *hapd, const u8 *addr, const char *ifname)
2109 {
2110 if (!hapd->ubus.obj.has_subscribers)
2111 return;
2112
2113 blob_buf_init(&b, 0);
2114 blobmsg_add_macaddr(&b, "address", addr);
2115 blobmsg_add_string(&b, "ifname", ifname);
2116
2117 ubus_notify(ctx, &hapd->ubus.obj, "apup-newpeer", b.head, -1);
2118 }
2119 #endif // def CONFIG_APUP
2120
2121 void hostapd_ubus_notify_csa(struct hostapd_data *hapd, int freq)
2122 {
2123 if (!hapd->ubus.obj.has_subscribers)
2124 return;
2125
2126 blob_buf_init(&b, 0);
2127 blobmsg_add_string(&b, "ifname", hapd->conf->iface);
2128 blobmsg_add_u32(&b, "freq", freq);
2129 blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid));
2130
2131 ubus_notify(ctx, &hapd->ubus.obj, "channel-switch", b.head, -1);
2132 }