diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index c5b258bf1..c6160ded3 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3105,6 +3105,34 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, } +static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf, + size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) iface->drv_flags2); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (iface->drv_flags2 & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag2_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, const char *txtaddr) { @@ -3517,6 +3545,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply, reply_size); + } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { + reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply, + reply_size); } else if (os_strcmp(buf, "TERMINATE") == 0) { eloop_terminate(); } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { diff --git a/hostapd/main.c b/hostapd/main.c index 4af8e8f9c..6a69412d0 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -218,6 +218,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface) struct wowlan_triggers *triggs; iface->drv_flags = capa.flags; + iface->drv_flags2 = capa.flags2; iface->probe_resp_offloads = capa.probe_resp_offloads; /* * Use default extended capa values from per-radio information diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index ec5b9d57f..fff15f118 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -475,6 +475,7 @@ struct hostapd_iface { struct ap_info *ap_hash[STA_HASH_SIZE]; u64 drv_flags; + u64 drv_flags2; /* * A bitmap of supported protocols for probe response offload. See diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 032bbd892..e01f26c12 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1852,6 +1852,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID 0x8000000000000000ULL u64 flags; + u64 flags2; + #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ (drv_flags & WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE) @@ -5921,6 +5923,7 @@ wpa_get_wowlan_triggers(const char *wowlan_triggers, const struct wpa_driver_capa *capa); /* Convert driver flag to string */ const char * driver_flag_to_string(u64 flag); +const char * driver_flag2_to_string(u64 flag2); /* NULL terminated array of linked in driver wrappers */ extern const struct wpa_driver_ops *const wpa_drivers[]; diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 63846db2e..c62cf51e3 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -321,3 +321,13 @@ const char * driver_flag_to_string(u64 flag) return "UNKNOWN"; #undef DF2S } + + +const char * driver_flag2_to_string(u64 flag2) +{ +#define DF2S(x) case WPA_DRIVER_FLAGS2_ ## x: return #x + switch (flag2) { + } + return "UNKNOWN"; +#undef DF2S +} diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 13e2f41a9..541de758e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7960,6 +7960,34 @@ static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, } +static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s, + char *buf, size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) wpa_s->drv_flags2); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (wpa_s->drv_flags2 & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag2_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) { @@ -10730,6 +10758,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, reply_size); + } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { + reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply, + reply_size); #ifdef ANDROID } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index b504124fa..c085466b1 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -268,6 +268,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, return -ENOMEM; ifmsh->drv_flags = wpa_s->drv_flags; + ifmsh->drv_flags2 = wpa_s->drv_flags2; ifmsh->num_bss = 1; ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, sizeof(struct hostapd_data *)); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e29ed83e1..6a69ccebf 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6243,6 +6243,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, if (capa_res == 0) { wpa_s->drv_capa_known = 1; wpa_s->drv_flags = capa.flags; + wpa_s->drv_flags2 = capa.flags2; wpa_s->drv_enc = capa.enc; wpa_s->drv_rrm_flags = capa.rrm_flags; wpa_s->probe_resp_offloads = capa.probe_resp_offloads; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 997e5f642..619ae42b6 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -725,6 +725,7 @@ struct wpa_supplicant { unsigned int no_suitable_network; u64 drv_flags; + u64 drv_flags2; unsigned int drv_enc; unsigned int drv_rrm_flags;