⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isl_ioctl.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	union iwreq_data wrqu;	char *memptr;	int n = strlen(str);	memptr = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL);	if (!memptr)		return;	BUG_ON(n > IW_CUSTOM_MAX);	wrqu.data.pointer = memptr;	wrqu.data.length = n;	strcpy(memptr, str);	wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, memptr);	kfree(memptr);}static voidlink_changed(struct net_device *ndev, u32 bitrate){	islpci_private *priv = netdev_priv(ndev);	if (bitrate) {		if (priv->iw_mode == IW_MODE_INFRA) {			union iwreq_data uwrq;			prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq,					NULL);			wireless_send_event(ndev, SIOCGIWAP, &uwrq, NULL);		} else			send_simple_event(netdev_priv(ndev),					  "Link established");	} else		send_simple_event(netdev_priv(ndev), "Link lost");}/* Beacon/ProbeResp payload header */struct ieee80211_beacon_phdr {	u8 timestamp[8];	u16 beacon_int;	u16 capab_info;} __attribute__ ((packed));#define WLAN_EID_GENERIC 0xddstatic u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 };static voidprism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,		       u8 *wpa_ie, size_t wpa_ie_len){	struct list_head *ptr;	struct islpci_bss_wpa_ie *bss = NULL;	DECLARE_MAC_BUF(mac);	if (wpa_ie_len > MAX_WPA_IE_LEN)		wpa_ie_len = MAX_WPA_IE_LEN;	if (down_interruptible(&priv->wpa_sem))		return;	/* try to use existing entry */	list_for_each(ptr, &priv->bss_wpa_list) {		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);		if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) {			list_move(&bss->list, &priv->bss_wpa_list);			break;		}		bss = NULL;	}	if (bss == NULL) {		/* add a new BSS entry; if max number of entries is already		 * reached, replace the least recently updated */		if (priv->num_bss_wpa >= MAX_BSS_WPA_IE_COUNT) {			bss = list_entry(priv->bss_wpa_list.prev,					 struct islpci_bss_wpa_ie, list);			list_del(&bss->list);		} else {			bss = kzalloc(sizeof (*bss), GFP_ATOMIC);			if (bss != NULL)				priv->num_bss_wpa++;		}		if (bss != NULL) {			memcpy(bss->bssid, bssid, ETH_ALEN);			list_add(&bss->list, &priv->bss_wpa_list);		}	}	if (bss != NULL) {		memcpy(bss->wpa_ie, wpa_ie, wpa_ie_len);		bss->wpa_ie_len = wpa_ie_len;		bss->last_update = jiffies;	} else {		printk(KERN_DEBUG "Failed to add BSS WPA entry for "		       "%s\n", print_mac(mac, bssid));	}	/* expire old entries from WPA list */	while (priv->num_bss_wpa > 0) {		bss = list_entry(priv->bss_wpa_list.prev,				 struct islpci_bss_wpa_ie, list);		if (!time_after(jiffies, bss->last_update + 60 * HZ))			break;		list_del(&bss->list);		priv->num_bss_wpa--;		kfree(bss);	}	up(&priv->wpa_sem);}static size_tprism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie){	struct list_head *ptr;	struct islpci_bss_wpa_ie *bss = NULL;	size_t len = 0;	if (down_interruptible(&priv->wpa_sem))		return 0;	list_for_each(ptr, &priv->bss_wpa_list) {		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);		if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0)			break;		bss = NULL;	}	if (bss) {		len = bss->wpa_ie_len;		memcpy(wpa_ie, bss->wpa_ie, len);	}	up(&priv->wpa_sem);	return len;}voidprism54_wpa_bss_ie_init(islpci_private *priv){	INIT_LIST_HEAD(&priv->bss_wpa_list);	sema_init(&priv->wpa_sem, 1);}voidprism54_wpa_bss_ie_clean(islpci_private *priv){	struct islpci_bss_wpa_ie *bss, *n;	list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) {		kfree(bss);	}}static voidprism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr,			 u8 *payload, size_t len){	struct ieee80211_beacon_phdr *hdr;	u8 *pos, *end;	DECLARE_MAC_BUF(mac);	if (!priv->wpa)		return;	hdr = (struct ieee80211_beacon_phdr *) payload;	pos = (u8 *) (hdr + 1);	end = payload + len;	while (pos < end) {		if (pos + 2 + pos[1] > end) {			printk(KERN_DEBUG "Parsing Beacon/ProbeResp failed "			       "for %s\n", print_mac(mac, addr));			return;		}		if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&		    memcmp(pos + 2, wpa_oid, 4) == 0) {			prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2);			return;		}		pos += 2 + pos[1];	}}static voidhandle_request(islpci_private *priv, struct obj_mlme *mlme, enum oid_num_t oid){	if (((mlme->state == DOT11_STATE_AUTHING) ||	     (mlme->state == DOT11_STATE_ASSOCING))	    && mgt_mlme_answer(priv)) {		/* Someone is requesting auth and we must respond. Just send back		 * the trap with error code set accordingly.		 */		mlme->code = prism54_mac_accept(&priv->acl,						mlme->address) ? 0 : 1;		mgt_set_request(priv, oid, 0, mlme);	}}static intprism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,			    char *data){	struct obj_mlme *mlme = (struct obj_mlme *) data;	struct obj_mlmeex *mlmeex = (struct obj_mlmeex *) data;	struct obj_mlmeex *confirm;	u8 wpa_ie[MAX_WPA_IE_LEN];	int wpa_ie_len;	size_t len = 0; /* u16, better? */	u8 *payload = NULL, *pos = NULL;	int ret;	DECLARE_MAC_BUF(mac);	/* I think all trapable objects are listed here.	 * Some oids have a EX version. The difference is that they are emitted	 * in DOT11_MLME_EXTENDED mode (set with DOT11_OID_MLMEAUTOLEVEL)	 * with more info.	 * The few events already defined by the wireless tools are not really	 * suited. We use the more flexible custom event facility.	 */	if (oid >= DOT11_OID_BEACON) {		len = mlmeex->size;		payload = pos = mlmeex->data;	}	/* I fear prism54_process_bss_data won't work with big endian data */	if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE))		prism54_process_bss_data(priv, oid, mlmeex->address,					 payload, len);	mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme);	switch (oid) {	case GEN_OID_LINKSTATE:		link_changed(priv->ndev, (u32) *data);		break;	case DOT11_OID_MICFAILURE:		send_simple_event(priv, "Mic failure");		break;	case DOT11_OID_DEAUTHENTICATE:		send_formatted_event(priv, "DeAuthenticate request", mlme, 0);		break;	case DOT11_OID_AUTHENTICATE:		handle_request(priv, mlme, oid);		send_formatted_event(priv, "Authenticate request", mlme, 1);		break;	case DOT11_OID_DISASSOCIATE:		send_formatted_event(priv, "Disassociate request", mlme, 0);		break;	case DOT11_OID_ASSOCIATE:		handle_request(priv, mlme, oid);		send_formatted_event(priv, "Associate request", mlme, 1);		break;	case DOT11_OID_REASSOCIATE:		handle_request(priv, mlme, oid);		send_formatted_event(priv, "ReAssociate request", mlme, 1);		break;	case DOT11_OID_BEACON:		send_formatted_event(priv,				     "Received a beacon from an unkown AP",				     mlme, 0);		break;	case DOT11_OID_PROBE:		/* we received a probe from a client. */		send_formatted_event(priv, "Received a probe from client", mlme,				     0);		break;		/* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this		 * is backward compatible layout-wise with "struct obj_mlme".		 */	case DOT11_OID_DEAUTHENTICATEEX:		send_formatted_event(priv, "DeAuthenticate request", mlme, 0);		break;	case DOT11_OID_AUTHENTICATEEX:		handle_request(priv, mlme, oid);		send_formatted_event(priv, "Authenticate request (ex)", mlme, 1);		if (priv->iw_mode != IW_MODE_MASTER				&& mlmeex->state != DOT11_STATE_AUTHING)			break;		confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC);		if (!confirm)			break;		memcpy(&confirm->address, mlmeex->address, ETH_ALEN);		printk(KERN_DEBUG "Authenticate from: address:\t%s\n",		       print_mac(mac, mlmeex->address));		confirm->id = -1; /* or mlmeex->id ? */		confirm->state = 0; /* not used */		confirm->code = 0;		confirm->size = 6;		confirm->data[0] = 0x00;		confirm->data[1] = 0x00;		confirm->data[2] = 0x02;		confirm->data[3] = 0x00;		confirm->data[4] = 0x00;		confirm->data[5] = 0x00;		ret = mgt_set_varlen(priv, DOT11_OID_ASSOCIATEEX, confirm, 6);		kfree(confirm);		if (ret)			return ret;		break;	case DOT11_OID_DISASSOCIATEEX:		send_formatted_event(priv, "Disassociate request (ex)", mlme, 0);		break;	case DOT11_OID_ASSOCIATEEX:		handle_request(priv, mlme, oid);		send_formatted_event(priv, "Associate request (ex)", mlme, 1);		if (priv->iw_mode != IW_MODE_MASTER				&& mlmeex->state != DOT11_STATE_ASSOCING)			break;		confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);		if (!confirm)			break;		memcpy(&confirm->address, mlmeex->address, ETH_ALEN);		confirm->id = ((struct obj_mlmeex *)mlme)->id;		confirm->state = 0; /* not used */		confirm->code = 0;		wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);		if (!wpa_ie_len) {			printk(KERN_DEBUG "No WPA IE found from address:\t%s\n",			       print_mac(mac, mlmeex->address));			kfree(confirm);			break;		}		confirm->size = wpa_ie_len;		memcpy(&confirm->data, wpa_ie, wpa_ie_len);		mgt_set_varlen(priv, oid, confirm, wpa_ie_len);		kfree(confirm);		break;	case DOT11_OID_REASSOCIATEEX:		handle_request(priv, mlme, oid);		send_formatted_event(priv, "Reassociate request (ex)", mlme, 1);		if (priv->iw_mode != IW_MODE_MASTER				&& mlmeex->state != DOT11_STATE_ASSOCING)			break;		confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);		if (!confirm)			break;		memcpy(&confirm->address, mlmeex->address, ETH_ALEN);		confirm->id = mlmeex->id;		confirm->state = 0; /* not used */		confirm->code = 0;		wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);		if (!wpa_ie_len) {			printk(KERN_DEBUG "No WPA IE found from address:\t%s\n",			       print_mac(mac, mlmeex->address));			kfree(confirm);			break;		}		confirm->size = wpa_ie_len;		memcpy(&confirm->data, wpa_ie, wpa_ie_len);		mgt_set_varlen(priv, oid, confirm, wpa_ie_len);		kfree(confirm);		break;	default:		return -EINVAL;	}	return 0;}/* * Process a device trap.  This is called via schedule_work(), outside of * interrupt context, no locks held. */voidprism54_process_trap(struct work_struct *work){	struct islpci_mgmtframe *frame =		container_of(work, struct islpci_mgmtframe, ws);	struct net_device *ndev = frame->ndev;	enum oid_num_t n = mgt_oidtonum(frame->header->oid);	if (n != OID_NUM_LAST)		prism54_process_trap_helper(netdev_priv(ndev), n, frame->data);	islpci_mgt_release(frame);}intprism54_set_mac_address(struct net_device *ndev, void *addr){	islpci_private *priv = netdev_priv(ndev);	int ret;	if (ndev->addr_len != 6)		return -EINVAL;	ret = mgt_set_request(priv, GEN_OID_MACADDRESS, 0,			      &((struct sockaddr *) addr)->sa_data);	if (!ret)		memcpy(priv->ndev->dev_addr,		       &((struct sockaddr *) addr)->sa_data, 6);	return ret;}/* Note: currently, use hostapd ioctl from the Host AP driver for WPA * support. This is to be replaced with Linux wireless extensions once they * get WPA support. *//* Note II: please leave all this together as it will be easier to remove later, * once wireless extensions add WPA support -mcgrof *//* PRISM54_HOSTAPD ioctl() cmd: */enum {	PRISM2_SET_ENCRYPTION = 6,	PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,	PRISM2_HOSTAPD_MLME = 13,	PRISM2_HOSTAPD_SCAN_REQ = 14,};#define PRISM54_SET_WPA			SIOCIWFIRSTPRIV+12#define PRISM54_HOSTAPD			SIOCIWFIRSTPRIV+25#define PRISM54_DROP_UNENCRYPTED	SIOCIWFIRSTPRIV+26#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))/* Maximum length for algorithm names (-1 for nul termination) * used in ioctl() */#define HOSTAP_CRYPT_ALG_NAME_LEN 16struct prism2_hostapd_param {	u32 cmd;	u8 sta_addr[ETH_ALEN];	union {	       struct {		       u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];		       u32 flags;		       u32 err;		       u8 idx;		       u8 seq[8]; /* sequence counter (set: RX, get: TX) */		       u16 key_len;		       u8 key[0];		       } crypt;               struct {                       u8 len;                       u8 data[0];               } generic_elem;               struct {#define MLME_STA_DEAUTH 0#define MLME_STA_DISASSOC 1                       u16 cmd;                       u16 reason_code;               } mlme;               struct {                       u8 ssid_len;                       u8 ssid[32];               } scan_req;       } u;};static intprism2_ioctl_set_encryption(struct net_device *dev,	struct prism2_hostapd_param *param,	int param_len){	islpci_private *priv = netdev_priv(dev);	int rvalue = 0, force = 0;	int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;	union oid_res_t r;	/* with the new API, it's impossible to get a NULL pointer.	 * New version of iwconfig set the IW_ENCODE_NOKEY flag	 * when no key is given, but older versions don't. */	if (param->u.crypt.key_len > 0) {		/* we have a key to set */		int index = param->u.crypt.idx;		int current_index;		struct o

⌨️ 快捷键说明

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