[PATCH] : Scan in master mode

Jean Tourrilhes jt
Thu Dec 5 18:40:56 PST 2002


	Hi,

	As part of WE-16, I'm improving the iwspy support. HostAP is
currently problematic as I want to "reclaim" the SIOCGIWSPY call, and
HostAP currently uses it.

	So, I've decided 2 things :
	1) I've un-deprecated SIOCGIWAPLIST and broaden its
definition. You can now return any list of address you want, not only
APs, and will remain supported.
	2) I've made the little patch below (for 2002-10-12) and I'm
suggesting its inclusion in HostAP. The patch was *very* quickly
tested.

	Jouni, any comments ?

	Have fun...

	Jean

-------------- next part --------------
diff -u -p driver/modules.15/hostap.c driver/modules/hostap.c
--- driver/modules.15/hostap.c	Sun Sep 15 10:33:05 2002
+++ driver/modules/hostap.c	Thu Dec  5 18:25:47 2002
@@ -63,6 +63,9 @@ static int prism2_wds_del(local_info_t *
 static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
 				  struct iw_quality qual[], int buf_size,
 				  int aplist);
+#if WIRELESS_EXT > 13
+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+#endif /* WIRELESS_EXT > 13 */
 #endif /* WIRELESS_EXT */
 static int prism2_hostapd(struct ap_data *ap,
 			  struct prism2_hostapd_param *param);
diff -u -p driver/modules.15/hostap_ap.c driver/modules/hostap_ap.c
--- driver/modules.15/hostap_ap.c	Sat Sep 14 08:54:12 2002
+++ driver/modules/hostap_ap.c	Thu Dec  5 18:30:19 2002
@@ -2129,6 +2129,84 @@ static int prism2_ap_get_sta_qual(local_
 
 	return count;
 }
+
+#if WIRELESS_EXT > 13
+/* Translate our list of Access Points & Stations to a card independant
+ * format that the Wireless Tools will understand - Jean II */
+static int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
+{
+	local_info_t *local = (local_info_t *) dev->priv;
+	struct ap_data *ap = local->ap;
+	struct list_head *ptr;
+	unsigned long flags;
+	struct iw_event iwe;
+	char *current_ev = buffer;
+	char *end_buf = buffer + IW_SCAN_MAX_DATA;
+
+	spin_lock_irqsave(&ap->sta_table_lock, flags);
+
+	for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list;
+	     ptr = ptr->next) {
+		struct sta_info *sta = (struct sta_info *) ptr;
+
+		/* First entry *MUST* be the AP MAC address */
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = SIOCGIWAP;
+		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+		memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN);
+		iwe.len = IW_EV_ADDR_LEN;
+		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+						  IW_EV_ADDR_LEN);
+
+		/* Use the mode to indicate if it's a station or
+		 * an Access Point */
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = SIOCGIWMODE;
+		if (sta->ap)
+			iwe.u.mode = IW_MODE_MASTER;
+		else
+			iwe.u.mode = IW_MODE_INFRA;
+		iwe.len = IW_EV_UINT_LEN;
+		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+						  IW_EV_UINT_LEN);
+
+		/* Some quality */
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVQUAL;
+		if (sta->last_rx_silence == 0)
+			iwe.u.qual.qual = sta->last_rx_signal < 27 ?
+				0 : (sta->last_rx_signal - 27) * 92 / 127;
+		else
+			iwe.u.qual.qual = sta->last_rx_signal -
+				sta->last_rx_silence - 35;
+		iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
+		iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+		iwe.u.qual.updated = sta->last_rx_updated;
+		iwe.len = IW_EV_QUAL_LEN;
+		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+						  IW_EV_QUAL_LEN);
+		sta->last_rx_updated = 0;
+
+		/* To be continued, we should make good use of IWEVCUSTOM */
+	}
+	spin_unlock_irqrestore(&ap->sta_table_lock, flags);
+
+#if 0
+	{
+		u8 *pos = buffer;
+		left = (current_ev - buffer);
+		printk(KERN_DEBUG "IW SCAN (len=%d):", left);
+		while (left > 0) {
+			printk(" %02x", *pos++);
+			left--;
+		}
+		printk("\n");
+	}
+#endif
+
+	return current_ev - buffer;
+}
+#endif /* WIRELESS_EXT > 13 */
 #endif /* WIRELESS_EXT */
 
 
