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

📄 hostap_ap.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	hdr->frame_ctl = cpu_to_le16(fc);	meta = (struct hostap_skb_tx_data *) skb->cb;	memset(meta, 0, sizeof(*meta));	meta->magic = HOSTAP_SKB_TX_DATA_MAGIC;	meta->iface = iface;	meta->tx_cb_idx = tx_cb_idx;	skb->dev = dev;	skb->mac.raw = skb->nh.raw = skb->data;	dev_queue_xmit(skb);}#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */static int prism2_sta_proc_read(char *page, char **start, off_t off,				int count, int *eof, void *data){	char *p = page;	struct sta_info *sta = (struct sta_info *) data;	int i;	/* FIX: possible race condition.. the STA data could have just expired,	 * but proc entry was still here so that the read could have started;	 * some locking should be done here.. */	if (off != 0) {		*eof = 1;		return 0;	}	p += sprintf(p, "%s=" MACSTR "\nusers=%d\naid=%d\n"		     "flags=0x%04x%s%s%s%s%s%s%s\n"		     "capability=0x%02x\nlisten_interval=%d\nsupported_rates=",		     sta->ap ? "AP" : "STA",		     MAC2STR(sta->addr), atomic_read(&sta->users), sta->aid,		     sta->flags,		     sta->flags & WLAN_STA_AUTH ? " AUTH" : "",		     sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "",		     sta->flags & WLAN_STA_PS ? " PS" : "",		     sta->flags & WLAN_STA_TIM ? " TIM" : "",		     sta->flags & WLAN_STA_PERM ? " PERM" : "",		     sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "",		     sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "",		     sta->capability, sta->listen_interval);	/* supported_rates: 500 kbit/s units with msb ignored */	for (i = 0; i < sizeof(sta->supported_rates); i++)		if (sta->supported_rates[i] != 0)			p += sprintf(p, "%d%sMbps ",				     (sta->supported_rates[i] & 0x7f) / 2,				     sta->supported_rates[i] & 1 ? ".5" : "");	p += sprintf(p, "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n"		     "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n"		     "tx_packets=%lu\n"		     "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n"		     "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n"		     "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n"		     "tx[11M]=%d\n"		     "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n",		     jiffies, sta->last_auth, sta->last_assoc, sta->last_rx,		     sta->last_tx,		     sta->rx_packets, sta->tx_packets, sta->rx_bytes,		     sta->tx_bytes, skb_queue_len(&sta->tx_buf),		     sta->last_rx_silence,		     sta->last_rx_signal, sta->last_rx_rate / 10,		     sta->last_rx_rate % 10 ? ".5" : "",		     sta->tx_rate, sta->tx_count[0], sta->tx_count[1],		     sta->tx_count[2], sta->tx_count[3],  sta->rx_count[0],		     sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]);	if (sta->crypt && sta->crypt->ops && sta->crypt->ops->print_stats)		p = sta->crypt->ops->print_stats(p, sta->crypt->priv);#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT	if (sta->ap) {		if (sta->u.ap.channel >= 0)			p += sprintf(p, "channel=%d\n", sta->u.ap.channel);		p += sprintf(p, "ssid=");		for (i = 0; i < sta->u.ap.ssid_len; i++)			p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 &&					  sta->u.ap.ssid[i] < 127) ?					 "%c" : "<%02x>"),				     sta->u.ap.ssid[i]);		p += sprintf(p, "\n");	}#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */	return (p - page);}static void handle_add_proc_queue(void *data){	struct ap_data *ap = (struct ap_data *) data;	struct sta_info *sta;	char name[20];	struct add_sta_proc_data *entry, *prev;	entry = ap->add_sta_proc_entries;	ap->add_sta_proc_entries = NULL;	while (entry) {		spin_lock_bh(&ap->sta_table_lock);		sta = ap_get_sta(ap, entry->addr);		if (sta)			atomic_inc(&sta->users);		spin_unlock_bh(&ap->sta_table_lock);		if (sta) {			sprintf(name, MACSTR, MAC2STR(sta->addr));			sta->proc = create_proc_read_entry(				name, 0, ap->proc,				prism2_sta_proc_read, sta);			atomic_dec(&sta->users);		}		prev = entry;		entry = entry->next;		kfree(prev);	}}static struct sta_info * ap_add_sta(struct ap_data *ap, u8 *addr){	struct sta_info *sta;	sta = (struct sta_info *)		kmalloc(sizeof(struct sta_info), GFP_ATOMIC);	if (sta == NULL) {		PDEBUG(DEBUG_AP, "AP: kmalloc failed\n");		return NULL;	}	/* initialize STA info data */	memset(sta, 0, sizeof(struct sta_info));	sta->local = ap->local;	skb_queue_head_init(&sta->tx_buf);	memcpy(sta->addr, addr, ETH_ALEN);	atomic_inc(&sta->users);	spin_lock_bh(&ap->sta_table_lock);	list_add(&sta->list, &ap->sta_list);	ap->num_sta++;	ap_sta_hash_add(ap, sta);	spin_unlock_bh(&ap->sta_table_lock);	if (ap->proc) {		struct add_sta_proc_data *entry;		/* schedule a non-interrupt context process to add a procfs		 * entry for the STA since procfs code use GFP_KERNEL */		entry = kmalloc(sizeof(*entry), GFP_ATOMIC);		if (entry) {			memcpy(entry->addr, sta->addr, ETH_ALEN);			entry->next = ap->add_sta_proc_entries;			ap->add_sta_proc_entries = entry;			schedule_work(&ap->add_sta_proc_queue);		} else			printk(KERN_DEBUG "Failed to add STA proc data\n");	}#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT	init_timer(&sta->timer);	sta->timer.expires = jiffies + ap->max_inactivity;	sta->timer.data = (unsigned long) sta;	sta->timer.function = ap_handle_timer;	if (!ap->local->hostapd)		add_timer(&sta->timer);#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */	return sta;}static int ap_tx_rate_ok(int rateidx, struct sta_info *sta,			 local_info_t *local){	if (rateidx > sta->tx_max_rate ||	    !(sta->tx_supp_rates & (1 << rateidx)))		return 0;	if (local->tx_rate_control != 0 &&	    !(local->tx_rate_control & (1 << rateidx)))		return 0;	return 1;}static void prism2_check_tx_rates(struct sta_info *sta){	int i;	sta->tx_supp_rates = 0;	for (i = 0; i < sizeof(sta->supported_rates); i++) {		if ((sta->supported_rates[i] & 0x7f) == 2)			sta->tx_supp_rates |= WLAN_RATE_1M;		if ((sta->supported_rates[i] & 0x7f) == 4)			sta->tx_supp_rates |= WLAN_RATE_2M;		if ((sta->supported_rates[i] & 0x7f) == 11)			sta->tx_supp_rates |= WLAN_RATE_5M5;		if ((sta->supported_rates[i] & 0x7f) == 22)			sta->tx_supp_rates |= WLAN_RATE_11M;	}	sta->tx_max_rate = sta->tx_rate = sta->tx_rate_idx = 0;	if (sta->tx_supp_rates & WLAN_RATE_1M) {		sta->tx_max_rate = 0;		if (ap_tx_rate_ok(0, sta, sta->local)) {			sta->tx_rate = 10;			sta->tx_rate_idx = 0;		}	}	if (sta->tx_supp_rates & WLAN_RATE_2M) {		sta->tx_max_rate = 1;		if (ap_tx_rate_ok(1, sta, sta->local)) {			sta->tx_rate = 20;			sta->tx_rate_idx = 1;		}	}	if (sta->tx_supp_rates & WLAN_RATE_5M5) {		sta->tx_max_rate = 2;		if (ap_tx_rate_ok(2, sta, sta->local)) {			sta->tx_rate = 55;			sta->tx_rate_idx = 2;		}	}	if (sta->tx_supp_rates & WLAN_RATE_11M) {		sta->tx_max_rate = 3;		if (ap_tx_rate_ok(3, sta, sta->local)) {			sta->tx_rate = 110;			sta->tx_rate_idx = 3;		}	}}#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMTstatic void ap_crypt_init(struct ap_data *ap){	ap->crypt = ieee80211_get_crypto_ops("WEP");	if (ap->crypt) {		if (ap->crypt->init) {			ap->crypt_priv = ap->crypt->init(0);			if (ap->crypt_priv == NULL)				ap->crypt = NULL;			else {				u8 key[WEP_KEY_LEN];				get_random_bytes(key, WEP_KEY_LEN);				ap->crypt->set_key(key, WEP_KEY_LEN, NULL,						   ap->crypt_priv);			}		}	}	if (ap->crypt == NULL) {		printk(KERN_WARNING "AP could not initialize WEP: load module "		       "ieee80211_crypt_wep.ko\n");	}}/* Generate challenge data for shared key authentication. IEEE 802.11 specifies * that WEP algorithm is used for generating challange. This should be unique, * but otherwise there is not really need for randomness etc. Initialize WEP * with pseudo random key and then use increasing IV to get unique challenge * streams. * * Called only as a scheduled task for pending AP frames. */static char * ap_auth_make_challenge(struct ap_data *ap){	char *tmpbuf;	struct sk_buff *skb;	if (ap->crypt == NULL) {		ap_crypt_init(ap);		if (ap->crypt == NULL)			return NULL;	}	tmpbuf = (char *) kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC);	if (tmpbuf == NULL) {		PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n");		return NULL;	}	skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN +			    ap->crypt->extra_mpdu_prefix_len +			    ap->crypt->extra_mpdu_postfix_len);	if (skb == NULL) {		kfree(tmpbuf);		return NULL;	}	skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len);	memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0,	       WLAN_AUTH_CHALLENGE_LEN);	if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) {		dev_kfree_skb(skb);		kfree(tmpbuf);		return NULL;	}	memcpy(tmpbuf, skb->data + ap->crypt->extra_mpdu_prefix_len,	       WLAN_AUTH_CHALLENGE_LEN);	dev_kfree_skb(skb);	return tmpbuf;}/* Called only as a scheduled task for pending AP frames. */static void handle_authen(local_info_t *local, struct sk_buff *skb,			  struct hostap_80211_rx_status *rx_stats){	struct net_device *dev = local->dev;	struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;	size_t hdrlen;	struct ap_data *ap = local->ap;	char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;	int len, olen;	u16 auth_alg, auth_transaction, status_code, *pos;	u16 resp = WLAN_STATUS_SUCCESS, fc;	struct sta_info *sta = NULL;	struct ieee80211_crypt_data *crypt;	char *txt = "";	len = skb->len - IEEE80211_MGMT_HDR_LEN;	fc = le16_to_cpu(hdr->frame_ctl);	hdrlen = hostap_80211_get_hdrlen(fc);	if (len < 6) {		PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload "		       "(len=%d) from " MACSTR "\n", dev->name, len,		       MAC2STR(hdr->addr2));		return;	}	spin_lock_bh(&local->ap->sta_table_lock);	sta = ap_get_sta(local->ap, hdr->addr2);	if (sta)		atomic_inc(&sta->users);	spin_unlock_bh(&local->ap->sta_table_lock);	if (sta && sta->crypt)		crypt = sta->crypt;	else {		int idx = 0;		if (skb->len >= hdrlen + 3)			idx = skb->data[hdrlen + 3] >> 6;		crypt = local->crypt[idx];	}	pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);	auth_alg = __le16_to_cpu(*pos);	pos++;	auth_transaction = __le16_to_cpu(*pos);	pos++;	status_code = __le16_to_cpu(*pos);	pos++;	if (memcmp(dev->dev_addr, hdr->addr2, ETH_ALEN) == 0 ||	    ap_control_mac_deny(&ap->mac_restrictions, hdr->addr2)) {		txt = "authentication denied";		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;		goto fail;	}	if (((local->auth_algs & PRISM2_AUTH_OPEN) &&	     auth_alg == WLAN_AUTH_OPEN) ||	    ((local->auth_algs & PRISM2_AUTH_SHARED_KEY) &&	     crypt && auth_alg == WLAN_AUTH_SHARED_KEY)) {	} else {		txt = "unsupported algorithm";		resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;		goto fail;	}	if (len >= 8) {		u8 *u = (u8 *) pos;		if (*u == WLAN_EID_CHALLENGE) {			if (*(u + 1) != WLAN_AUTH_CHALLENGE_LEN) {				txt = "invalid challenge len";				resp = WLAN_STATUS_CHALLENGE_FAIL;				goto fail;			}			if (len - 8 < WLAN_AUTH_CHALLENGE_LEN) {				txt = "challenge underflow";				resp = WLAN_STATUS_CHALLENGE_FAIL;				goto fail;			}			challenge = (char *) (u + 2);		}	}	if (sta && sta->ap) {		if (time_after(jiffies, sta->u.ap.last_beacon +			       (10 * sta->listen_interval * HZ) / 1024)) {			PDEBUG(DEBUG_AP, "%s: no beacons received for a while,"			       " assuming AP " MACSTR " is now STA\n",			       dev->name, MAC2STR(sta->addr));			sta->ap = 0;			sta->flags = 0;			sta->u.sta.challenge = NULL;		} else {			txt = "AP trying to authenticate?";			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;			goto fail;		}	}	if ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) ||	    (auth_alg == WLAN_AUTH_SHARED_KEY &&	     (auth_transaction == 1 ||	      (auth_transaction == 3 && sta != NULL &&	       sta->u.sta.challenge != NULL)))) {	} else {		txt = "unknown authentication transaction number";		resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;		goto fail;	}	if (sta == NULL) {		txt = "new STA";		if (local->ap->num_sta >= MAX_STA_COUNT) {			/* FIX: might try to remove some old STAs first? */			txt = "no more room for new STAs";			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;			goto fail;		}		sta = ap_add_sta(local->ap, hdr->addr2);		if (sta == NULL) {			txt = "ap_add_sta failed";			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;			goto fail;		}	}	switch (auth_alg) {	case WLAN_AUTH_OPEN:		txt = "authOK";		/* IEEE 802.11 standard is not completely clear about		 * whether STA is considered authenticated after		 * authentication OK frame has been send or after it		 * has been ACKed. In order to reduce interoperability		 * issues, mark the STA authenticated before ACK. */		sta->flags |= WLAN_STA_AUTH;		break;	case WLAN_AUTH_SHARED_KEY:		if (auth_transaction == 1) {			if (sta->u.sta.challenge == NULL) {				sta->u.sta.challenge =					ap_auth_make_challenge(local->ap);				if (sta->u.sta.challenge == NULL) {					resp = WLAN_STATUS_UNSPECIFIED_FAILURE;					goto fail;				}			}		} else {			if (sta->u.sta.challenge == NULL ||			    challenge == NULL ||			    memcmp(sta->u.sta.challenge, challenge,				   WLAN_AUTH_CHALLENGE_LEN) != 0 ||			    !(fc & IEEE80211_FCTL_PROTECTED)) {				txt = "challenge response incorrect";				resp = WLAN_STATUS_CHALLENGE_FAIL;				goto fail;			}			txt = "challenge OK - authOK";			/* IEEE 802.11 standard is not completely clear about			 * whether STA is considered authenticated after			 * authentication OK frame has been send or after it			 * has been ACKed. In order to reduce interoperability			 * issues, mark the STA authenticated before ACK. */			sta->flags |= WLAN_STA_AUTH;			kfree(sta->u.sta.challenge);			sta->u.sta.challenge = NULL;		}		break;

⌨️ 快捷键说明

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