hostapd: report bssid, ssid and channel over ubus
[openwrt/openwrt.git] / package / network / services / hostapd / src / src / ap / ubus.c
index 8546d2ce6991cb6b9cd0b7cb36b790d2b45f1c41..289c8ff7a4541255c06bca4e6df4325dad45c4f8 100644 (file)
@@ -372,6 +372,32 @@ hostapd_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj,
        return 0;
 }
 
+/* Imported from iw/util.c
+ *  https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git/tree/util.c?id=4b25ae3537af48dbf9d0abf94132e5ba01b32c18#n200
+ */
+int ieee80211_frequency_to_channel(int freq)
+{
+       /* see 802.11-2007 17.3.8.3.2 and Annex J */
+       if (freq == 2484)
+               return 14;
+       /* see 802.11ax D6.1 27.3.23.2 and Annex E */
+       else if (freq == 5935)
+               return 2;
+       else if (freq < 2484)
+               return (freq - 2407) / 5;
+       else if (freq >= 4910 && freq <= 4980)
+               return (freq - 4000) / 5;
+       else if (freq < 5950)
+               return (freq - 5000) / 5;
+       else if (freq <= 45000) /* DMG band lower limit */
+               /* see 802.11ax D6.1 27.3.23.2 */
+               return (freq - 5950) / 5;
+       else if (freq >= 58320 && freq <= 70200)
+               return (freq - 56160) / 2160;
+       else
+               return 0;
+}
+
 static int
 hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
                       struct ubus_request_data *req, const char *method,
@@ -380,12 +406,24 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
        struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
        void *airtime_table, *dfs_table;
        struct os_reltime now;
+       char ssid[SSID_MAX_LEN + 1];
        char phy_name[17];
        char mac_buf[20];
+       size_t ssid_len = SSID_MAX_LEN;
+
+       if (hapd->conf->ssid.ssid_len < SSID_MAX_LEN)
+               ssid_len = hapd->conf->ssid.ssid_len;
 
        blob_buf_init(&b, 0);
        blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state));
+       blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid));
+
+       memset(ssid, 0, SSID_MAX_LEN + 1);
+       memcpy(ssid, hapd->conf->ssid.ssid, ssid_len);
+       blobmsg_add_string(&b, "ssid", ssid);
+
        blobmsg_add_u32(&b, "freq", hapd->iface->freq);
+       blobmsg_add_u32(&b, "channel", ieee80211_frequency_to_channel(hapd->iface->freq));
 
        snprintf(phy_name, 17, "%s", hapd->iface->phy);
        blobmsg_add_string(&b, "phy", phy_name);
@@ -658,6 +696,10 @@ hostapd_config_add(struct ubus_context *ctx, struct ubus_object *obj,
        if (hostapd_add_iface(interfaces, buf))
                return UBUS_STATUS_INVALID_ARGUMENT;
 
+       blob_buf_init(&b, 0);
+       blobmsg_add_u32(&b, "pid", getpid());
+       ubus_send_reply(ctx, req, b.head);
+
        return UBUS_STATUS_OK;
 }
 
@@ -724,6 +766,8 @@ hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj,
        struct blob_attr *tb[__CSA_MAX];
        struct hostapd_data *hapd = get_hapd_from_object(obj);
        struct csa_settings css;
+       int ret = UBUS_STATUS_OK;
+       int i;
 
        blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg));
 
@@ -748,10 +792,14 @@ hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj,
        SET_CSA_SETTING(CSA_VHT, freq_params.vht_enabled, bool);
        SET_CSA_SETTING(CSA_BLOCK_TX, block_tx, bool);
 
+       for (i = 0; i < hapd->iface->num_bss; i++) {
+               struct hostapd_data *bss = hapd->iface->bss[i];
 
-       if (hostapd_switch_channel(hapd, &css) != 0)
-               return UBUS_STATUS_NOT_SUPPORTED;
-       return UBUS_STATUS_OK;
+               if (hostapd_switch_channel(bss, &css) != 0)
+                       ret = UBUS_STATUS_NOT_SUPPORTED;
+       }
+
+       return ret;
 #undef SET_CSA_SETTING
 }
 #endif
@@ -1360,6 +1408,43 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd)
        free(name);
 }
 
+static void
+hostapd_ubus_vlan_action(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
+                        const char *action)
+{
+       struct vlan_description *desc = &vlan->vlan_desc;
+       void *c;
+       int i;
+
+       if (!hapd->ubus.obj.has_subscribers)
+               return;
+
+       blob_buf_init(&b, 0);
+       blobmsg_add_string(&b, "ifname", vlan->ifname);
+       blobmsg_add_string(&b, "bridge", vlan->bridge);
+       blobmsg_add_u32(&b, "vlan_id", vlan->vlan_id);
+
+       if (desc->notempty) {
+               blobmsg_add_u32(&b, "untagged", desc->untagged);
+               c = blobmsg_open_array(&b, "tagged");
+               for (i = 0; i < ARRAY_SIZE(desc->tagged) && desc->tagged[i]; i++)
+                       blobmsg_add_u32(&b, "", desc->tagged[i]);
+               blobmsg_close_array(&b, c);
+       }
+
+       ubus_notify(ctx, &hapd->ubus.obj, action, b.head, -1);
+}
+
+void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
+{
+       hostapd_ubus_vlan_action(hapd, vlan, "vlan_add");
+}
+
+void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
+{
+       hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove");
+}
+
 static const struct ubus_method daemon_methods[] = {
        UBUS_METHOD("config_add", hostapd_config_add, config_add_policy),
        UBUS_METHOD("config_remove", hostapd_config_remove, config_remove_policy),
@@ -1546,3 +1631,24 @@ void hostapd_ubus_notify_beacon_report(
 
        ubus_notify(ctx, &hapd->ubus.obj, "beacon-report", b.head, -1);
 }
+
+void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
+                                       int chan_width, int cf1, int cf2)
+{
+       struct hostapd_data *hapd;
+       int i;
+
+       if (!hapd->ubus.obj.has_subscribers)
+               return;
+
+       blob_buf_init(&b, 0);
+       blobmsg_add_u16(&b, "frequency", frequency);
+       blobmsg_add_u16(&b, "width", chan_width);
+       blobmsg_add_u16(&b, "center1", cf1);
+       blobmsg_add_u16(&b, "center2", cf2);
+
+       for (i = 0; i < iface->num_bss; i++) {
+               hapd = iface->bss[i];
+               ubus_notify(ctx, &hapd->ubus.obj, "radar-detected", b.head, -1);
+       }
+}