These commnds are mesh version of PMKSA_GET/ADD commands. So the usage and security risk is similar to them. Refer Commit 3459381dd260e15e7bf768a75cb0b799cc1db33a ('External persistent storage for PMKSA cache entries') also. The MESH_PMKSA_GET command requires peer MAC address or "ANY" as an argument and outputs appropriate stored PMKSA cache. And the MESH_PMKSA_ADD command receives an output of MESH_PMKSA_GET and re-store the PMKSA cache into wpa_supplicant. By using re-stored PMKSA cache, wpa_supplicant can skip commit massage creation which spends many CPU resource. The output of the MESH_PMKSA_GET command uses the following format: <BSSID> <PMKID> <PMK> <expiration in seconds> The example of MESH_PMKSA_ADD command is this. MESH_PMKSA_ADD 02:00:00:00:03:00 231dc1c9fa2eed0354ea49e8ff2cc2dc cb0f6c9cab358a8146488566ca155421ab4f3ea4a6de2120050c149b797018fe 42930 MESH_PMKSA_ADD 02:00:00:00:04:00 d7e595916611640d3e4e8eac02909c3c eb414a33c74831275f25c2357b3c12e3d8bd2f2aab6cf781d6ade706be71321a 43180 This functionality is disabled by default and can be enabled with CONFIG_PMKSA_CACHE_EXTERNAL=y build configuration option. Signed-off-by: Masashi Honma <masashi.honma@xxxxxxxxx> --- src/ap/ctrl_iface_ap.c | 57 ++++++++++++++++ src/ap/ctrl_iface_ap.h | 3 + src/ap/pmksa_cache_auth.c | 133 +++++++++++++++++++++++++++++++++++++- src/ap/pmksa_cache_auth.h | 9 +++ src/ap/wpa_auth.c | 42 ++++++++++++ src/ap/wpa_auth.h | 7 ++ wpa_supplicant/ap.c | 37 +++++++++++ wpa_supplicant/ap.h | 3 + wpa_supplicant/ctrl_iface.c | 54 ++++++++++++++++ wpa_supplicant/mesh_rsn.c | 18 ++++++ wpa_supplicant/wpa_cli.c | 24 +++++++ wpa_supplicant/wpa_supplicant.c | 6 ++ wpa_supplicant/wpa_supplicant_i.h | 8 +++ 13 files changed, 398 insertions(+), 3 deletions(-) diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 3680fda..cc6e215 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -639,3 +639,60 @@ void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd) { wpa_auth_pmksa_flush(hapd->wpa_auth); } + + +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + +int hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data *hapd, + const u8 *addr, char *buf, size_t len) +{ + return wpa_auth_pmksa_list_mesh(hapd->wpa_auth, addr, buf, len); +} + + +void *hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd) +{ + u8 spa[ETH_ALEN]; + u8 pmkid[PMKID_LEN]; + u8 pmk[PMK_LEN_MAX]; + char *pos; + int expiration; + + /* + * Entry format: + * <BSSID> <PMKID> <PMK> <expiration in seconds> + */ + + if (hwaddr_aton(cmd, spa)) + return NULL; + + pos = os_strchr(cmd, ' '); + if (!pos) + return NULL; + pos++; + + if (hexstr2bin(pos, pmkid, PMKID_LEN) < 0) + return NULL; + + pos = os_strchr(pos, ' '); + if (!pos) + return NULL; + pos++; + + if (hexstr2bin(pos, pmk, PMK_LEN) < 0) + return NULL; + + pos = os_strchr(pos, ' '); + if (!pos) + return NULL; + pos++; + + if (sscanf(pos, "%d", &expiration) != 1) + return NULL; + + return wpa_auth_pmksa_create_entry(aa, spa, pmk, pmkid, expiration); +} +#endif /* CONFIG_MESH */ + +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ diff --git a/src/ap/ctrl_iface_ap.h b/src/ap/ctrl_iface_ap.h index 4f99680..39d1705 100644 --- a/src/ap/ctrl_iface_ap.h +++ b/src/ap/ctrl_iface_ap.h @@ -32,5 +32,8 @@ int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd); int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf, size_t len); void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd); +int hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data *hapd, + const u8 *addr, char *buf, size_t len); +void *hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd); #endif /* CTRL_IFACE_AP_H */ diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c index d610e7e..50f1316 100644 --- a/src/ap/pmksa_cache_auth.c +++ b/src/ap/pmksa_cache_auth.c @@ -282,7 +282,42 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, int session_timeout, struct eapol_state_machine *eapol, int akmp) { - struct rsn_pmksa_cache_entry *entry, *pos; + struct rsn_pmksa_cache_entry *entry; + + entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, kck, kck_len, + aa, spa, session_timeout, eapol, + akmp); + + if (pmksa_cache_auth_add_entry(pmksa, entry) < 0) + return NULL; + + return entry; +} + + +/** + * pmksa_cache_auth_create_entry - Create a PMKSA cache entry + * @pmk: The new pairwise master key + * @pmk_len: PMK length in bytes, usually PMK_LEN (32) + * @pmkid: Calculated PMKID + * @kck: Key confirmation key or %NULL if not yet derived + * @kck_len: KCK length in bytes + * @aa: Authenticator address + * @spa: Supplicant address + * @session_timeout: Session timeout + * @eapol: Pointer to EAPOL state machine data + * @akmp: WPA_KEY_MGMT_* used in key derivation + * Returns: Pointer to the added PMKSA cache entry or %NULL on error + * + * This function creates a PMKSA entry. + */ +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp) +{ + struct rsn_pmksa_cache_entry *entry; struct os_reltime now; if (pmk_len > PMK_LEN_MAX) @@ -315,9 +350,30 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, os_memcpy(entry->spa, spa, ETH_ALEN); pmksa_cache_from_eapol_data(entry, eapol); + return entry; +} + + +/** + * pmksa_cache_auth_add_entry - Add a PMKSA cache entry + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + * @entry: Pointer to PMKSA cache entry + * + * This function adds PMKSA cache entry to the PMKSA cache. If an old entry is + * already in the cache for the same Supplicant, this entry will be replaced + * with the new entry. PMKID will be calculated based on the PMK. + */ +int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry) +{ + struct rsn_pmksa_cache_entry *pos; + + if (entry == NULL) + return -1; + /* Replace an old entry for the same STA (if found) with the new entry */ - pos = pmksa_cache_auth_get(pmksa, spa, NULL); + pos = pmksa_cache_auth_get(pmksa, entry->spa, NULL); if (pos) pmksa_cache_free_entry(pmksa, pos); @@ -331,7 +387,7 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, pmksa_cache_link_entry(pmksa, entry); - return entry; + return 0; } @@ -605,3 +661,74 @@ int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) } return pos - buf; } + + +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + +/** + * pmksa_cache_auth_list_mesh - Dump text list of entries in PMKSA cache + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + * @addr: MAC address of the peer (NULL means any) + * @buf: Buffer for the list + * @len: Length of the buffer + * Returns: Number of bytes written to buffer + * + * This function is used to generate a text format representation of the + * current PMKSA cache contents for the ctrl_iface PMKSA_GET command to store + * in external storage + */ +int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr, + char *buf, size_t len) +{ + int ret; + char *pos, *end; + struct rsn_pmksa_cache_entry *entry; + struct os_reltime now; + + pos = buf; + end = buf + len; + os_get_reltime(&now); + + entry = pmksa->pmksa; + + /* + * Entry format: + * <BSSID> <PMKID> <PMK> <expiration in seconds> + */ + while (entry) { + if (addr && os_memcmp(entry->spa, addr, ETH_ALEN) != 0) { + entry = entry->next; + continue; + } + + ret = os_snprintf(pos, end - pos, MACSTR " ", + MAC2STR(entry->spa)); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + pos += wpa_snprintf_hex(pos, end - pos, entry->pmkid, + PMKID_LEN); + + ret = os_snprintf(pos, end - pos, " "); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + pos += wpa_snprintf_hex(pos, end - pos, entry->pmk, + entry->pmk_len); + + ret = os_snprintf(pos, end - pos, " %d\n", + (int)(entry->expiration - now.sec)); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + entry = entry->next; + } + + return pos - buf; +} +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ diff --git a/src/ap/pmksa_cache_auth.h b/src/ap/pmksa_cache_auth.h index d8d9c5a..bd1b672 100644 --- a/src/ap/pmksa_cache_auth.h +++ b/src/ap/pmksa_cache_auth.h @@ -53,6 +53,13 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, int session_timeout, struct eapol_state_machine *eapol, int akmp); struct rsn_pmksa_cache_entry * +pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp); +int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry); +struct rsn_pmksa_cache_entry * pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, const struct rsn_pmksa_cache_entry *old_entry, const u8 *aa, const u8 *pmkid); @@ -65,5 +72,7 @@ int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, struct radius_das_attrs *attr); int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa); +int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr, + char *buf, size_t len); #endif /* PMKSA_CACHE_H */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 43e3558..0a6117d 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3850,6 +3850,48 @@ void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth) } +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + +int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr, + char *buf, size_t len) +{ + if (!wpa_auth || !wpa_auth->pmksa) + return 0; + + return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len); +} + + +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk, + const u8 *pmkid, int expiration) +{ + struct rsn_pmksa_cache_entry *entry; + struct os_reltime now; + + entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa, + spa, 0, NULL, WPA_KEY_MGMT_SAE); + + os_get_reltime(&now); + entry->expiration = now.sec + expiration; + return entry; +} + + +int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth, + struct rsn_pmksa_cache_entry *entry) +{ + if (wpa_auth == NULL || wpa_auth->pmksa == NULL) + return -1; + + return pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry); +} +#endif /* CONFIG_MESH */ + +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + + struct rsn_pmksa_cache_entry * wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, const u8 *pmkid) diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 743f2e6..f383ab0 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -302,6 +302,13 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, size_t len); void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth); +int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr, + char *buf, size_t len); +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk, + const u8 *pmkid, int expiration); +int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth, + struct rsn_pmksa_cache_entry *entry); struct rsn_pmksa_cache_entry * wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, const u8 *pmkid); diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 5afb772..2972091 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -1436,6 +1436,43 @@ void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s) if (wpa_s->ifmsh) hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]); } + + +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + +int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr, + char *buf, size_t len) +{ + return hostapd_ctrl_iface_pmksa_list_mesh(wpa_s->ifmsh->bss[0], addr, + &buf[0], len); +} + + +int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd) +{ + struct external_pmksa_cache *entry; + void *pmksa_cache; + + pmksa_cache = hostapd_ctrl_iface_pmksa_create_entry(wpa_s->own_addr, + cmd); + if (pmksa_cache == NULL) + return -1; + + entry = os_malloc(sizeof(struct external_pmksa_cache)); + if (entry == NULL) + return -1; + + entry->pmksa_cache = pmksa_cache; + + dl_list_add(&wpa_s->mesh_external_pmksa_cache, &entry->list); + + return 0; +} + +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + #endif /* CONFIG_CTRL_IFACE */ diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h index 5a59ddc..3fa656f 100644 --- a/wpa_supplicant/ap.h +++ b/wpa_supplicant/ap.h @@ -85,6 +85,9 @@ int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s); int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, size_t len); void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s); +int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr, + char *buf, size_t len); +int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd); void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, struct dfs_event *radar); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index be178d7..bbfc8e6 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8982,6 +8982,52 @@ fail: return ret; } + +#ifdef CONFIG_MESH +static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s, + const char *cmd, char *buf, + size_t buflen) +{ + char *pos, *end; + int ret; + u8 spa[ETH_ALEN]; + + if (!wpa_s->ifmsh) + return -1; + + if (os_strcasecmp(cmd, "any") == 0) + return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen); + + if (hwaddr_aton(cmd, spa)) { + pos = buf; + end = buf + buflen; + + ret = os_snprintf(pos, end - pos, "Specify \"any\" or a MAC address of the peer\n"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + return pos - buf; + } + + return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen); +} + + +static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, + char *cmd) +{ + /* + * We does not check mesh interface existance because PMKSA + * should be stored before wpa_s->ifmsh creation to suppress + * commit message creation. + */ + //if (!wpa_s->ifmsh) + // return -1; + + return wpas_ap_pmksa_cache_add_external(wpa_s, cmd); +} +#endif /* CONFIG_MESH */ + #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ @@ -9066,6 +9112,14 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0) reply_len = -1; +#ifdef CONFIG_MESH + } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) { + reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15, + reply, reply_size); + } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { + if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0) + reply_len = -1; +#endif /* CONFIG_MESH */ #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ } else if (os_strncmp(buf, "SET ", 4) == 0) { if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c index b1cf138..8278bef 100644 --- a/wpa_supplicant/mesh_rsn.c +++ b/wpa_supplicant/mesh_rsn.c @@ -320,6 +320,9 @@ int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, struct rsn_pmksa_cache_entry *pmksa; unsigned int rnd; int ret; +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + struct external_pmksa_cache *entry; +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ if (!ssid) { wpa_msg(wpa_s, MSG_DEBUG, @@ -333,6 +336,21 @@ int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, return -1; } +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + while (!dl_list_empty(&wpa_s->mesh_external_pmksa_cache)) { + entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache, + struct external_pmksa_cache, list); + if (wpa_auth_pmksa_add_entry(hapd->wpa_auth, + entry->pmksa_cache) < 0) { + wpa_msg(wpa_s, MSG_DEBUG, + "AUTH: Failed to store external PMKSA cache"); + return -1; + } + dl_list_del(&entry->list); + os_free(entry); + } +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr, NULL); if (pmksa) { if (!sta->wpa_sm) diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 4c6b69d..8288661 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -348,6 +348,22 @@ static int wpa_cli_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, char *argv[]) return wpa_cli_cmd(ctrl, "PMKSA_ADD", 8, argc, argv); } + +#ifdef CONFIG_MESH +static int wpa_cli_mesh_cmd_pmksa_get(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_PMKSA_GET", 1, argc, argv); +} + + +static int wpa_cli_mesh_cmd_pmksa_add(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "MESH_PMKSA_ADD", 4, argc, argv); +} +#endif /* CONFIG_MESH */ + #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ @@ -2891,6 +2907,14 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "pmksa_add", wpa_cli_cmd_pmksa_add, NULL, cli_cmd_flag_none, "<network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> <expiration in seconds> <akmp> <opportunistic> = store PMKSA cache entry from external storage" }, +#ifdef CONFIG_MESH + { "mesh_pmksa_get", wpa_cli_mesh_cmd_pmksa_get, NULL, + cli_cmd_flag_none, + "<peer MAC address | any> = fetch all stored mesh PMKSA cache entries" }, + { "mesh_pmksa_add", wpa_cli_mesh_cmd_pmksa_add, NULL, + cli_cmd_flag_none, + "<BSSID> <PMKID> <PMK> <expiration in seconds> = store mesh PMKSA cache entry from external storage" }, +#endif /* CONFIG_MESH */ #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ { "reassociate", wpa_cli_cmd_reassociate, NULL, cli_cmd_flag_none, diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 214b9b3..b9d8368 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4976,6 +4976,12 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, if (wpa_bss_init(wpa_s) < 0) return -1; +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + dl_list_init(&wpa_s->mesh_external_pmksa_cache); +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + /* * Set Wake-on-WLAN triggers, if configured. * Note: We don't restore/remove the triggers on shutdown (it doesn't diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index f03d51a..15c5b5c 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -446,6 +446,11 @@ struct wpa_bss_tmp_disallowed { struct os_reltime disallowed_until; }; +struct external_pmksa_cache { + struct dl_list list; + void *pmksa_cache; +}; + /** * struct wpa_supplicant - Internal data for wpa_supplicant interface * @@ -776,6 +781,9 @@ struct wpa_supplicant { unsigned int mesh_if_created:1; unsigned int mesh_ht_enabled:1; unsigned int mesh_vht_enabled:1; +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + struct dl_list mesh_external_pmksa_cache; +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ #endif /* CONFIG_MESH */ unsigned int off_channel_freq; -- 2.7.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap