Commit cc721287 authored by Sujith Manoharan's avatar Sujith Manoharan Committed by John W. Linville

ath9k_htc: Fix packet injection

To inject a packet in monitor mode, a dummy station has
to be associated with the monitor interface in the target.
Failing to do this would result in a firmware crash on the device.
Signed-off-by: default avatarSujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a8851d10
...@@ -235,16 +235,38 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, ...@@ -235,16 +235,38 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
return ret; return ret;
} }
static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath9k_htc_target_vif hvif;
int ret = 0;
u8 cmd_rsp;
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
hvif.index = 0; /* Should do for now */
WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
priv->nvifs--;
}
static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
{ {
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath9k_htc_target_vif hvif; struct ath9k_htc_target_vif hvif;
struct ath9k_htc_target_sta tsta;
int ret = 0; int ret = 0;
u8 cmd_rsp; u8 cmd_rsp;
if (priv->nvifs > 0) if (priv->nvifs > 0)
return -ENOBUFS; return -ENOBUFS;
if (priv->nstations >= ATH9K_HTC_MAX_STA)
return -ENOBUFS;
/*
* Add an interface.
*/
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
...@@ -257,23 +279,57 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) ...@@ -257,23 +279,57 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
return ret; return ret;
priv->nvifs++; priv->nvifs++;
/*
* Associate a station with the interface for packet injection.
*/
memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN);
tsta.is_vif_sta = 1;
tsta.sta_index = priv->nstations;
tsta.vif_index = hvif.index;
tsta.maxampdu = 0xffff;
WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
if (ret) {
ath_err(common, "Unable to add station entry for monitor mode\n");
goto err_vif;
}
priv->nstations++;
return 0; return 0;
err_vif:
/*
* Remove the interface from the target.
*/
__ath9k_htc_remove_monitor_interface(priv);
return ret;
} }
static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
{ {
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath9k_htc_target_vif hvif;
int ret = 0; int ret = 0;
u8 cmd_rsp; u8 cmd_rsp, sta_idx;
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); __ath9k_htc_remove_monitor_interface(priv);
memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
hvif.index = 0; /* Should do for now */ sta_idx = 0; /* Only single interface, for now */
WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
priv->nvifs--;
WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
if (ret) {
ath_err(common, "Unable to remove station entry for monitor mode\n");
return ret; return ret;
}
priv->nstations--;
return 0;
} }
static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment