wireless/bcm43xxx: correct auth status if PSK is invaild

Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
chao an 2022-10-21 00:27:34 +08:00 committed by Xiang Xiao
parent 41c86c526a
commit 4fe321b6fb
2 changed files with 140 additions and 75 deletions

View File

@ -55,7 +55,7 @@
#define DOT11_BSSTYPE_ANY 2
#define BCMF_SCAN_TIMEOUT_TICK (5*CLOCKS_PER_SEC)
#define BCMF_AUTH_TIMEOUT_MS 20000 /* was 10000 */
#define BCMF_AUTH_TIMEOUT_MS 15000 /* was 10000 */
#define BCMF_SCAN_RESULT_ENTRIES CONFIG_IEEE80211_BROADCOM_SCAN_RESULT_ENTRIES
/* CLM file is cut into pieces of MAX_CHUNK_LEN.
@ -124,27 +124,33 @@ enum
DL_TYPE_CLM = 2
};
typedef begin_packed_struct struct wpa_cipher_suite
begin_packed_struct struct wpa_cipher_suite
{
uint8_t oui[3];
uint8_t type;
} end_packed_struct wpa_cipher_suite_t;
} end_packed_struct;
typedef begin_packed_struct struct wpa_rsn
typedef struct wpa_cipher_suite wpa_cipher_suite_t;
begin_packed_struct struct wpa_rsn
{
uint16_t version;
wpa_cipher_suite_t group;
uint16_t scount;
wpa_cipher_suite_t pairwise[0];
} end_packed_struct wpa_rsn_t;
} end_packed_struct;
typedef begin_packed_struct struct wpa_akm
typedef struct wpa_rsn wpa_rsn_t;
begin_packed_struct struct wpa_akm
{
uint16_t scount;
wpa_cipher_suite_t suite[0];
} end_packed_struct wpa_akm_t;
} end_packed_struct;
typedef begin_packed_struct struct
typedef struct wpa_akm wpa_akm_t;
begin_packed_struct struct wpa_ie_fixed
{
uint8_t tag; /* TAG */
uint8_t length; /* TAG length */
@ -154,8 +160,11 @@ typedef begin_packed_struct struct
{
uint8_t low;
uint8_t high;
} end_packed_struct version; /* IE version */
} end_packed_struct wpa_ie_fixed_t;
}
end_packed_struct version; /* IE version */
} end_packed_struct;
typedef struct wpa_ie_fixed wpa_ie_fixed_t;
/****************************************************************************
* Private Function Prototypes
@ -471,7 +480,7 @@ int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active)
out_len = 4;
value = GMODE_AUTO;
ret = bcmf_cdc_ioctl(priv, interface, true, WLC_SET_GMODE,
(uint8_t *)&value, &out_len);
(FAR uint8_t *)&value, &out_len);
if (ret != OK)
{
goto errout_in_sdio_active;
@ -519,7 +528,7 @@ int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active)
/* Remove line feed */
out_len = strlen((char *)tmp_buf);
out_len = strlen((FAR char *)tmp_buf);
if (out_len > 0 && tmp_buf[out_len - 1] == '\n')
{
tmp_buf[out_len - 1] = 0;
@ -621,11 +630,15 @@ void bcmf_wl_auth_event_handler(FAR struct bcmf_dev_s *priv,
struct bcmf_event_s *event,
unsigned int len)
{
uint32_t type;
bool auth = false;
int carrier = -1;
uint32_t reason;
uint32_t status;
uint32_t type;
type = bcmf_getle32(&event->type);
status = bcmf_getle32(&event->status);
reason = bcmf_getle32(&event->reason);
wlinfo("Got auth event %" PRId32 " status %" PRId32 " from <%s>\n",
type, status, event->src_name);
@ -637,18 +650,44 @@ void bcmf_wl_auth_event_handler(FAR struct bcmf_dev_s *priv,
bcmf_hexdump((uint8_t *)event, len, (unsigned long)event);
if (type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS)
if (type == WLC_E_PSK_SUP)
{
/* Auth complete */
netdev_carrier_on(&priv->bc_dev);
priv->auth_status = OK;
nxsem_post(&priv->auth_signal);
carrier = (reason == WLC_E_SUP_OTHER) ? 1 : 0;
if (priv->auth_pending)
{
priv->auth_status = reason;
auth = true;
}
}
else if (type == WLC_E_SET_SSID)
{
carrier = (status == WLC_E_STATUS_SUCCESS) ? 1 : 0;
if (!priv->auth_pending || !carrier)
{
priv->auth_status = status;
auth = true;
}
}
else if (type == WLC_E_DISASSOC)
{
netdev_carrier_off(&priv->bc_dev);
carrier = 0;
}
if (carrier >= 0)
{
if (carrier)
{
netdev_carrier_on(&priv->bc_dev);
}
else
{
netdev_carrier_off(&priv->bc_dev);
}
}
if (auth && priv->auth_signal)
{
nxsem_post(priv->auth_signal);
}
}
@ -776,7 +815,8 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
{
case WLAN_EID_RSN:
{
FAR wpa_rsn_t *rsn = (FAR wpa_rsn_t *)&ie_buffer[ie_offset + 2];
FAR wpa_rsn_t *rsn = (FAR wpa_rsn_t *)
&ie_buffer[ie_offset + 2];
FAR wpa_akm_t *akm;
if (rsn->version != WPA_VERSION)
@ -791,10 +831,12 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
if (ie_buffer[ie_offset + 1] > suitelen + 2)
{
akm = (FAR wpa_akm_t *)&ie_buffer[ie_offset + suitelen + 2];
akm = (FAR wpa_akm_t *)
&ie_buffer[ie_offset + suitelen + 2];
for (j = 0; j < akm->scount; j++)
{
uint32_t suite = ntohl(*(FAR uint32_t *)&akm->suite[j]);
uint32_t suite = ntohl
(*(FAR uint32_t *)&akm->suite[j]);
if (suite == WLAN_AKM_SUITE_PSK)
{
goto vaild_bss;
@ -806,7 +848,8 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
case WLAN_EID_VENDOR_SPECIFIC:
{
FAR wpa_ie_fixed_t *ie = (wpa_ie_fixed_t *)&ie_buffer[ie_offset];
FAR wpa_ie_fixed_t *ie = (FAR wpa_ie_fixed_t *)
&ie_buffer[ie_offset];
FAR wpa_akm_t *akm;
FAR wpa_rsn_t *rsn;
@ -817,15 +860,19 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
vaild_bss = false;
rsn = (wpa_rsn_t *)&ie_buffer[ie_offset + sizeof(wpa_ie_fixed_t) - 2];
suitelen = sizeof(wpa_ie_fixed_t) + sizeof(*rsn) + rsn->scount *
rsn = (FAR wpa_rsn_t *)&ie_buffer[ie_offset +
sizeof(wpa_ie_fixed_t) - 2];
suitelen = sizeof(wpa_ie_fixed_t) +
sizeof(*rsn) + rsn->scount *
sizeof(wpa_cipher_suite_t) - 2;
if (ie_buffer[ie_offset + 1] + 2 > suitelen)
{
akm = (FAR wpa_akm_t *)&ie_buffer[ie_offset + suitelen];
akm = (FAR wpa_akm_t *)&ie_buffer[ie_offset +
suitelen];
for (j = 0; j < akm->scount; j++)
{
if (*(FAR uint32_t *)&akm->suite[j] == WLAN_WPA_SEL(WLAN_AKM_PSK))
if (*(FAR uint32_t *)&akm->suite[j] ==
WLAN_WPA_SEL(WLAN_AKM_PSK))
{
goto vaild_bss;
}
@ -1131,18 +1178,6 @@ FAR struct bcmf_dev_s *bcmf_allocate_device(void)
goto exit_free_priv;
}
/* Init authentication signal semaphore */
if ((ret = nxsem_init(&priv->auth_signal, 0, 0)) != OK)
{
goto exit_free_priv;
}
if ((ret = nxsem_set_protocol(&priv->auth_signal, SEM_PRIO_NONE)) != OK)
{
goto exit_free_priv;
}
/* Init scan timeout timer */
priv->scan_status = BCMF_SCAN_DISABLED;
@ -1178,7 +1213,7 @@ int bcmf_wl_enable(FAR struct bcmf_dev_s *priv, bool enable)
out_len = 0;
ret = bcmf_cdc_ioctl(priv, CHIP_STA_INTERFACE, true,
enable ? WLC_UP : WLC_DOWN, NULL, &out_len);
enable ? WLC_UP : WLC_DOWN, NULL, &out_len);
/* TODO wait for WLC_E_RADIO event */
@ -1267,7 +1302,7 @@ int bcmf_wl_start_scan(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
value = scan_params.params.scan_type;
out_len = 4;
if (bcmf_cdc_ioctl(priv, CHIP_STA_INTERFACE, true,
WLC_SET_PASSIVE_SCAN, (uint8_t *)&value, &out_len))
WLC_SET_PASSIVE_SCAN, (FAR uint8_t *)&value, &out_len))
{
ret = -EIO;
goto exit_failed;
@ -1873,10 +1908,9 @@ int bcmf_wl_get_rssi(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
int interface;
struct iw_encode_ext *ext;
uint32_t out_len;
wsec_pmk_t psk;
int interface;
interface = bcmf_wl_get_interface(priv, iwr);
@ -1905,9 +1939,10 @@ int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
psk.key_len = ext->key_len;
psk.flags = WSEC_PASSPHRASE;
out_len = sizeof(psk);
return bcmf_cdc_ioctl(priv, interface, true,
WLC_SET_WSEC_PMK, (uint8_t *)&psk, &out_len);
priv->auth_pending = true;
memcpy(&priv->auth_pmk, &psk, sizeof(psk));
return OK;
}
/****************************************************************************
@ -1919,11 +1954,12 @@ int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
int ret;
int interface;
sem_t auth_signal;
uint32_t out_len;
wlc_ssid_t ssid;
scb_val_t scbval;
wlc_ssid_t ssid;
int interface;
int ret;
interface = bcmf_wl_get_interface(priv, iwr);
@ -1932,39 +1968,63 @@ int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
return -EINVAL;
}
if (iwr->u.essid.flags)
out_len = sizeof(scbval);
memset(&scbval, 0x0, out_len);
ret = bcmf_cdc_ioctl(priv, interface, true,
WLC_DISASSOC, (FAR uint8_t *)&scbval, &out_len);
if (ret < 0 || !iwr->u.essid.flags)
{
ssid.ssid_len = iwr->u.essid.length;
memcpy(ssid.SSID, iwr->u.essid.pointer, iwr->u.essid.length);
goto errout_with_auth;
}
/* Configure AP SSID and trig authentication request */
out_len = sizeof(ssid);
if (priv->auth_pending)
{
out_len = sizeof(priv->auth_pmk);
ret = bcmf_cdc_ioctl(priv, interface, true,
WLC_SET_SSID, (uint8_t *)&ssid, &out_len);
WLC_SET_WSEC_PMK,
(FAR uint8_t *)&priv->auth_pmk, &out_len);
if (ret < 0)
{
wlerr("Associate request failure\n");
return ret;
goto errout_with_auth;
}
}
else
{
out_len = sizeof(scbval);
memset(&scbval, 0x0, out_len);
return bcmf_cdc_ioctl(priv, interface, true,
WLC_DISASSOC, (uint8_t *)&scbval, &out_len);
/* Init authentication signal semaphore */
ret = nxsem_init(&auth_signal, 0, 0);
if (ret == OK)
{
ret = nxsem_set_protocol(&auth_signal, SEM_PRIO_NONE);
}
ret = nxsem_tickwait_uninterruptible(&priv->auth_signal,
MSEC2TICK(BCMF_AUTH_TIMEOUT_MS));
wlinfo("semwait done ! %d\n", ret);
if (ret < OK)
{
goto errout_with_auth;
}
priv->auth_signal = &auth_signal;
ssid.ssid_len = iwr->u.essid.length;
memcpy(ssid.SSID, iwr->u.essid.pointer, iwr->u.essid.length);
/* Configure AP SSID and trig authentication request */
out_len = sizeof(ssid);
ret = bcmf_cdc_ioctl(priv, interface, true,
WLC_SET_SSID,
(FAR uint8_t *)&ssid, &out_len);
if (ret == OK)
{
ret = bcmf_sem_wait(priv->auth_signal, BCMF_AUTH_TIMEOUT_MS);
}
priv->auth_signal = NULL;
nxsem_destroy(&auth_signal);
if (ret < 0)
{
wlerr("Associate request timeout\n");
return ret;
goto errout_with_auth;
}
switch (priv->auth_status)
@ -1975,10 +2035,13 @@ int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
default:
wlerr("AP join failed %d\n", priv->auth_status);
return -EINVAL;
ret = -EINVAL;
break;
}
return OK;
errout_with_auth:
priv->auth_pending = false;
return ret;
}
/****************************************************************************
@ -2006,7 +2069,7 @@ int bcmf_wl_get_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
out_len = sizeof(ssid);
ret = bcmf_cdc_ioctl(priv, interface, false,
WLC_GET_SSID, (uint8_t *)&ssid, &out_len);
WLC_GET_SSID, (FAR uint8_t *)&ssid, &out_len);
if (ret == OK)
{
iwr->u.essid.flags = iwr->u.data.flags = 1;

View File

@ -92,8 +92,10 @@ struct bcmf_dev_s
FAR wl_bss_info_t *scan_result; /* Temp buffer that holds results */
unsigned int scan_result_entries; /* Current entries of temp buffer */
sem_t auth_signal; /* Authentication notification signal */
int auth_status; /* Authentication status */
sem_t *auth_signal; /* Authentication notification signal */
uint32_t auth_status; /* Authentication status */
wsec_pmk_t auth_pmk; /* Authentication pmk */
bool auth_pending; /* Authentication pending */
#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER
struct work_s lp_work_ifdown; /* Ifdown work to work queue */