예제 #1
0
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;
}
예제 #2
0
파일: prism2mgmt.c 프로젝트: krzk/linux
/*----------------------------------------------------------------
 * 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;
}