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

📄 hostap_ap.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */static void ap_control_kickall(struct ap_data *ap){	struct list_head *ptr, *n;	struct sta_info *sta;	spin_lock_bh(&ap->sta_table_lock);	for (ptr = ap->sta_list.next, n = ptr->next; ptr != &ap->sta_list;	     ptr = n, n = ptr->next) {		sta = list_entry(ptr, struct sta_info, list);		ap_sta_hash_del(ap, sta);		list_del(&sta->list);		if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)			hostap_event_expired_sta(sta->local->dev, sta);		ap_free_sta(ap, sta);	}	spin_unlock_bh(&ap->sta_table_lock);}#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT#define PROC_LIMIT (PAGE_SIZE - 80)static int prism2_ap_proc_read(char *page, char **start, off_t off,			       int count, int *eof, void *data){	char *p = page;	struct ap_data *ap = (struct ap_data *) data;	struct list_head *ptr;	int i;	if (off > PROC_LIMIT) {		*eof = 1;		return 0;	}	p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");	spin_lock_bh(&ap->sta_table_lock);	for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {		struct sta_info *sta = (struct sta_info *) ptr;		if (!sta->ap)			continue;		p += sprintf(p, MACSTR " %d %d %d %d '", MAC2STR(sta->addr),			     sta->u.ap.channel, sta->last_rx_signal,			     sta->last_rx_silence, sta->last_rx_rate);		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, "'");		if (sta->capability & WLAN_CAPABILITY_ESS)			p += sprintf(p, " [ESS]");		if (sta->capability & WLAN_CAPABILITY_IBSS)			p += sprintf(p, " [IBSS]");		if (sta->capability & WLAN_CAPABILITY_PRIVACY)			p += sprintf(p, " [WEP]");		p += sprintf(p, "\n");		if ((p - page) > PROC_LIMIT) {			printk(KERN_DEBUG "hostap: ap proc did not fit\n");			break;		}	}	spin_unlock_bh(&ap->sta_table_lock);	if ((p - page) <= off) {		*eof = 1;		return 0;	}	*start = page + off;	return (p - page - off);}#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver){	if (!ap)		return;	if (sta_fw_ver == PRISM2_FW_VER(0,8,0)) {		PDEBUG(DEBUG_AP, "Using data::nullfunc ACK workaround - "		       "firmware upgrade recommended\n");		ap->nullfunc_ack = 1;	} else		ap->nullfunc_ack = 0;	if (sta_fw_ver == PRISM2_FW_VER(1,4,2)) {		printk(KERN_WARNING "%s: Warning: secondary station firmware "		       "version 1.4.2 does not seem to work in Host AP mode\n",		       ap->local->dev->name);	}}/* Called only as a tasklet (software IRQ) */static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data){	struct ap_data *ap = data;	u16 fc;	struct ieee80211_hdr_4addr *hdr;	if (!ap->local->hostapd || !ap->local->apdev) {		dev_kfree_skb(skb);		return;	}	hdr = (struct ieee80211_hdr_4addr *) skb->data;	fc = le16_to_cpu(hdr->frame_ctl);	/* Pass the TX callback frame to the hostapd; use 802.11 header version	 * 1 to indicate failure (no ACK) and 2 success (frame ACKed) */	fc &= ~IEEE80211_FCTL_VERS;	fc |= ok ? BIT(1) : BIT(0);	hdr->frame_ctl = cpu_to_le16(fc);	skb->dev = ap->local->apdev;	skb_pull(skb, hostap_80211_get_hdrlen(fc));	skb->pkt_type = PACKET_OTHERHOST;	skb->protocol = __constant_htons(ETH_P_802_2);	memset(skb->cb, 0, sizeof(skb->cb));	netif_rx(skb);}#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT/* Called only as a tasklet (software IRQ) */static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data){	struct ap_data *ap = data;	struct net_device *dev = ap->local->dev;	struct ieee80211_hdr_4addr *hdr;	u16 fc, *pos, auth_alg, auth_transaction, status;	struct sta_info *sta = NULL;	char *txt = NULL;	if (ap->local->hostapd) {		dev_kfree_skb(skb);		return;	}	hdr = (struct ieee80211_hdr_4addr *) skb->data;	fc = le16_to_cpu(hdr->frame_ctl);	if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||	    WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_AUTH ||	    skb->len < IEEE80211_MGMT_HDR_LEN + 6) {		printk(KERN_DEBUG "%s: hostap_ap_tx_cb_auth received invalid "		       "frame\n", dev->name);		dev_kfree_skb(skb);		return;	}	pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);	auth_alg = le16_to_cpu(*pos++);	auth_transaction = le16_to_cpu(*pos++);	status = le16_to_cpu(*pos++);	if (!ok) {		txt = "frame was not ACKed";		goto done;	}	spin_lock(&ap->sta_table_lock);	sta = ap_get_sta(ap, hdr->addr1);	if (sta)		atomic_inc(&sta->users);	spin_unlock(&ap->sta_table_lock);	if (!sta) {		txt = "STA not found";		goto done;	}	if (status == WLAN_STATUS_SUCCESS &&	    ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||	     (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {		txt = "STA authenticated";		sta->flags |= WLAN_STA_AUTH;		sta->last_auth = jiffies;	} else if (status != WLAN_STATUS_SUCCESS)		txt = "authentication failed"; done:	if (sta)		atomic_dec(&sta->users);	if (txt) {		PDEBUG(DEBUG_AP, "%s: " MACSTR " auth_cb - alg=%d trans#=%d "		       "status=%d - %s\n",		       dev->name, MAC2STR(hdr->addr1), auth_alg,		       auth_transaction, status, txt);	}	dev_kfree_skb(skb);}/* Called only as a tasklet (software IRQ) */static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data){	struct ap_data *ap = data;	struct net_device *dev = ap->local->dev;	struct ieee80211_hdr_4addr *hdr;	u16 fc, *pos, status;	struct sta_info *sta = NULL;	char *txt = NULL;	if (ap->local->hostapd) {		dev_kfree_skb(skb);		return;	}	hdr = (struct ieee80211_hdr_4addr *) skb->data;	fc = le16_to_cpu(hdr->frame_ctl);	if (WLAN_FC_GET_TYPE(fc) != IEEE80211_FTYPE_MGMT ||	    (WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_ASSOC_RESP &&	     WLAN_FC_GET_STYPE(fc) != IEEE80211_STYPE_REASSOC_RESP) ||	    skb->len < IEEE80211_MGMT_HDR_LEN + 4) {		printk(KERN_DEBUG "%s: hostap_ap_tx_cb_assoc received invalid "		       "frame\n", dev->name);		dev_kfree_skb(skb);		return;	}	if (!ok) {		txt = "frame was not ACKed";		goto done;	}	spin_lock(&ap->sta_table_lock);	sta = ap_get_sta(ap, hdr->addr1);	if (sta)		atomic_inc(&sta->users);	spin_unlock(&ap->sta_table_lock);	if (!sta) {		txt = "STA not found";		goto done;	}	pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);	pos++;	status = le16_to_cpu(*pos++);	if (status == WLAN_STATUS_SUCCESS) {		if (!(sta->flags & WLAN_STA_ASSOC))			hostap_event_new_sta(dev, sta);		txt = "STA associated";		sta->flags |= WLAN_STA_ASSOC;		sta->last_assoc = jiffies;	} else		txt = "association failed"; done:	if (sta)		atomic_dec(&sta->users);	if (txt) {		PDEBUG(DEBUG_AP, "%s: " MACSTR " assoc_cb - %s\n",		       dev->name, MAC2STR(hdr->addr1), txt);	}	dev_kfree_skb(skb);}/* Called only as a tasklet (software IRQ); TX callback for poll frames used * in verifying whether the STA is still present. */static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data){	struct ap_data *ap = data;	struct ieee80211_hdr_4addr *hdr;	struct sta_info *sta;	if (skb->len < 24)		goto fail;	hdr = (struct ieee80211_hdr_4addr *) skb->data;	if (ok) {		spin_lock(&ap->sta_table_lock);		sta = ap_get_sta(ap, hdr->addr1);		if (sta)			sta->flags &= ~WLAN_STA_PENDING_POLL;		spin_unlock(&ap->sta_table_lock);	} else {		PDEBUG(DEBUG_AP, "%s: STA " MACSTR " did not ACK activity "		       "poll frame\n", ap->local->dev->name,		       MAC2STR(hdr->addr1));	} fail:	dev_kfree_skb(skb);}#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */void hostap_init_data(local_info_t *local){	struct ap_data *ap = local->ap;	if (ap == NULL) {		printk(KERN_WARNING "hostap_init_data: ap == NULL\n");		return;	}	memset(ap, 0, sizeof(struct ap_data));	ap->local = local;	ap->ap_policy = GET_INT_PARM(other_ap_policy, local->card_idx);	ap->bridge_packets = GET_INT_PARM(ap_bridge_packets, local->card_idx);	ap->max_inactivity =		GET_INT_PARM(ap_max_inactivity, local->card_idx) * HZ;	ap->autom_ap_wds = GET_INT_PARM(autom_ap_wds, local->card_idx);	spin_lock_init(&ap->sta_table_lock);	INIT_LIST_HEAD(&ap->sta_list);	/* Initialize task queue structure for AP management */	INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue, ap);	ap->tx_callback_idx =		hostap_tx_callback_register(local, hostap_ap_tx_cb, ap);	if (ap->tx_callback_idx == 0)		printk(KERN_WARNING "%s: failed to register TX callback for "		       "AP\n", local->dev->name);#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT	INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue, local);	ap->tx_callback_auth =		hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap);	ap->tx_callback_assoc =		hostap_tx_callback_register(local, hostap_ap_tx_cb_assoc, ap);	ap->tx_callback_poll =		hostap_tx_callback_register(local, hostap_ap_tx_cb_poll, ap);	if (ap->tx_callback_auth == 0 || ap->tx_callback_assoc == 0 ||		ap->tx_callback_poll == 0)		printk(KERN_WARNING "%s: failed to register TX callback for "		       "AP\n", local->dev->name);	spin_lock_init(&ap->mac_restrictions.lock);	INIT_LIST_HEAD(&ap->mac_restrictions.mac_list);#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */	ap->initialized = 1;}void hostap_init_ap_proc(local_info_t *local){	struct ap_data *ap = local->ap;	ap->proc = local->proc;	if (ap->proc == NULL)		return;#ifndef PRISM2_NO_PROCFS_DEBUG	create_proc_read_entry("ap_debug", 0, ap->proc,			       ap_debug_proc_read, ap);#endif /* PRISM2_NO_PROCFS_DEBUG */#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT	create_proc_read_entry("ap_control", 0, ap->proc,			       ap_control_proc_read, ap);	create_proc_read_entry("ap", 0, ap->proc,			       prism2_ap_proc_read, ap);#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */}void hostap_free_data(struct ap_data *ap){	struct list_head *n, *ptr;	if (ap == NULL || !ap->initialized) {		printk(KERN_DEBUG "hostap_free_data: ap has not yet been "		       "initialized - skip resource freeing\n");		return;	}#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT	if (ap->crypt)		ap->crypt->deinit(ap->crypt_priv);	ap->crypt = ap->crypt_priv = NULL;#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */	list_for_each_safe(ptr, n, &ap->sta_list) {		struct sta_info *sta = list_entry(ptr, struct sta_info, list);		ap_sta_hash_del(ap, sta);		list_del(&sta->list);		if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)			hostap_event_expired_sta(sta->local->dev, sta);		ap_free_sta(ap, sta);	}#ifndef PRISM2_NO_PROCFS_DEBUG	if (ap->proc != NULL) {		remove_proc_entry("ap_debug", ap->proc);	}#endif /* PRISM2_NO_PROCFS_DEBUG */#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT	if (ap->proc != NULL) {	  remove_proc_entry("ap", ap->proc);		remove_proc_entry("ap_control", ap->proc);	}	ap_control_flush_macs(&ap->mac_restrictions);#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */	ap->initialized = 0;}/* caller should have mutex for AP STA list handling */static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta){	struct sta_info *s;	s = ap->sta_hash[STA_HASH(sta)];	while (s != NULL && memcmp(s->addr, sta, ETH_ALEN) != 0)		s = s->hnext;	return s;}#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT/* Called from timer handler and from scheduled AP queue handlers */static void prism2_send_mgmt(struct net_device *dev,			     u16 type_subtype, char *body,			     int body_len, u8 *addr, u16 tx_cb_idx){	struct hostap_interface *iface;	local_info_t *local;	struct ieee80211_hdr_4addr *hdr;	u16 fc;	struct sk_buff *skb;	struct hostap_skb_tx_data *meta;	int hdrlen;	iface = netdev_priv(dev);	local = iface->local;	dev = local->dev; /* always use master radio device */	iface = netdev_priv(dev);	if (!(dev->flags & IFF_UP)) {		PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt - device is not UP - "		       "cannot send frame\n", dev->name);		return;	}	skb = dev_alloc_skb(sizeof(*hdr) + body_len);	if (skb == NULL) {		PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt failed to allocate "		       "skb\n", dev->name);		return;	}	fc = type_subtype;	hdrlen = hostap_80211_get_hdrlen(fc);	hdr = (struct ieee80211_hdr_4addr *) skb_put(skb, hdrlen);	if (body)		memcpy(skb_put(skb, body_len), body, body_len);	memset(hdr, 0, hdrlen);	/* FIX: ctrl::ack sending used special HFA384X_TX_CTRL_802_11	 * tx_control instead of using local->tx_control */	memcpy(hdr->addr1, addr, ETH_ALEN); /* DA / RA */	if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) {		fc |= IEEE80211_FCTL_FROMDS;		memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* BSSID */		memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* SA */	} else if (WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_CTL) {		/* control:ACK does not have addr2 or addr3 */		memset(hdr->addr2, 0, ETH_ALEN);		memset(hdr->addr3, 0, ETH_ALEN);	} else {		memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* SA */		memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* BSSID */	}

⌨️ 快捷键说明

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