compat.c

来自「和我之前上载的intel 802.11协议源码是配套的」· C语言 代码 · 共 599 行 · 第 1/2 页

C
599
字号
/* * Header file to maintain compatibility among different kernel versions. * * Copyright (c) 2004-2006  Zhu Yi <yi.zhu@intel.com>, Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#if WIRELESS_EXT < 18/* Support for wpa_supplicant before WE-18, deprecated. *//* following definitions must match definitions in driver_ipw.c */#define IPW_IOCTL_WPA_SUPPLICANT		SIOCIWFIRSTPRIV+30#define IPW_CMD_SET_WPA_PARAM			1#define	IPW_CMD_SET_WPA_IE			2#define IPW_CMD_SET_ENCRYPTION			3#define IPW_CMD_MLME				4#define IPW_PARAM_WPA_ENABLED			1#define IPW_PARAM_TKIP_COUNTERMEASURES		2#define IPW_PARAM_DROP_UNENCRYPTED		3#define IPW_PARAM_PRIVACY_INVOKED		4#define IPW_PARAM_AUTH_ALGS			5#define IPW_PARAM_IEEE_802_1X			6#define IPW_MLME_STA_DEAUTH			1#define IPW_MLME_STA_DISASSOC			2#define IPW_CRYPT_ERR_UNKNOWN_ALG		2#define IPW_CRYPT_ERR_UNKNOWN_ADDR		3#define IPW_CRYPT_ERR_CRYPT_INIT_FAILED		4#define IPW_CRYPT_ERR_KEY_SET_FAILED		5#define IPW_CRYPT_ERR_TX_KEY_SET_FAILED		6#define IPW_CRYPT_ERR_CARD_CONF_FAILED		7#define	IPW_CRYPT_ALG_NAME_LEN			16struct ipw_param {	u32 cmd;	u8 sta_addr[ETH_ALEN];	union {		struct {			u8 name;			u32 value;		} wpa_param;		struct {			u32 len;			u8 reserved[32];			u8 data[0];		} wpa_ie;		struct {			u32 command;			u32 reason_code;		} mlme;		struct {			u8 alg[IPW_CRYPT_ALG_NAME_LEN];			u8 set_tx;			u32 err;			u8 idx;			u8 seq[8];	/* sequence counter (set: RX, get: TX) */			u16 key_len;			u8 key[0];		} crypt;	} u;};/* end of driver_ipw.c code */struct ipw_priv;static int ipw_wpa_enable(struct ipw_priv *priv, int value);static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value);static int ipw_disassociate(void *data);static void ipw_set_hw_decrypt_unicast(struct ipw_priv *priv, int level);static void ipw_set_hw_decrypt_multicast(struct ipw_priv *priv, int level);static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie,				int wpa_ie_len);static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value){	struct ipw_priv *priv = ieee80211_priv(dev);	struct ieee80211_crypt_data *crypt;	unsigned long flags;	int ret = 0;	switch (name) {	case IPW_PARAM_WPA_ENABLED:		ret = ipw_wpa_enable(priv, value);		break;	case IPW_PARAM_TKIP_COUNTERMEASURES:		crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];		if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) {			IPW_WARNING("Can't set TKIP countermeasures: "				    "crypt not set!\n");			break;		}		flags = crypt->ops->get_flags(crypt->priv);		if (value)			flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;		else			flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;		crypt->ops->set_flags(flags, crypt->priv);		break;	case IPW_PARAM_DROP_UNENCRYPTED:{			/* HACK:			 *			 * wpa_supplicant calls set_wpa_enabled when the driver			 * is loaded and unloaded, regardless of if WPA is being			 * used.  No other calls are made which can be used to			 * determine if encryption will be used or not prior to			 * association being expected.  If encryption is not being			 * used, drop_unencrypted is set to false, else true -- we			 * can use this to determine if the CAP_PRIVACY_ON bit should			 * be set.			 */			struct ieee80211_security sec = {				.flags = SEC_ENABLED,				.enabled = value,			};			priv->ieee->drop_unencrypted = value;			/* We only change SEC_LEVEL for open mode. Others			 * are set by ipw_wpa_set_encryption.			 */			if (!value) {				sec.flags |= SEC_LEVEL;				sec.level = SEC_LEVEL_0;			} else {				sec.flags |= SEC_LEVEL;				sec.level = SEC_LEVEL_1;			}			if (priv->ieee->set_security)				priv->ieee->set_security(priv->ieee->dev, &sec);			break;		}	case IPW_PARAM_PRIVACY_INVOKED:		priv->ieee->privacy_invoked = value;		break;	case IPW_PARAM_AUTH_ALGS:		ret = ipw_wpa_set_auth_algs(priv, value);		break;	case IPW_PARAM_IEEE_802_1X:		priv->ieee->ieee802_1x = value;		break;	default:		IPW_ERROR("%s: Unknown WPA param: %d\n", dev->name, name);		ret = -EOPNOTSUPP;	}	return ret;}static int ipw_wpa_mlme(struct net_device *dev, int command, int reason){	struct ipw_priv *priv = ieee80211_priv(dev);	int ret = 0;	switch (command) {	case IPW_MLME_STA_DEAUTH:		// silently ignore		break;	case IPW_MLME_STA_DISASSOC:		ipw_disassociate(priv);		break;	default:		IPW_ERROR("%s: Unknown MLME request: %d\n", dev->name, command);		ret = -EOPNOTSUPP;	}	return ret;}static int ipw_wpa_ie_cipher2level(u8 cipher){	switch (cipher) {	case 4:		/* CCMP */		return SEC_LEVEL_3;	case 2:		/* TKIP */		return SEC_LEVEL_2;	case 5:		/* WEP104 */	case 1:		/* WEP40 */		return SEC_LEVEL_1;	case 0:		/* NONE */		return SEC_LEVEL_0;	default:		return -1;	}}static int ipw_wpa_set_wpa_ie(struct net_device *dev,			      struct ipw_param *param, int plen){	struct ipw_priv *priv = ieee80211_priv(dev);	struct ieee80211_device *ieee = priv->ieee;	u8 *buf;	u8 *ptk, *gtk;	int level;	if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||	    (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))		return -EINVAL;	if (param->u.wpa_ie.len) {		buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);		if (buf == NULL)			return -ENOMEM;		memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);		kfree(ieee->wpa_ie);		ieee->wpa_ie = buf;		ieee->wpa_ie_len = param->u.wpa_ie.len;	} else {		kfree(ieee->wpa_ie);		ieee->wpa_ie = NULL;		ieee->wpa_ie_len = 0;		goto done;	}	if (priv->ieee->host_encrypt)		goto done;	/* HACK: Parse wpa_ie here to get pairwise suite, otherwise	 * we need to change driver_ipw.c from wpa_supplicant. This	 * is OK since -Dipw is deprecated. The -Dwext driver has a	 * clean way to handle this. */	gtk = ptk = (u8 *) ieee->wpa_ie;	if (ieee->wpa_ie[0] == 0x30) {	/* RSN IE */		gtk += 4 + 3;		ptk += 4 + 4 + 2 + 3;	} else {		/* WPA IE */		gtk += 8 + 3;		ptk += 8 + 4 + 2 + 3;	}	if (ptk - (u8 *) ieee->wpa_ie > ieee->wpa_ie_len)		return -EINVAL;	level = ipw_wpa_ie_cipher2level(*gtk);	ipw_set_hw_decrypt_multicast(priv, level);	level = ipw_wpa_ie_cipher2level(*ptk);	ipw_set_hw_decrypt_unicast(priv, level);      done:	ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);	return 0;}/* implementation borrowed from hostap driver */static int ipw_wpa_set_encryption(struct net_device *dev,				  struct ipw_param *param, int param_len){	int ret = 0;	int group_key = 0;	struct ipw_priv *priv = ieee80211_priv(dev);	struct ieee80211_device *ieee = priv->ieee;	struct ieee80211_crypto_ops *ops;	struct ieee80211_crypt_data **crypt;	struct ieee80211_security sec = {		.flags = 0,	};	param->u.crypt.err = 0;	param->u.crypt.alg[IPW_CRYPT_ALG_NAME_LEN - 1] = '\0';	if (param_len !=	    (int)((char *)param->u.crypt.key - (char *)param) +	    param->u.crypt.key_len) {		IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len,			       param->u.crypt.key_len);		return -EINVAL;	}	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {		if (param->u.crypt.idx >= WEP_KEYS)			return -EINVAL;		crypt = &ieee->crypt[param->u.crypt.idx];	} else {		return -EINVAL;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?