/** * @brief Set AP configuration * * @param priv A pointer to moal_private structure * @param wrq A pointer to user data * * @return 0 --success, otherwise fail */ static int woal_uap_set_ap_cfg(moal_private * priv, struct iwreq *wrq) { int ret = 0; static t_s8 buf[MAX_BUF_LEN]; mlan_uap_bss_param sys_config; int restart = 0; ENTER(); #define MIN_AP_CFG_CMD_LEN 16 /* strlen("ASCII_CMD=AP_CFG") */ if ((wrq->u.data.length - 1) <= MIN_AP_CFG_CMD_LEN) { PRINTM(MERROR, "Invalid length of command\n"); ret = -EINVAL; goto done; } memset(buf, 0, MAX_BUF_LEN); memcpy(buf, wrq->u.data.pointer, wrq->u.data.length); /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_config); /* Setting the default values */ sys_config.channel = 6; sys_config.preamble_type = 0; if ((ret = woal_uap_ap_cfg_parse_data(&sys_config, buf))) goto done; /* If BSS already started stop it first and restart after changing the setting */ if (priv->bss_started == MTRUE) { if ((ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP))) goto done; restart = 1; } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, &sys_config)) { ret = -EFAULT; goto done; } /* Start the BSS after successful configuration */ if (restart) ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); done: LEAVE(); return ret; }
/** * @brief reset AP or GO parameters * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * * @return 0 -- success, otherwise fail */ int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { moal_private *priv = (moal_private *)woal_get_netdev_priv(dev); int ret = 0; #ifdef STA_SUPPORT moal_private *pmpriv = NULL; #endif ENTER(); PRINTM(MMSG, "wlan: Stoping AP\n"); woal_deauth_all_station(priv); /* if the bss is still running, then stop it */ if (priv->bss_started == MTRUE) { if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT, UAP_BSS_STOP)) { ret = -EFAULT; goto done; } if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_RESET)) { ret = -EFAULT; goto done; } /* Set WLAN MAC addresses */ if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) { PRINTM(MERROR, "Set MAC address failed\n"); ret = -EFAULT; goto done; } } woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT); #ifdef STA_SUPPORT if (!woal_is_any_interface_active(priv->phandle)) { pmpriv = woal_get_priv((moal_handle *)priv->phandle, MLAN_BSS_ROLE_STA); if (pmpriv) woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME, PASSIVE_SCAN_CHAN_TIME, SPECIFIC_SCAN_CHAN_TIME); } #endif priv->cipher = 0; memset(priv->uap_wep_key, 0, sizeof(priv->uap_wep_key)); priv->channel = 0; PRINTM(MMSG, "wlan: AP stopped\n"); done: LEAVE(); return ret; }
/** * @brief uap bss control 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_ctrl_ioctl(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); int ret = 0, data = 0; ENTER(); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_bss_ctrl() corrupt data\n"); ret = -EFAULT; goto done; } if (copy_from_user(&data, req->ifr_data, sizeof(data))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, data); done: 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 reset AP or GO parameters * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * * @return 0 -- success, otherwise fail */ int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); PRINTM(MIOCTL, "del beacon\n"); /* if the bss is still running, then stop it */ if (priv->bss_started == MTRUE) { if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP)) { ret = -EFAULT; goto done; } if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_RESET)) { ret = -EFAULT; goto done; } } #if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) /* clear BEACON WPS/P2P IE */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON_WPS_P2P)) { ret = -EFAULT; goto done; } #endif /* clear mgmt frame ies */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | MGMT_MASK_ASSOC_RESP)) { ret = -EFAULT; goto done; } priv->cipher = 0; priv->key_len = 0; done: LEAVE(); return ret; }
/** * @brief Change the AP BSSID * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param awrq A pointer to iw_param structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra) { int ret = 0; moal_private *priv = (moal_private *) netdev_priv(dev); const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 }; ENTER(); if (awrq->sa_family != ARPHRD_ETHER) { ret = -EINVAL; goto done; } PRINTM(MINFO, "ASSOC: WAP: uAP bss : " MACSTR "\n", MAC2STR((t_u8 *) awrq->sa_data)); /* * Using this ioctl to start/stop the BSS, return if bss * is already started/stopped. */ if (memcmp(zero_mac, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) { if (priv->bss_started == MFALSE) ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); else PRINTM(MINFO, "BSS is already started.\n"); } else { /* zero_mac means bss_stop */ if (priv->bss_started == MTRUE) ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); else PRINTM(MINFO, "BSS is already stopped.\n"); } done: 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 ioctl function for wireless IOCTLs * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * @param cmd Command * * @return 0 --success, otherwise fail */ int woal_uap_do_priv_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { moal_private *priv = (moal_private *)netdev_priv(dev); struct iwreq *wrq = (struct iwreq *)req; int ret = 0; ENTER(); switch (cmd) { case WOAL_UAP_SETNONE_GETNONE: switch (wrq->u.data.flags) { case WOAL_UAP_START: break; case WOAL_UAP_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; case WOAL_AP_BSS_START: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); break; case WOAL_AP_BSS_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; default: ret = -EINVAL; break; } break; case WOAL_UAP_SETONEINT_GETWORDCHAR: switch (wrq->u.data.flags) { case WOAL_UAP_VERSION: ret = woal_get_driver_version(priv, req); break; case WOAL_UAP_VEREXT: ret = woal_get_driver_verext(priv, req); break; default: ret = -EOPNOTSUPP; break; } break; case WOAL_UAP_SET_GET_256_CHAR: switch (wrq->u.data.flags) { case WOAL_WL_FW_RELOAD: break; case WOAL_AP_SET_CFG: ret = woal_uap_set_ap_cfg(priv, wrq->u.data.pointer, wrq->u.data.length); break; default: ret = -EINVAL; break; } break; #if defined(WIFI_DIRECT_SUPPORT) #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) case WOAL_UAP_SETONEINT_GETONEINT: switch (wrq->u.data.flags) { case WOAL_UAP_SET_GET_BSS_ROLE: ret = woal_set_get_bss_role(priv, wrq); break; default: ret = -EINVAL; break; } break; #endif #endif case WOAL_UAP_HOST_CMD: ret = woal_host_command(priv, wrq); break; case WOAL_UAP_FROYO_START: break; case WOAL_UAP_FROYO_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; case WOAL_UAP_FROYO_AP_BSS_START: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); break; case WOAL_UAP_FROYO_AP_BSS_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; case WOAL_UAP_FROYO_WL_FW_RELOAD: break; case WOAL_UAP_FROYO_AP_SET_CFG: ret = woal_uap_set_ap_cfg(priv, wrq->u.data.pointer, wrq->u.data.length); break; default: ret = -EINVAL; break; } LEAVE(); return ret; }
/** * @brief initialize AP or GO parameters * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * @param params A pointer to beacon_parameters structure * @return 0 -- success, otherwise fail */ int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) #endif { moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); PRINTM(MIOCTL, "add beacon\n"); #ifdef STA_CFG80211 /*** cancel pending scan */ woal_cancel_scan(priv, MOAL_IOCTL_WAIT); #endif if (params != NULL) { /* bss config */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) { ret = -EFAULT; goto done; } /* set mgmt frame ies */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, #if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) params->tail, params->tail_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) params->beacon. tail, params->beacon. tail_len, params->beacon. proberesp_ies, params->beacon. proberesp_ies_len, params->beacon. assocresp_ies, params->beacon. assocresp_ies_len, #else params->tail, params->tail_len, params-> proberesp_ies, params-> proberesp_ies_len, params-> assocresp_ies, params-> assocresp_ies_len, #endif NULL, 0, MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | MGMT_MASK_ASSOC_RESP #endif )) { ret = -EFAULT; goto done; } } /* if the bss is stopped, then start it */ if (priv->bss_started == MFALSE) { if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START)) { ret = -EFAULT; goto done; } } done: LEAVE(); return ret; }
/** * @brief ioctl function for wireless IOCTLs * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * @param cmd Command * * @return 0 --success, otherwise fail */ int woal_uap_do_priv_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { moal_private *priv = (moal_private *) netdev_priv(dev); struct iwreq *wrq = (struct iwreq *) req; int ret = 0; ENTER(); switch (cmd) { case WOAL_UAP_SETNONE_GETNONE: switch (wrq->u.data.flags) { case WOAL_UAP_START: break; case WOAL_UAP_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; case WOAL_AP_BSS_START: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); break; case WOAL_AP_BSS_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; default: ret = -EINVAL; break; } break; case WOAL_UAP_SET_GET_256_CHAR: switch (wrq->u.data.flags) { case WOAL_WL_FW_RELOAD: ret = woal_uap_wl_fw_reload(priv, wrq);; break; case WOAL_AP_SET_CFG: ret = woal_uap_set_ap_cfg(priv, wrq); break; default: ret = -EINVAL; break; } break; case WOAL_UAP_HOST_CMD: ret = woal_host_command(priv, wrq); break; case WOAL_UAP_FROYO_START: ret = 0; break; case WOAL_UAP_FROYO_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; case WOAL_UAP_FROYO_AP_BSS_START: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); break; case WOAL_UAP_FROYO_AP_BSS_STOP: ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP); break; case WOAL_UAP_FROYO_WL_FW_RELOAD: ret = woal_uap_wl_fw_reload(priv, wrq); break; case WOAL_UAP_FROYO_AP_SET_CFG: ret = woal_uap_set_ap_cfg(priv, wrq); break; default: ret = -EINVAL; break; } LEAVE(); return ret; }
/** * @brief initialize AP or GO parameters * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * @param params A pointer to beacon_parameters structure * @return 0 -- success, otherwise fail */ int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) #endif { moal_private *priv = (moal_private *)woal_get_netdev_priv(dev); int ret = 0; ENTER(); PRINTM(MMSG, "wlan: Starting AP\n"); #ifdef STA_CFG80211 /*** cancel pending scan */ woal_cancel_scan(priv, MOAL_IOCTL_WAIT); #endif if (params != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) priv->channel = ieee80211_frequency_to_channel(params->chandef.chan-> center_freq); #else priv->channel = ieee80211_frequency_to_channel(params->channel-> center_freq); #endif #endif /* bss config */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) { ret = -EFAULT; goto done; } /* set mgmt frame ies */ ret = woal_cfg80211_mgmt_frame_ie(priv, #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !defined(COMPAT_WIRELESS) params->tail, params->tail_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) params->beacon.tail, params->beacon.tail_len, params->beacon.proberesp_ies, params->beacon. proberesp_ies_len, params->beacon.assocresp_ies, params->beacon. assocresp_ies_len, #else params->tail, params->tail_len, params->proberesp_ies, params->proberesp_ies_len, params->assocresp_ies, params->assocresp_ies_len, #endif NULL, 0, MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | MGMT_MASK_ASSOC_RESP #endif , MOAL_IOCTL_WAIT); if (ret) goto done; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) || defined(COMPAT_WIRELESS) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) { ret = woal_cfg80211_mgmt_frame_ie(priv, params->beacon.beacon_ies, params->beacon.beacon_ies_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON_WPS_P2P, MOAL_IOCTL_WAIT); if (ret) { PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n"); goto done; } } #else if (params->beacon_ies && params->beacon_ies_len) { ret = woal_cfg80211_mgmt_frame_ie(priv, params->beacon_ies, params->beacon_ies_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON_WPS_P2P, MOAL_IOCTL_WAIT); if (ret) { PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n"); goto done; } } #endif #endif /* if the bss is stopped, then start it */ if (priv->bss_started == MFALSE) { if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START)) { ret = -EFAULT; goto done; } } PRINTM(MMSG, "wlan: AP started\n"); done: LEAVE(); return ret; }