diff -u -p driver/modules.15/hostap_ioctl.c driver/modules/hostap_ioctl.c
--- driver/modules.15/hostap_ioctl.c	Sat Oct 12 04:37:26 2002
+++ driver/modules/hostap_ioctl.c	Thu Dec  5 18:18:08 2002
@@ -1369,20 +1369,24 @@ static int prism2_ioctl_siwscan(struct n
 				struct iw_request_info *info,
 				struct iw_point *data, char *extra)
 {
-#ifdef PRISM2_NO_STATION_MODES
-	return -EOPNOTSUPP;
-#else /* PRISM2_NO_STATION_MODES */
 	local_info_t *local = (local_info_t *) dev->priv;
+#ifndef PRISM2_NO_STATION_MODES
 	struct hfa384x_scan_request scan_req;
 	int ret = 0;
+#endif /* !PRISM2_NO_STATION_MODES */
 
 	if (local->iw_mode == IW_MODE_MASTER) {
-		printk(KERN_DEBUG "%s: SIOCSIWSCAN is currently only supported"
-		       " in Station modes\n", dev->name);
+		/* In master mode, we just return the results of our local
+		 * tables, so we don't need to start anything...
+		 * Jean II */
 		data->length = 0;
-		return -EOPNOTSUPP;
+		return 0;
 	}
 
+#ifdef PRISM2_NO_STATION_MODES
+	return -EOPNOTSUPP;
+#else /* PRISM2_NO_STATION_MODES */
+
 	memset(&scan_req, 0, sizeof(scan_req));
 	scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
 	scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
@@ -1490,7 +1494,7 @@ static inline int prism2_translate_scan(
 		if (capabilities & (WLAN_CAPABILITY_ESS |
 				    WLAN_CAPABILITY_IBSS)) {
 			if (capabilities & WLAN_CAPABILITY_ESS)
-				iwe.u.mode = IW_MODE_INFRA;
+				iwe.u.mode = IW_MODE_MASTER;
 			else
 				iwe.u.mode = IW_MODE_ADHOC;
 			iwe.len = IW_EV_UINT_LEN;
@@ -1569,10 +1573,9 @@ static inline int prism2_translate_scan(
 }
 #endif /* PRISM2_NO_STATION_MODES */
 
-
-static int prism2_ioctl_giwscan(struct net_device *dev,
-				struct iw_request_info *info,
-				struct iw_point *data, char *extra)
+static inline int prism2_ioctl_giwscan_sta(struct net_device *dev,
+					   struct iw_request_info *info,
+					   struct iw_point *data, char *extra)
 {
 #ifdef PRISM2_NO_STATION_MODES
 	return -EOPNOTSUPP;
@@ -1644,6 +1647,41 @@ static int prism2_ioctl_giwscan(struct n
 		return res;
 	}
 #endif /* PRISM2_NO_STATION_MODES */
+}
+
+static int prism2_ioctl_giwscan(struct net_device *dev,
+				struct iw_request_info *info,
+				struct iw_point *data, char *extra)
+{
+	local_info_t *local = (local_info_t *) dev->priv;
+	int res;
+
+	if (local->iw_mode == IW_MODE_MASTER) {
+		/* In MASTER mode, it doesn't make sense to go around
+		 * scanning the frequencies and make the stations we serve
+		 * wait when what the user is really interested about is the
+		 * list of stations and access points we are talking to.
+		 * So, just extract results from our cache...
+		 * Jean II */
+
+		/* Translate to WE format */
+		res = prism2_ap_translate_scan(dev, extra);
+		if (res >= 0) {
+			printk(KERN_DEBUG "Scan result translation succeeded "
+			       "(length=%d)\n", res);
+			data->length = res;
+			return 0;
+		} else {
+			printk(KERN_DEBUG
+			       "Scan result translation failed (res=%d)\n",
+			       res);
+			data->length = 0;
+			return res;
+		}
+	} else {
+		/* Station mode */
+		return prism2_ioctl_giwscan_sta(dev, info, data, extra);
+	}
 }
 #endif /* WIRELESS_EXT > 13 */
 



More information about the Hostap mailing list