From 8d7502809c93ef7161e6e91707977a3d63bafc8a Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 22 Apr 2020 12:54:35 +0530 Subject: [PATCH] Allow per interface type AKM capabilities to be fetched Add support to query per interface type AKM capabilities through the control interface. For example, "GET_CAPABILITY key_mgmt iftype=STATION". Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/ctrl_iface.c | 109 ++++++++++++++++++++++++++++-------- wpa_supplicant/wpa_cli.c | 43 ++++++++++++-- 2 files changed, 122 insertions(+), 30 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 5c99735c8..4860e3480 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4098,11 +4098,49 @@ static int ctrl_iface_get_capability_group_mgmt(int res, char *strict, } +static int iftype_str_to_index(const char *iftype_str) +{ + if (!iftype_str) + return WPA_IF_MAX; + + if (os_strcmp(iftype_str, "STATION") == 0) + return WPA_IF_STATION; + + if (os_strcmp(iftype_str, "AP_VLAN") == 0) + return WPA_IF_AP_VLAN; + + if (os_strcmp(iftype_str, "AP") == 0) + return WPA_IF_AP_BSS; + + if (os_strcmp(iftype_str, "P2P_GO") == 0) + return WPA_IF_P2P_GO; + + if (os_strcmp(iftype_str, "P2P_CLIENT") == 0) + return WPA_IF_P2P_CLIENT; + + if (os_strcmp(iftype_str, "P2P_DEVICE") == 0) + return WPA_IF_P2P_DEVICE; + + if (os_strcmp(iftype_str, "MESH") == 0) + return WPA_IF_MESH; + + if (os_strcmp(iftype_str, "IBSS") == 0) + return WPA_IF_IBSS; + + if (os_strcmp(iftype_str, "NAN") == 0) + return WPA_IF_NAN; + + return WPA_IF_MAX; +} + + static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, struct wpa_driver_capa *capa, + const char *iftype_str, char *buf, size_t buflen) { int ret; + unsigned int key_mgmt; char *pos, *end; size_t len; @@ -4119,28 +4157,39 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, return len; } + if (iftype_str) { + enum wpa_driver_if_type iftype; + + iftype = iftype_str_to_index(iftype_str); + if (iftype == WPA_IF_MAX) + return -1; + key_mgmt = capa->key_mgmt_iftype[iftype]; + } else { + key_mgmt = capa->key_mgmt; + } + ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; - if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { + if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { ret = os_snprintf(pos, end - pos, " WPA-EAP"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { + if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { ret = os_snprintf(pos, end - pos, " WPA-PSK"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { ret = os_snprintf(pos, end - pos, " WPA-NONE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4148,7 +4197,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #ifdef CONFIG_SUITEB - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4156,7 +4205,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_SUITEB */ #ifdef CONFIG_SUITEB192 - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4164,7 +4213,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_SUITEB192 */ #ifdef CONFIG_OWE - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { ret = os_snprintf(pos, end - pos, " OWE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4172,7 +4221,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { ret = os_snprintf(pos, end - pos, " DPP"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4180,26 +4229,26 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_DPP */ #ifdef CONFIG_FILS - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { ret = os_snprintf(pos, end - pos, " FILS-SHA256"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { ret = os_snprintf(pos, end - pos, " FILS-SHA384"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } #ifdef CONFIG_IEEE80211R - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4208,7 +4257,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, #endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_FILS */ #ifdef CONFIG_IEEE80211R - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { ret = os_snprintf(pos, end - pos, " FT-PSK"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4216,7 +4265,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_SAE - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { ret = os_snprintf(pos, end - pos, " SAE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4512,23 +4561,35 @@ static int wpa_supplicant_ctrl_iface_get_capability( { struct wpa_driver_capa capa; int res; - char *strict; - char field[30]; + char *next_param, *curr_param, *iftype = NULL, *strict = NULL; + char field[50]; size_t len; /* Determine whether or not strict checking was requested */ len = os_strlcpy(field, _field, sizeof(field)); if (len >= sizeof(field)) return -1; - strict = os_strchr(field, ' '); - if (strict != NULL) { - *strict++ = '\0'; - if (os_strcmp(strict, "strict") != 0) + + next_param = os_strchr(field, ' '); + while (next_param) { + *next_param++ = '\0'; + curr_param = next_param; + next_param = os_strchr(next_param, ' '); + + if (next_param) + *next_param = '\0'; + + if (os_strcmp(curr_param, "strict") == 0) + strict = curr_param; + else if (os_strncmp(curr_param, "iftype=", 7) == 0) + iftype = curr_param + 7; + else return -1; } - wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", - field, strict ? strict : ""); + wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s", + field, iftype ? " iftype=" : "", iftype ? iftype : "", + strict ? " strict" : ""); if (os_strcmp(field, "eap") == 0) { return eap_get_names(buf, buflen); @@ -4550,7 +4611,7 @@ static int wpa_supplicant_ctrl_iface_get_capability( if (os_strcmp(field, "key_mgmt") == 0) return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, - buf, buflen); + iftype, buf, buflen); if (os_strcmp(field, "proto") == 0) return ctrl_iface_get_capability_proto(res, strict, &capa, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 07d5f315c..6a2d2c3d6 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1706,15 +1706,25 @@ static char ** wpa_cli_complete_bss(const char *str, int pos) static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, char *argv[]) { - if (argc < 1 || argc > 2) { - printf("Invalid GET_CAPABILITY command: need either one or " - "two arguments\n"); + if (argc < 1 || argc > 3) { + printf("Invalid GET_CAPABILITY command: need at least one argument and max three arguments\n"); return -1; } - if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { - printf("Invalid GET_CAPABILITY command: second argument, " - "if any, must be 'strict'\n"); + if (argc > 1 && os_strcmp(argv[0], "key_mgmt") != 0 && + os_strncmp(argv[1], "iftype=", 7) == 0) { + printf("Invalid GET_CAPABILITY command: 'iftype=' param is allowed only for 'key_mgmt'\n"); + return -1; + } + + if (argc == 2 && os_strcmp(argv[1], "strict") != 0 && + os_strncmp(argv[1], "iftype=", 7) != 0) { + printf("Invalid GET_CAPABILITY command: the second argument, if any, must be 'strict' OR 'iftype='\n"); + return -1; + } + + if (argc == 3 && os_strcmp(argv[2], "strict") != 0) { + printf("Invalid GET_CAPABILITY command: the third argument, if any, must be 'strict'\n"); return -1; } @@ -1741,7 +1751,13 @@ static char ** wpa_cli_complete_get_capability(const char *str, int pos) "acs", #endif /* CONFIG_ACS */ }; + const char *iftypes[] = { + "iftype=STATION", "iftype=AP", "iftype=P2P_CLIENT", + "iftype=P2P_GO", "iftype=AP_VLAN", "iftype=IBSS", "iftype=NAN", + "iftype=P2P_DEVICE", "iftype=MESH", + }; int i, num_fields = ARRAY_SIZE(fields); + int num_iftypes = ARRAY_SIZE(iftypes); char **res = NULL; if (arg == 1) { @@ -1755,6 +1771,21 @@ static char ** wpa_cli_complete_get_capability(const char *str, int pos) } } if (arg == 2) { + /* the second argument can be "iftype=" OR + * "strict" */ + res = os_calloc(num_iftypes + 2, sizeof(char *)); + if (!res) + return NULL; + res[0] = os_strdup("strict"); + if (!res[0]) + return res; + for (i = 0; i < num_iftypes; i++) { + res[i + 1] = os_strdup(iftypes[i]); + if (!res[i + 1]) + return res; + } + } + if (arg == 3) { res = os_calloc(1 + 1, sizeof(char *)); if (res == NULL) return NULL;