/** * @brief Set wapi enable * * @param priv A pointer to moal_private structure * @param wait_option Wait option * @param enable MTRUE or MFALSE * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status woal_set_wapi_enable(moal_private * priv, t_u8 wait_option, t_u32 enable) { int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_sec_cfg *sec = NULL; mlan_status status = MLAN_STATUS_SUCCESS; ENTER(); /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } /* Fill request buffer */ sec = (mlan_ds_sec_cfg *) req->pbuf; sec->sub_command = MLAN_OID_SEC_CFG_WAPI_ENABLED; req->req_id = MLAN_IOCTL_SEC_CFG; req->action = MLAN_ACT_SET; sec->param.wapi_enabled = enable; /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, wait_option); done: if (req && (status != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return status; }
/** * @brief Get uap statistics * * @param priv A pointer to moal_private structure * @param wait_option Wait option * @param ustats A pointer to mlan_ds_uap_stats structure * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status woal_uap_get_stats(moal_private * priv, t_u8 wait_option, mlan_ds_uap_stats * ustats) { mlan_ds_get_info *info = NULL; mlan_ioctl_req *req = NULL; mlan_status status = MLAN_STATUS_SUCCESS; ENTER(); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); if (req == NULL) { LEAVE(); return MLAN_STATUS_FAILURE; } info = (mlan_ds_get_info *) req->pbuf; info->sub_command = MLAN_OID_GET_STATS; req->req_id = MLAN_IOCTL_GET_INFO; req->action = MLAN_ACT_GET; status = woal_request_ioctl(priv, req, wait_option); if (status == MLAN_STATUS_SUCCESS) { if (ustats) memcpy(ustats, &info->param.ustats, sizeof(mlan_ds_uap_stats)); } if (req && (status != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return status; }
/** * @brief Cancel Host Sleep configuration * * @param priv A pointer to moal_private structure * @param wait_option wait option * * @return MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING, * or MLAN_STATUS_FAILURE */ mlan_status woal_hs_cfg_cancel(moal_private * priv, t_u8 wait_option) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ioctl_req *req = NULL; mlan_ds_pm_cfg *pmcfg = NULL; ENTER(); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); if (req == NULL) { ret = MLAN_STATUS_FAILURE; goto done; } pmcfg = (mlan_ds_pm_cfg *) req->pbuf; pmcfg->sub_command = MLAN_OID_PM_CFG_HS_CFG; req->req_id = MLAN_IOCTL_PM_CFG; req->action = MLAN_ACT_SET; /* Get current Host Sleep configuration */ woal_get_hs_params(priv, wait_option, &pmcfg->param.hs_cfg); pmcfg->param.hs_cfg.conditions = HOST_SLEEP_CFG_CANCEL; pmcfg->param.hs_cfg.is_invoke_hostcmd = MTRUE; ret = woal_request_ioctl(priv, req, wait_option); if (ret != MLAN_STATUS_PENDING) kfree(req); done: LEAVE(); return ret; }
/** * @brief uap BSS control ioctl handler * * @param priv A pointer to moal_private structure * @param wait_option Wait option * @param data BSS control type * @return 0 --success, otherwise fail */ int woal_uap_bss_ctrl(moal_private * priv, t_u8 wait_option, int data) { mlan_ioctl_req *req = NULL; mlan_ds_bss *bss = NULL; int ret = 0; ENTER(); PRINTM(MIOCTL, "ioctl bss ctrl=%d\n", data); if ((data != UAP_BSS_START) && (data != UAP_BSS_STOP) && (data != UAP_BSS_RESET)) { PRINTM(MERROR, "Invalid parameter: %d\n", data); ret = -EINVAL; goto done; } req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { ret = -ENOMEM; goto done; } bss = (mlan_ds_bss *) req->pbuf; switch (data) { case UAP_BSS_START: if (priv->bss_started == MTRUE) { PRINTM(MWARN, "Warning: BSS already started!\n"); // goto done; } bss->sub_command = MLAN_OID_BSS_START; break; case UAP_BSS_STOP: if (priv->bss_started == MFALSE) { PRINTM(MWARN, "Warning: BSS already stopped!\n"); // goto done; } bss->sub_command = MLAN_OID_BSS_STOP; break; case UAP_BSS_RESET: bss->sub_command = MLAN_OID_UAP_BSS_RESET; break; } req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_SET; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } if (data == UAP_BSS_STOP || data == UAP_BSS_RESET) priv->bss_started = MFALSE; done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief uAP set WAPI flag ioctl * * @param priv A pointer to moal_private structure * @param msg A pointer to wapi_msg structure * * @return 0 --success, otherwise fail */ static int woal_uap_set_wapi_flag_ioctl(moal_private * priv, wapi_msg * msg) { t_u8 wapi_psk_ie[] = { 0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14, 0x72, 0x02, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01, 0x00, 0x14, 0x72, 0x01, 0x00, 0x00 }; t_u8 wapi_cert_ie[] = { 0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01, 0x00, 0x14, 0x72, 0x01, 0x00, 0x00 }; mlan_ds_misc_cfg *misc = NULL; mlan_ioctl_req *req = NULL; int ret = 0; ENTER(); woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } misc = (mlan_ds_misc_cfg *) req->pbuf; misc->sub_command = MLAN_OID_MISC_GEN_IE; req->req_id = MLAN_IOCTL_MISC_CFG; req->action = MLAN_ACT_SET; misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE; misc->param.gen_ie.len = sizeof(wapi_psk_ie); if (msg->msg[0] & WAPI_MODE_PSK) { memcpy(misc->param.gen_ie.ie_data, wapi_psk_ie, misc->param.gen_ie.len); } else if (msg->msg[0] & WAPI_MODE_CERT) { memcpy(misc->param.gen_ie.ie_data, wapi_cert_ie, misc->param.gen_ie.len); } else if (msg->msg[0] == 0) { /* disable WAPI in driver */ if (MLAN_STATUS_SUCCESS != woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT, 0)) ret = -EFAULT; woal_enable_wapi(priv, MFALSE); goto done; } else { ret = -EINVAL; goto done; } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } woal_enable_wapi(priv, MTRUE); done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief Get version * * @param priv A pointer to moal_private structure * @param version A pointer to version buffer * @param max_len max length of version buffer * * @return N/A */ void woal_uap_get_version(moal_private * priv, char *version, int max_len) { mlan_ds_get_info *info = NULL; mlan_ioctl_req *req = NULL; mlan_status status = MLAN_STATUS_SUCCESS; ENTER(); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); if (req == NULL) { LEAVE(); return; } info = (mlan_ds_get_info *) req->pbuf; info->sub_command = MLAN_OID_GET_VER_EXT; req->req_id = MLAN_IOCTL_GET_INFO; req->action = MLAN_ACT_GET; status = woal_request_ioctl(priv, req, MOAL_PROC_WAIT); if (status == MLAN_STATUS_SUCCESS) { PRINTM(MINFO, "MOAL UAP VERSION: %s\n", info->param.ver_ext.version_str); snprintf(version, max_len, driver_version, info->param.ver_ext.version_str); } if (req && (status != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return; }
/** * @brief Notify mlan BSS will be removed. * * @param priv A pointer to moal_private structure * * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail */ mlan_status woal_bss_remove(moal_private *priv) { mlan_ioctl_req *req = NULL; mlan_ds_bss *bss = NULL; mlan_status status; ENTER(); /* Allocate an IOCTL request buffer */ req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { status = MLAN_STATUS_FAILURE; goto done; } /* Fill request buffer */ bss = (mlan_ds_bss *)req->pbuf; bss->sub_command = MLAN_OID_BSS_REMOVE; req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_SET; /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, MOAL_CMD_WAIT); done: if (status != MLAN_STATUS_PENDING) kfree(req); LEAVE(); return status; }
/** * @brief Set/Get radio * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * * @return 0 --success, otherwise fail */ static int woal_uap_radio_ctl(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); int ret = 0; mlan_ds_radio_cfg *radio = NULL; mlan_ioctl_req *mreq = NULL; int data[2] = { 0, 0 }; mlan_bss_info bss_info; ENTER(); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_radio_ctl() corrupt data\n"); ret = -EFAULT; goto done; } /* Get user data */ if (copy_from_user(&data, req->ifr_data, sizeof(data))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } if (data[0]) { mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg)); if (mreq == NULL) { ret = -ENOMEM; goto done; } radio = (mlan_ds_radio_cfg *) mreq->pbuf; radio->sub_command = MLAN_OID_RADIO_CTRL; mreq->req_id = MLAN_IOCTL_RADIO_CFG; mreq->action = MLAN_ACT_SET; radio->param.radio_on_off = (t_u32) data[1]; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT)) { ret = -EFAULT; } if (mreq) kfree(mreq); } else { /* Get radio status */ memset(&bss_info, 0, sizeof(bss_info)); woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info); data[1] = bss_info.radio_on; if (copy_to_user(req->ifr_data, data, sizeof(data))) { PRINTM(MERROR, "Copy to user failed\n"); ret = -EFAULT; } } done: LEAVE(); return ret; }
/** * @brief uap station deauth ioctl handler * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * @return 0 --success, otherwise fail */ static int woal_uap_sta_deauth_ioctl(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_ioctl_req *ioctl_req = NULL; mlan_ds_bss *bss = NULL; mlan_deauth_param deauth_param; int ret = 0; ENTER(); memset(&deauth_param, 0, sizeof(mlan_deauth_param)); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_sta_deauth_ioctl() corrupt data\n"); ret = -EFAULT; goto done; } if (copy_from_user(&deauth_param, req->ifr_data, sizeof(mlan_deauth_param))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } PRINTM(MIOCTL, "ioctl deauth station: %02x:%02x:%02x:%02x:%02x:%02x, reason=%d\n", deauth_param.mac_addr[0], deauth_param.mac_addr[1], deauth_param.mac_addr[2], deauth_param.mac_addr[3], deauth_param.mac_addr[4], deauth_param.mac_addr[5], deauth_param.reason_code); ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (ioctl_req == NULL) { ret = -ENOMEM; goto done; } bss = (mlan_ds_bss *) ioctl_req->pbuf; bss->sub_command = MLAN_OID_UAP_DEAUTH_STA; ioctl_req->req_id = MLAN_IOCTL_BSS; ioctl_req->action = MLAN_ACT_SET; memcpy(&bss->param.deauth_param, &deauth_param, sizeof(mlan_deauth_param)); if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; if (copy_to_user(req->ifr_data, &ioctl_req->status_code, sizeof(t_u32))) PRINTM(MERROR, "Copy to user failed!\n"); goto done; } done: if (ioctl_req) kfree(ioctl_req); LEAVE(); return ret; }
/** * @brief Get station info * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * @param mac A pointer to station mac address * @param stainfo A pointer to station_info structure * * @return 0 -- success, otherwise fail */ int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, u8 * mac, struct station_info *stainfo) { moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = -EFAULT; int i = 0; mlan_ds_get_info *info = NULL; mlan_ioctl_req *ioctl_req = NULL; ENTER(); if (priv->media_connected == MFALSE) { PRINTM(MINFO, "cfg80211: Media not connected!\n"); LEAVE(); return -ENOENT; } /* Allocate an IOCTL request buffer */ ioctl_req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); if (ioctl_req == NULL) { ret = -ENOMEM; goto done; } info = (mlan_ds_get_info *) ioctl_req->pbuf; info->sub_command = MLAN_OID_UAP_STA_LIST; ioctl_req->req_id = MLAN_IOCTL_GET_INFO; ioctl_req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { goto done; } for (i = 0; i < info->param.sta_list.sta_count; i++) { if (!memcmp(info->param.sta_list.info[i].mac_address, mac, ETH_ALEN)) { PRINTM(MIOCTL, "Get station: %02x:%02x:%02x:%02x:%02x:%02x RSSI=%d\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], (int) info->param.sta_list.info[i].rssi); stainfo->filled = STATION_INFO_INACTIVE_TIME | STATION_INFO_SIGNAL; stainfo->inactive_time = 0; stainfo->signal = info->param.sta_list.info[i].rssi; ret = 0; break; } } done: if (ioctl_req) kfree(ioctl_req); LEAVE(); return ret; }
/** * @brief Enable/Disable wapi in firmware * * @param priv A pointer to moal_private structure * @param enable MTRUE/MFALSE * * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail */ static mlan_status woal_enable_wapi(moal_private * priv, t_u8 enable) { mlan_ioctl_req *req = NULL; mlan_ds_bss *bss = NULL; mlan_status status; ENTER(); /* Allocate an IOCTL request buffer */ req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { status = MLAN_STATUS_FAILURE; goto done; } /* Fill request buffer */ bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_UAP_BSS_CONFIG; req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_GET; /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT); if (status != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Get AP setting failed! status=%d, error_code=0x%lx\n", status, req->status_code); } /* Change AP default setting */ req->action = MLAN_ACT_SET; if (enable == MFALSE) { bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN; bss->param.bss_config.protocol = PROTOCOL_NO_SECURITY; } else { bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN; bss->param.bss_config.protocol = PROTOCOL_WAPI; } /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT); if (status != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Set AP setting failed! status=%d, error_code=0x%lx\n", status, req->status_code); } if (enable) woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); done: if (req) kfree(req); LEAVE(); return status; }
/** * @brief uap get station list handler * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * @return 0 --success, otherwise fail */ static int woal_uap_get_sta_list_ioctl(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); int ret = 0; mlan_ds_get_info *info = NULL; mlan_ioctl_req *ioctl_req = NULL; ENTER(); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_get_sta_list_ioctl() corrupt data\n"); ret = -EFAULT; goto done; } /* Allocate an IOCTL request buffer */ ioctl_req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); if (ioctl_req == NULL) { ret = -ENOMEM; goto done; } info = (mlan_ds_get_info *) ioctl_req->pbuf; info->sub_command = MLAN_OID_UAP_STA_LIST; ioctl_req->req_id = MLAN_IOCTL_GET_INFO; ioctl_req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } if (ioctl_req->action == MLAN_ACT_GET) { /* Copy to user : sta_list */ if (copy_to_user (req->ifr_data, &info->param.sta_list, sizeof(mlan_ds_sta_list))) { PRINTM(MERROR, "Copy to user failed!\n"); ret = -EFAULT; goto done; } } done: if (ioctl_req) kfree(ioctl_req); LEAVE(); return ret; }
/** * @brief send deauth to all station * * @param A pointer to moal_private * @param mac A pointer to station mac address * * @return 0 -- success, otherwise fail */ static int woal_deauth_all_station(moal_private *priv) { int ret = -EFAULT; int i = 0; mlan_ds_get_info *info = NULL; mlan_ioctl_req *ioctl_req = NULL; mlan_status status = MLAN_STATUS_SUCCESS; ENTER(); if (priv->media_connected == MFALSE) { PRINTM(MINFO, "cfg80211: Media not connected!\n"); LEAVE(); return 0; } PRINTM(MIOCTL, "del all station\n"); /* Allocate an IOCTL request buffer */ ioctl_req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); if (ioctl_req == NULL) { ret = -ENOMEM; goto done; } info = (mlan_ds_get_info *)ioctl_req->pbuf; info->sub_command = MLAN_OID_UAP_STA_LIST; ioctl_req->req_id = MLAN_IOCTL_GET_INFO; ioctl_req->action = MLAN_ACT_GET; status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT); if (status != MLAN_STATUS_SUCCESS) goto done; if (!info->param.sta_list.sta_count) goto done; for (i = 0; i < info->param.sta_list.sta_count; i++) { PRINTM(MIOCTL, "deauth station " MACSTR "\n", MAC2STR(info->param.sta_list.info[i].mac_address)); ret = woal_deauth_station(priv, info->param.sta_list.info[i]. mac_address); } woal_sched_timeout(200); done: if (status != MLAN_STATUS_PENDING) kfree(ioctl_req); return ret; }
/** * @brief uAP set WAPI key ioctl * * @param priv A pointer to moal_private structure * @param msg A pointer to wapi_msg structure * * @return 0 --success, otherwise fail */ static int woal_uap_set_wapi_key_ioctl(moal_private * priv, wapi_msg * msg) { mlan_ioctl_req *req = NULL; mlan_ds_sec_cfg *sec = NULL; int ret = 0; wapi_key_msg *key_msg = NULL; t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ENTER(); if (msg->msg_len != sizeof(wapi_key_msg)) { ret = -EINVAL; goto done; } key_msg = (wapi_key_msg *) msg->msg; req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } sec = (mlan_ds_sec_cfg *) req->pbuf; sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY; req->req_id = MLAN_IOCTL_SEC_CFG; req->action = MLAN_ACT_SET; sec->param.encrypt_key.is_wapi_key = MTRUE; sec->param.encrypt_key.key_len = MLAN_MAX_KEY_LENGTH; memcpy(sec->param.encrypt_key.mac_addr, key_msg->mac_addr, ETH_ALEN); sec->param.encrypt_key.key_index = key_msg->key_id; if (0 == memcmp(key_msg->mac_addr, bcast_addr, ETH_ALEN)) sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY; else sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY; memcpy(sec->param.encrypt_key.key_material, key_msg->key, sec->param.encrypt_key.key_len); if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) ret = -EFAULT; done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief Set/Get system configuration parameters * * @param priv A pointer to moal_private structure * @param action MLAN_ACT_SET or MLAN_ACT_GET * @param sys_cfg A pointer to mlan_uap_bss_param structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status woal_set_get_sys_config(moal_private * priv, t_u16 action, mlan_uap_bss_param * sys_cfg) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_bss *bss = NULL; mlan_ioctl_req *req = NULL; ENTER(); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { ret = MLAN_STATUS_FAILURE; goto done; } bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_UAP_BSS_CONFIG; req->req_id = MLAN_IOCTL_BSS; req->action = action; if (action == MLAN_ACT_SET) { memcpy(&bss->param.bss_config, sys_cfg, sizeof(mlan_uap_bss_param)); } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = MLAN_STATUS_FAILURE; goto done; } if (action == MLAN_ACT_GET) { memcpy(sys_cfg, &bss->param.bss_config, sizeof(mlan_uap_bss_param)); } done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief Send multicast list request to MLAN * * @param priv A pointer to moal_private structure * @param dev A pointer to net_device structure * * @return None */ void woal_request_set_multicast_list(moal_private * priv, struct net_device *dev) { mlan_ioctl_req *req = NULL; mlan_ds_bss *bss = NULL; mlan_status status; ENTER(); /* Allocate an IOCTL request buffer */ req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { PRINTM(MERROR, "%s:Fail to alloc ioctl req buffer\n", __FUNCTION__); goto done; } /* Fill request buffer */ bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_BSS_MULTICAST_LIST; req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_SET; if (dev->flags & IFF_PROMISC) { bss->param.multicast_list.mode = MLAN_PROMISC_MODE; } else if (dev->flags & IFF_ALLMULTI || dev->mc_count > MLAN_MAX_MULTICAST_LIST_SIZE) { bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE; } else { bss->param.multicast_list.mode = MLAN_MULTICAST_MODE; if (dev->mc_count) bss->param.multicast_list.num_multicast_addr = woal_copy_mcast_addr(&bss->param.multicast_list, dev); } /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, MOAL_NO_WAIT); if (status != MLAN_STATUS_PENDING) kfree(req); done: LEAVE(); return; }
/** * @brief Set debug info * * @param priv A pointer to moal_private structure * @param wait_option Wait option * @param debug_info A pointer to mlan_debug_info structure * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status woal_set_debug_info(moal_private * priv, t_u8 wait_option, mlan_debug_info * debug_info) { int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_get_info *info = NULL; mlan_status status = MLAN_STATUS_SUCCESS; ENTER(); if (!debug_info) { ret = -EINVAL; LEAVE(); return MLAN_STATUS_FAILURE; } /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); if (req == NULL) { ret = -ENOMEM; goto done; } /* Fill request buffer */ info = (mlan_ds_get_info *) req->pbuf; info->sub_command = MLAN_OID_GET_DEBUG_INFO; memcpy(&info->param.debug_info, debug_info, sizeof(mlan_debug_info)); req->req_id = MLAN_IOCTL_GET_INFO; req->action = MLAN_ACT_SET; /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, wait_option); done: if (req && (status != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return status; }
/** * @brief Send set MAC address request to MLAN * * @param priv A pointer to moal_private structure * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status woal_request_set_mac_address(moal_private * priv) { mlan_ioctl_req *req = NULL; mlan_ds_bss *bss = NULL; mlan_status status; ENTER(); /* Allocate an IOCTL request buffer */ req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { status = MLAN_STATUS_FAILURE; goto done; } /* Fill request buffer */ bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_BSS_MAC_ADDR; memcpy(&bss->param.mac_addr, priv->current_addr, sizeof(mlan_802_11_mac_addr)); req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_SET; /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, MOAL_CMD_WAIT); if (status == MLAN_STATUS_SUCCESS) { memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN); HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN); } else { PRINTM(MERROR, "set mac address failed! status=%d, error_code=0x%lx\n", status, req->status_code); } done: if (req) kfree(req); LEAVE(); return status; }
/** * @brief Send deauth command to MLAN * * @param priv A pointer to moal_private structure * @param wait_option Wait option * @param mac MAC address to deauthenticate * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status woal_disconnect(moal_private * priv, t_u8 wait_option, t_u8 * mac) { mlan_ioctl_req *req = NULL; mlan_ds_bss *bss = NULL; mlan_status status; ENTER(); /* Allocate an IOCTL request buffer */ req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { status = MLAN_STATUS_FAILURE; goto done; } /* Fill request buffer */ bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_BSS_STOP; if (mac) memcpy((t_u8 *) & bss->param.bssid, mac, sizeof(mlan_802_11_mac_addr)); req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_SET; /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, wait_option); done: if (req) kfree(req); #ifdef REASSOCIATION priv->reassoc_required = MFALSE; #endif /* REASSOCIATION */ LEAVE(); return status; }
/** * @brief Send bss_start command to MLAN * * @param priv A pointer to moal_private structure * @param wait_option Wait option * @param ssid_bssid A point to mlan_ssid_bssid structure * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status woal_bss_start(moal_private * priv, t_u8 wait_option, mlan_ssid_bssid * ssid_bssid) { mlan_ioctl_req *req = NULL; mlan_ds_bss *bss = NULL; mlan_status status; ENTER(); /* Stop the O.S. TX queue if needed */ if (!netif_queue_stopped(priv->netdev)) netif_stop_queue(priv->netdev); /* Allocate an IOCTL request buffer */ req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { status = MLAN_STATUS_FAILURE; goto done; } /* Fill request buffer */ bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_BSS_START; if (ssid_bssid) memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid)); req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_SET; /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, wait_option); done: if (req) kfree(req); LEAVE(); return status; }
/** * @brief Get Host Sleep parameters * * @param priv A pointer to moal_private structure * @param wait_option Wait option (MOAL_WAIT or MOAL_NO_WAIT) * @param hscfg A pointer to mlan_ds_hs_cfg structure * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status woal_get_hs_params(moal_private * priv, t_u8 wait_option, mlan_ds_hs_cfg * hscfg) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_pm_cfg *pmcfg = NULL; mlan_ioctl_req *req = NULL; ENTER(); /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } /* Fill request buffer */ pmcfg = (mlan_ds_pm_cfg *) req->pbuf; pmcfg->sub_command = MLAN_OID_PM_CFG_HS_CFG; req->req_id = MLAN_IOCTL_PM_CFG; req->action = MLAN_ACT_GET; /* Send IOCTL request to MLAN */ ret = woal_request_ioctl(priv, req, wait_option); if (ret == MLAN_STATUS_SUCCESS) { if (hscfg) { memcpy(hscfg, &pmcfg->param.hs_cfg, sizeof(mlan_ds_hs_cfg)); } } done: if (req && (ret != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return ret; }
/** * @brief send deauth to station * * @param A pointer to moal_private * @param mac A pointer to station mac address * * @return 0 -- success, otherwise fail */ static int woal_deauth_station(moal_private *priv, u8 *mac_addr) { mlan_ioctl_req *ioctl_req = NULL; mlan_ds_bss *bss = NULL; int ret = 0; mlan_status status = MLAN_STATUS_SUCCESS; ENTER(); ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (ioctl_req == NULL) { ret = -ENOMEM; goto done; } bss = (mlan_ds_bss *)ioctl_req->pbuf; bss->sub_command = MLAN_OID_UAP_DEAUTH_STA; ioctl_req->req_id = MLAN_IOCTL_BSS; ioctl_req->action = MLAN_ACT_SET; memcpy(bss->param.deauth_param.mac_addr, mac_addr, MLAN_MAC_ADDR_LENGTH); #define REASON_CODE_DEAUTH_LEAVING 3 bss->param.deauth_param.reason_code = REASON_CODE_DEAUTH_LEAVING; status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT); if (status != MLAN_STATUS_SUCCESS) { ret = -EFAULT; goto done; } done: if (status != MLAN_STATUS_PENDING) kfree(ioctl_req); LEAVE(); return ret; }
/** * @brief Extended version of encoding configuration * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_encode_ext(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; moal_private *priv = (moal_private *) netdev_priv(dev); int key_index; t_u8 *pkey_material = NULL; mlan_ioctl_req *req = NULL; mlan_ds_sec_cfg *sec = NULL; mlan_uap_bss_param sys_cfg; wep_key *pwep_key = NULL; int ret = 0; ENTER(); key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1; if (key_index < 0 || key_index > 5) { ret = -EINVAL; goto done; } if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) { ret = -EINVAL; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); pkey_material = (t_u8 *) (ext + 1); /* Disable Key */ if ((dwrq->flags & IW_ENCODE_DISABLED) && !ext->key_len) { sys_cfg.protocol = PROTOCOL_NO_SECURITY; } else if (ext->alg == IW_ENCODE_ALG_WEP) { sys_cfg.protocol = PROTOCOL_STATIC_WEP; /* Set WEP key */ switch (key_index) { case 0: pwep_key = &sys_cfg.wep_cfg.key0; break; case 1: pwep_key = &sys_cfg.wep_cfg.key1; break; case 2: pwep_key = &sys_cfg.wep_cfg.key2; break; case 3: pwep_key = &sys_cfg.wep_cfg.key3; break; } if (pwep_key) { pwep_key->key_index = key_index; pwep_key->is_default = MTRUE; pwep_key->length = ext->key_len; memcpy(pwep_key->key, pkey_material, ext->key_len); } } else { /* Set GTK/PTK key */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } sec = (mlan_ds_sec_cfg *) req->pbuf; sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY; req->req_id = MLAN_IOCTL_SEC_CFG; req->action = MLAN_ACT_SET; sec->param.encrypt_key.key_len = ext->key_len; sec->param.encrypt_key.key_index = key_index; memcpy(sec->param.encrypt_key.key_material, pkey_material, ext->key_len); memcpy(sec->param.encrypt_key.mac_addr, ext->addr.sa_data, ETH_ALEN); sec->param.encrypt_key.key_flags = ext->ext_flags; if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { memcpy(sec->param.encrypt_key.pn, (t_u8 *) ext->rx_seq, SEQ_MAX_SIZE); DBG_HEXDUMP(MCMD_D, "Uap Rx PN", sec->param.encrypt_key.pn, SEQ_MAX_SIZE); } if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) { memcpy(sec->param.encrypt_key.pn, (t_u8 *) ext->tx_seq, SEQ_MAX_SIZE); DBG_HEXDUMP(MCMD_D, "Uap Tx PN", sec->param.encrypt_key.pn, SEQ_MAX_SIZE); } PRINTM(MIOCTL, "set uap wpa key key_index=%d, key_len=%d key_flags=0x%x " MACSTR "\n", key_index, ext->key_len, sec->param.encrypt_key.key_flags, MAC2STR(sec->param.encrypt_key.mac_addr)); DBG_HEXDUMP(MCMD_D, "uap wpa key", pkey_material, ext->key_len); #define IW_ENCODE_ALG_AES_CMAC 5 if (ext->alg == IW_ENCODE_ALG_AES_CMAC) sec->param.encrypt_key.key_flags |= KEY_FLAG_AES_MCAST_IGTK; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; } /* Cipher set will be done in set generic IE */ priv->pairwise_cipher = ext->alg; priv->group_cipher = ext->alg; goto done; /* No AP configuration */ } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief Request MLME operation * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0--success, otherwise fail */ static int woal_set_mlme(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { struct iw_mlme *mlme = (struct iw_mlme *)extra; moal_private *priv = (moal_private *) netdev_priv(dev); mlan_ds_bss *bss = NULL; mlan_ds_get_info *pinfo = NULL; mlan_ioctl_req *req = NULL; mlan_ds_sta_list *sta_list = NULL; const t_u8 bc_addr[] = { 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF }; t_u8 sta_addr[ETH_ALEN]; int ret = 0, i; ENTER(); memset(sta_addr, 0, ETH_ALEN); if ((mlme->cmd == IW_MLME_DEAUTH) || (mlme->cmd == IW_MLME_DISASSOC)) { memcpy(sta_addr, (t_u8 *) mlme->addr.sa_data, ETH_ALEN); PRINTM(MIOCTL, "Deauth station: " MACSTR ", " "reason=%d\n", MAC2STR(sta_addr), mlme->reason_code); /* FIXME: For flushing all stations we need to use zero MAC, but right now the FW does not support this. So, manually delete each one individually. */ /* If deauth all station, get the connected STA list first */ if (!memcmp(bc_addr, sta_addr, ETH_ALEN)) { PRINTM(MIOCTL, "Deauth all stations\n"); req = woal_alloc_mlan_ioctl_req(sizeof (mlan_ds_get_info)); if (req == NULL) { LEAVE(); return -ENOMEM; } pinfo = (mlan_ds_get_info *) req->pbuf; pinfo->sub_command = MLAN_OID_UAP_STA_LIST; req->req_id = MLAN_IOCTL_GET_INFO; req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } sta_list = (mlan_ds_sta_list *) kmalloc(sizeof(mlan_ds_sta_list), GFP_KERNEL); if (sta_list == NULL) { PRINTM(MERROR, "Memory allocation failed!\n"); ret = -ENOMEM; goto done; } memcpy(sta_list, &pinfo->param.sta_list, sizeof(mlan_ds_sta_list)); if (req) { kfree(req); req = NULL; } } req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { ret = -ENOMEM; goto done; } bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_UAP_DEAUTH_STA; req->req_id = MLAN_IOCTL_BSS; req->action = MLAN_ACT_SET; if (!memcmp(bc_addr, sta_addr, ETH_ALEN)) { for (i = 0; i < sta_list->sta_count; i++) { memcpy(bss->param.deauth_param.mac_addr, sta_list->info[i].mac_address, ETH_ALEN); bss->param.deauth_param.reason_code = mlme->reason_code; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } } } else { memcpy(bss->param.deauth_param.mac_addr, sta_addr, ETH_ALEN); bss->param.deauth_param.reason_code = mlme->reason_code; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } } } done: if (req) kfree(req); if (sta_list) kfree(sta_list); LEAVE(); return ret; }
/** * @brief Extended version of encoding configuration * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_encode_ext(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; moal_private *priv = (moal_private *) netdev_priv(dev); int key_index; t_u8 *pkey_material = NULL; mlan_ioctl_req *req = NULL; mlan_ds_sec_cfg *sec = NULL; mlan_uap_bss_param sys_cfg; wep_key *pwep_key = NULL; int ret = 0; ENTER(); key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1; if (key_index < 0 || key_index > 3) { ret = -EINVAL; goto done; } if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) { ret = -EINVAL; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); pkey_material = (t_u8 *) (ext + 1); /* Disable Key */ if ((dwrq->flags & IW_ENCODE_DISABLED) && !ext->key_len) { sys_cfg.protocol = PROTOCOL_NO_SECURITY; } else if (ext->alg == IW_ENCODE_ALG_WEP) { sys_cfg.protocol = PROTOCOL_STATIC_WEP; /* Set WEP key */ switch (key_index) { case 0: pwep_key = &sys_cfg.wep_cfg.key0; break; case 1: pwep_key = &sys_cfg.wep_cfg.key1; break; case 2: pwep_key = &sys_cfg.wep_cfg.key2; break; case 3: pwep_key = &sys_cfg.wep_cfg.key3; break; } pwep_key->key_index = key_index; pwep_key->is_default = MTRUE; pwep_key->length = ext->key_len; memcpy(pwep_key->key, pkey_material, ext->key_len); } else { sys_cfg.protocol = PROTOCOL_WPA2_MIXED; if (ext->alg == IW_ENCODE_ALG_TKIP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP; sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_TKIP; sys_cfg.wpa_cfg.group_cipher = CIPHER_TKIP; } if (ext->alg == IW_ENCODE_ALG_CCMP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_AES_CCMP; sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP; sys_cfg.wpa_cfg.group_cipher = CIPHER_AES_CCMP; } /* Set WPA key */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } sec = (mlan_ds_sec_cfg *) req->pbuf; sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY; req->req_id = MLAN_IOCTL_SEC_CFG; req->action = MLAN_ACT_SET; sec->param.encrypt_key.key_len = ext->key_len; sec->param.encrypt_key.key_index = key_index; memcpy(sec->param.encrypt_key.key_material, pkey_material, ext->key_len); memcpy(sec->param.encrypt_key.mac_addr, ext->addr.sa_data, ETH_ALEN); if ((ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && !key_index) { key_index = 1; sec->param.encrypt_key.key_index = key_index; PRINTM(MWARN, "Key index changed for GTK: %ld\n", sec->param.encrypt_key.key_index); } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; } } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief Set IE * * Pass an opaque block of data, expected to be IEEE IEs, to the driver * for eventual passthrough to the firmware in an associate/join * (and potentially start) command. * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_gen_ie(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { int ret = 0; moal_private *priv = (moal_private *) netdev_priv(dev); mlan_ds_misc_cfg *misc = NULL; mlan_ioctl_req *req = NULL; mlan_uap_bss_param sys_cfg; IEEEtypes_Header_t *ie_hdr = NULL; IEEEtypes_Header_t *ie_hdr1 = NULL; ENTER(); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } req->req_id = MLAN_IOCTL_MISC_CFG; misc = (mlan_ds_misc_cfg *) req->pbuf; misc->sub_command = MLAN_OID_MISC_CUSTOM_IE; misc->param.cust_ie.type = 0x0169; /* TLV_TYPE_MGMT_IE */ req->action = MLAN_ACT_SET; if (dwrq->length > MAX_IE_SIZE) { ret = -EFAULT; goto done; } misc->param.cust_ie.len = dwrq->length + sizeof(custom_ie) - MAX_IE_SIZE; misc->param.cust_ie.ie_data_list[0].ie_index = 0; misc->param.cust_ie.ie_data_list[0].mgmt_subtype_mask = 0xffff; misc->param.cust_ie.ie_data_list[0].ie_length = dwrq->length; memcpy(misc->param.cust_ie.ie_data_list[0].ie_buffer, extra, dwrq->length); if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); ie_hdr = (IEEEtypes_Header_t *) extra; if (ie_hdr->element_id == WPA_IE) sys_cfg.protocol = PROTOCOL_WPA; else if (ie_hdr->element_id == RSN_IE) sys_cfg.protocol = PROTOCOL_WPA2; if (dwrq->length > (ie_hdr->len + sizeof(IEEEtypes_Header_t))) { ie_hdr1 = (IEEEtypes_Header_t *) ((t_u8 *) extra + ie_hdr->len + sizeof(IEEEtypes_Header_t)); if ((ie_hdr->element_id == WPA_IE && ie_hdr1->element_id == RSN_IE) || (ie_hdr->element_id == RSN_IE && ie_hdr1->element_id == WPA_IE)) { sys_cfg.protocol = PROTOCOL_WPA2_MIXED; } } if (sys_cfg.protocol) { if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } } done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief Initialize the uAP wiphy * * @param priv A pointer to moal_private structure * @param wait_option Wait option * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status woal_cfg80211_uap_init_wiphy(moal_private * priv, t_u8 wait_option) { struct wiphy *wiphy; mlan_uap_bss_param ap_cfg; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; t_u32 hw_dev_cap; ENTER(); if (priv->wdev) wiphy = priv->wdev->wiphy; else { PRINTM(MERROR, "Invalid parameter when init wiphy.\n"); LEAVE(); return MLAN_STATUS_FAILURE; } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, wait_option, &ap_cfg)) { LEAVE(); return MLAN_STATUS_FAILURE; } /* Get 11n tx parameters from MLAN */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { LEAVE(); return MLAN_STATUS_FAILURE; } cfg_11n = (mlan_ds_11n_cfg *) req->pbuf; cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG; req->req_id = MLAN_IOCTL_11N_CFG; req->action = MLAN_ACT_GET; cfg_11n->param.htcap_cfg.hw_cap_req = MTRUE; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { kfree(req); LEAVE(); return MLAN_STATUS_FAILURE; } hw_dev_cap = cfg_11n->param.htcap_cfg.htcap; /* Get supported MCS sets */ memset(req->pbuf, 0, sizeof(mlan_ds_11n_cfg)); cfg_11n->sub_command = MLAN_OID_11N_CFG_SUPPORTED_MCS_SET; req->req_id = MLAN_IOCTL_11N_CFG; req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { kfree(req); LEAVE(); return MLAN_STATUS_FAILURE; } /* Initialize parameters for 2GHz and 5GHz bands */ woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, hw_dev_cap, cfg_11n->param.supported_mcs_set); /* For 2.4G band only card, this shouldn't be set */ if (wiphy->bands[IEEE80211_BAND_5GHZ]) woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, hw_dev_cap, cfg_11n->param.supported_mcs_set); if (req) kfree(req); /* Set retry limit count to wiphy */ wiphy->retry_long = (t_u8) ap_cfg.retry_limit; wiphy->retry_short = (t_u8) ap_cfg.retry_limit; wiphy->max_scan_ie_len = MAX_IE_SIZE; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) wiphy->mgmt_stypes = ieee80211_uap_mgmt_stypes; #endif /* Set RTS threshold to wiphy */ wiphy->rts_threshold = (t_u32) ap_cfg.rts_threshold; /* Set fragment threshold to wiphy */ wiphy->frag_threshold = (t_u32) ap_cfg.frag_threshold; LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief uap BSS config ioctl handler * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * @return 0 --success, otherwise fail */ static int woal_uap_bss_cfg_ioctl(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); int ret = 0; mlan_ds_bss *bss = NULL; mlan_ioctl_req *ioctl_req = NULL; int offset = 0; t_u32 action = 0; ENTER(); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_bss_cfg_ioctl() corrupt data\n"); ret = -EFAULT; goto done; } /* Get action */ if (copy_from_user(&action, req->ifr_data + offset, sizeof(action))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } offset += sizeof(action); /* Allocate an IOCTL request buffer */ ioctl_req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (ioctl_req == NULL) { ret = -ENOMEM; goto done; } bss = (mlan_ds_bss *) ioctl_req->pbuf; bss->sub_command = MLAN_OID_UAP_BSS_CONFIG; ioctl_req->req_id = MLAN_IOCTL_BSS; if (action == 1) { ioctl_req->action = MLAN_ACT_SET; } else { ioctl_req->action = MLAN_ACT_GET; } if (ioctl_req->action == MLAN_ACT_SET) { /* Get the BSS config from user */ if (copy_from_user (&bss->param.bss_config, req->ifr_data + offset, sizeof(mlan_uap_bss_param))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } if (ioctl_req->action == MLAN_ACT_GET) { offset = sizeof(action); /* Copy to user : BSS config */ if (copy_to_user (req->ifr_data + offset, &bss->param.bss_config, sizeof(mlan_uap_bss_param))) { PRINTM(MERROR, "Copy to user failed!\n"); ret = -EFAULT; goto done; } } done: if (ioctl_req) kfree(ioctl_req); LEAVE(); return ret; }
/** * @brief uap power mode ioctl handler * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * @return 0 --success, otherwise fail */ static int woal_uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_ioctl_req *ioctl_req = NULL; mlan_ds_pm_cfg *pm_cfg = NULL; mlan_ds_ps_mgmt ps_mgmt; int ret = 0; ENTER(); memset(&ps_mgmt, 0, sizeof(mlan_ds_ps_mgmt)); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_power_mode_ioctl() corrupt data\n"); ret = -EFAULT; goto done; } if (copy_from_user(&ps_mgmt, req->ifr_data, sizeof(mlan_ds_ps_mgmt))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } PRINTM(MIOCTL, "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d " "inact_to=%d min_awake=%d max_awake=%d\n", ps_mgmt.flags, (int) ps_mgmt.ps_mode, (int) ps_mgmt.sleep_param.ctrl_bitmap, (int) ps_mgmt.sleep_param.min_sleep, (int) ps_mgmt.sleep_param.max_sleep, (int) ps_mgmt.inact_param.inactivity_to, (int) ps_mgmt.inact_param.min_awake, (int) ps_mgmt.inact_param.max_awake); if (ps_mgmt. flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM | PS_FLAG_INACT_SLEEP_PARAM)) { PRINTM(MERROR, "Invalid parameter: flags = 0x%x\n", ps_mgmt.flags); ret = -EINVAL; goto done; } if (ps_mgmt.ps_mode > PS_MODE_INACTIVITY) { PRINTM(MERROR, "Invalid parameter: ps_mode = %d\n", (int) ps_mgmt.flags); ret = -EINVAL; goto done; } ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); if (ioctl_req == NULL) { ret = -ENOMEM; goto done; } pm_cfg = (mlan_ds_pm_cfg *) ioctl_req->pbuf; pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE; ioctl_req->req_id = MLAN_IOCTL_PM_CFG; if (ps_mgmt.flags) { ioctl_req->action = MLAN_ACT_SET; memcpy(&pm_cfg->param.ps_mgmt, &ps_mgmt, sizeof(mlan_ds_ps_mgmt)); } else { ioctl_req->action = MLAN_ACT_GET; } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; if (copy_to_user(req->ifr_data, &ioctl_req->status_code, sizeof(t_u32))) PRINTM(MERROR, "Copy to user failed!\n"); goto done; } if (!ps_mgmt.flags) { /* Copy to user */ if (copy_to_user (req->ifr_data, &pm_cfg->param.ps_mgmt, sizeof(mlan_ds_ps_mgmt))) { PRINTM(MERROR, "Copy to user failed!\n"); ret = -EFAULT; goto done; } } done: if (ioctl_req) kfree(ioctl_req); LEAVE(); return ret; }
/** * @brief Set/Get tx rate * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * * @return 0 --success, otherwise fail */ static int woal_uap_tx_rate_cfg(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); int data[2] = { 0, 0 }; int ret = 0; mlan_ds_rate *rate = NULL; mlan_ioctl_req *mreq = NULL; ENTER(); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_radio_ctl() corrupt data\n"); ret = -EFAULT; goto done; } /* Get user data */ if (copy_from_user(&data, req->ifr_data, sizeof(data))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate)); if (mreq == NULL) { ret = -ENOMEM; goto done; } rate = (mlan_ds_rate *) mreq->pbuf; rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX; rate->sub_command = MLAN_OID_RATE_CFG; mreq->req_id = MLAN_IOCTL_RATE; if (!data[0]) mreq->action = MLAN_ACT_GET; else { mreq->action = MLAN_ACT_SET; if (data[1] == AUTO_RATE) rate->param.rate_cfg.is_rate_auto = 1; else { if ((data[1] != MLAN_RATE_INDEX_MCS32) && ((data[1] < 0) || (data[1] > MLAN_RATE_INDEX_MCS7))) { ret = -EINVAL; goto done; } } rate->param.rate_cfg.rate = data[1]; } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } if (data[0]) { priv->rate_index = data[1]; } else { if (rate->param.rate_cfg.is_rate_auto) data[1] = AUTO_RATE; else data[1] = rate->param.rate_cfg.rate; if (copy_to_user(req->ifr_data, data, sizeof(data))) { PRINTM(MERROR, "Copy to user failed\n"); ret = -EFAULT; } } done: if (mreq) kfree(mreq); LEAVE(); return ret; }