u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate) { hfa384x_t *hw = (hfa384x_t *) wlandev->priv; u32 result; result = P80211ENUM_resultcode_implementation_failure; pr_debug("Current MSD state(%d), requesting(%d)\n", wlandev->msdstate, ifstate); switch (ifstate) { case P80211ENUM_ifstate_fwload: switch (wlandev->msdstate) { case WLAN_MSD_HWPRESENT: wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING; result = hfa384x_drvr_start(hw); if (result) { printk(KERN_ERR "hfa384x_drvr_start() failed," "result=%d\n", (int)result); result = P80211ENUM_resultcode_implementation_failure; wlandev->msdstate = WLAN_MSD_HWPRESENT; break; } wlandev->msdstate = WLAN_MSD_FWLOAD; result = P80211ENUM_resultcode_success; break; case WLAN_MSD_FWLOAD: hfa384x_cmd_initialize(hw); result = P80211ENUM_resultcode_success; break; case WLAN_MSD_RUNNING: printk(KERN_WARNING "Cannot enter fwload state from enable state," "you must disable first.\n"); result = P80211ENUM_resultcode_invalid_parameters; break; case WLAN_MSD_HWFAIL: default: result = P80211ENUM_resultcode_implementation_failure; break; } break; case P80211ENUM_ifstate_enable: switch (wlandev->msdstate) { case WLAN_MSD_HWPRESENT: case WLAN_MSD_FWLOAD: wlandev->msdstate = WLAN_MSD_RUNNING_PENDING; result = hfa384x_drvr_start(hw); if (result) { printk(KERN_ERR "hfa384x_drvr_start() failed," "result=%d\n", (int)result); result = P80211ENUM_resultcode_implementation_failure; wlandev->msdstate = WLAN_MSD_HWPRESENT; break; } result = prism2sta_getcardinfo(wlandev); if (result) { printk(KERN_ERR "prism2sta_getcardinfo() failed," "result=%d\n", (int)result); result = P80211ENUM_resultcode_implementation_failure; hfa384x_drvr_stop(hw); wlandev->msdstate = WLAN_MSD_HWPRESENT; break; } result = prism2sta_globalsetup(wlandev); if (result) { printk(KERN_ERR "prism2sta_globalsetup() failed," "result=%d\n", (int)result); result = P80211ENUM_resultcode_implementation_failure; hfa384x_drvr_stop(hw); wlandev->msdstate = WLAN_MSD_HWPRESENT; break; } wlandev->msdstate = WLAN_MSD_RUNNING; hw->join_ap = 0; hw->join_retries = 60; result = P80211ENUM_resultcode_success; break; case WLAN_MSD_RUNNING: result = P80211ENUM_resultcode_success; break; case WLAN_MSD_HWFAIL: default: result = P80211ENUM_resultcode_implementation_failure; break; } break; case P80211ENUM_ifstate_disable: switch (wlandev->msdstate) { case WLAN_MSD_HWPRESENT: result = P80211ENUM_resultcode_success; break; case WLAN_MSD_FWLOAD: case WLAN_MSD_RUNNING: wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING; if (!wlandev->hwremoved) netif_carrier_off(wlandev->netdev); hfa384x_drvr_stop(hw); wlandev->macmode = WLAN_MACMODE_NONE; wlandev->msdstate = WLAN_MSD_HWPRESENT; result = P80211ENUM_resultcode_success; break; case WLAN_MSD_HWFAIL: default: result = P80211ENUM_resultcode_implementation_failure; break; } break; default: result = P80211ENUM_resultcode_invalid_parameters; break; } return result; }
/*---------------------------------------------------------------- * prism2mgmt_wlansniff * * Start or stop sniffing. * * Arguments: * wlandev wlan device structure * msgp ptr to msg buffer * * Returns: * 0 success and done * <0 success, but we're waiting for something to finish. * >0 an error occurred while handling the message. * Side effects: * * Call context: * process thread (usually) * interrupt *---------------------------------------------------------------- */ int prism2mgmt_wlansniff(struct wlandevice *wlandev, void *msgp) { int result = 0; struct p80211msg_lnxreq_wlansniff *msg = msgp; struct hfa384x *hw = wlandev->priv; u16 word; msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; switch (msg->enable.data) { case P80211ENUM_truth_false: /* Confirm that we're in monitor mode */ if (wlandev->netdev->type == ARPHRD_ETHER) { msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; return 0; } /* Disable monitor mode */ result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE); if (result) { netdev_dbg(wlandev->netdev, "failed to disable monitor mode, result=%d\n", result); goto failed; } /* Disable port 0 */ result = hfa384x_drvr_disable(hw, 0); if (result) { netdev_dbg (wlandev->netdev, "failed to disable port 0 after sniffing, result=%d\n", result); goto failed; } /* Clear the driver state */ wlandev->netdev->type = ARPHRD_ETHER; /* Restore the wepflags */ result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, hw->presniff_wepflags); if (result) { netdev_dbg (wlandev->netdev, "failed to restore wepflags=0x%04x, result=%d\n", hw->presniff_wepflags, result); goto failed; } /* Set the port to its prior type and enable (if necessary) */ if (hw->presniff_port_type != 0) { word = hw->presniff_port_type; result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, word); if (result) { netdev_dbg (wlandev->netdev, "failed to restore porttype, result=%d\n", result); goto failed; } /* Enable the port */ result = hfa384x_drvr_enable(hw, 0); if (result) { netdev_dbg(wlandev->netdev, "failed to enable port to presniff setting, result=%d\n", result); goto failed; } } else { result = hfa384x_drvr_disable(hw, 0); } netdev_info(wlandev->netdev, "monitor mode disabled\n"); msg->resultcode.data = P80211ENUM_resultcode_success; return 0; case P80211ENUM_truth_true: /* Disable the port (if enabled), only check Port 0 */ if (hw->port_enabled[0]) { if (wlandev->netdev->type == ARPHRD_ETHER) { /* Save macport 0 state */ result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFPORTTYPE, &(hw->presniff_port_type)); if (result) { netdev_dbg (wlandev->netdev, "failed to read porttype, result=%d\n", result); goto failed; } /* Save the wepflags state */ result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFWEPFLAGS, &(hw->presniff_wepflags)); if (result) { netdev_dbg (wlandev->netdev, "failed to read wepflags, result=%d\n", result); goto failed; } hfa384x_drvr_stop(hw); result = hfa384x_drvr_start(hw); if (result) { netdev_dbg(wlandev->netdev, "failed to restart the card for sniffing, result=%d\n", result); goto failed; } } else { /* Disable the port */ result = hfa384x_drvr_disable(hw, 0); if (result) { netdev_dbg(wlandev->netdev, "failed to enable port for sniffing, result=%d\n", result); goto failed; } } } else { hw->presniff_port_type = 0; } /* Set the channel we wish to sniff */ word = msg->channel.data; result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); hw->sniff_channel = word; if (result) { netdev_dbg(wlandev->netdev, "failed to set channel %d, result=%d\n", word, result); goto failed; } /* Now if we're already sniffing, we can skip the rest */ if (wlandev->netdev->type != ARPHRD_ETHER) { /* Set the port type to pIbss */ word = HFA384x_PORTTYPE_PSUEDOIBSS; result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, word); if (result) { netdev_dbg (wlandev->netdev, "failed to set porttype %d, result=%d\n", word, result); goto failed; } if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) { /* Set the wepflags for no decryption */ word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT | HFA384x_WEPFLAGS_DISABLE_RXCRYPT; result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word); } if (result) { netdev_dbg (wlandev->netdev, "failed to set wepflags=0x%04x, result=%d\n", word, result); goto failed; } } /* Do we want to strip the FCS in monitor mode? */ if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) { hw->sniff_fcs = 0; } else { hw->sniff_fcs = 1; } /* Do we want to truncate the packets? */ if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) { hw->sniff_truncate = msg->packet_trunc.data; } else { hw->sniff_truncate = 0; } /* Enable the port */ result = hfa384x_drvr_enable(hw, 0); if (result) { netdev_dbg (wlandev->netdev, "failed to enable port for sniffing, result=%d\n", result); goto failed; } /* Enable monitor mode */ result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE); if (result) { netdev_dbg(wlandev->netdev, "failed to enable monitor mode, result=%d\n", result); goto failed; } if (wlandev->netdev->type == ARPHRD_ETHER) netdev_info(wlandev->netdev, "monitor mode enabled\n"); /* Set the driver state */ /* Do we want the prism2 header? */ if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) { hw->sniffhdr = 0; wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) { hw->sniffhdr = 1; wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; } else { wlandev->netdev->type = ARPHRD_IEEE80211; } msg->resultcode.data = P80211ENUM_resultcode_success; return 0; default: msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; return 0; } failed: msg->resultcode.data = P80211ENUM_resultcode_refused; return 0; }