[OpenWrt-Devel] [PATCH] Allow scan of single channel

Dmitry Ivanov dmitrijs.ivanovs at ubnt.com
Thu Dec 17 05:47:29 EST 2015


Sometimes it is enough to scan single channel only. This is much faster
than scanning all of them and ingnoring unnecessary data.

Signed-off-by: Dmitry Ivanov <dima at ubnt.com>
---
 include/iwinfo.h |  1 +
 iwinfo_cli.c     | 65 ++++++++++++++++++++++++++++++++++++++++----------------
 iwinfo_nl80211.c | 33 +++++++++++++++++++++-------
 3 files changed, 73 insertions(+), 26 deletions(-)

diff --git a/include/iwinfo.h b/include/iwinfo.h
index f8cec73..e5ea48e 100644
--- a/include/iwinfo.h
+++ b/include/iwinfo.h
@@ -202,6 +202,7 @@ struct iwinfo_ops {
 	int (*assoclist)(const char *, char *, int *);
 	int (*txpwrlist)(const char *, char *, int *);
 	int (*scanlist)(const char *, char *, int *);
+	int (*scanlist2)(const char *, char *, int *, unsigned int);
 	int (*freqlist)(const char *, char *, int *);
 	int (*countrylist)(const char *, char *, int *);
 	int (*lookup_phy)(const char *, char *);
diff --git a/iwinfo_cli.c b/iwinfo_cli.c
index 7cb90c2..b0cc76d 100644
--- a/iwinfo_cli.c
+++ b/iwinfo_cli.c
@@ -562,18 +562,32 @@ static void print_info(const struct iwinfo_ops *iw, const char *ifname)
 }
 
 
-static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
+static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname, unsigned int freq)
 {
 	int i, x, len;
 	char buf[IWINFO_BUFSIZE];
 	struct iwinfo_scanlist_entry *e;
 
-	if (iw->scanlist(ifname, buf, &len))
+	if (freq)
+	{
+		if (!iw->scanlist2)
+		{
+			printf("Scanning of specific frequency not implemented\n\n");
+			return;
+		}
+		if (iw->scanlist2(ifname, buf, &len, freq))
+		{
+			printf("Scanning of specific frequency not possible\n\n");
+			return;
+		}
+	}
+	else if (iw->scanlist(ifname, buf, &len))
 	{
 		printf("Scanning not possible\n\n");
 		return;
 	}
-	else if (len <= 0)
+
+	if (len <= 0)
 	{
 		printf("No scan results\n\n");
 		return;
@@ -794,6 +808,7 @@ int main(int argc, char **argv)
 			"Usage:\n"
 			"	iwinfo <device> info\n"
 			"	iwinfo <device> scan\n"
+			"	iwinfo <device> scan <freq>\n"
 			"	iwinfo <device> txpowerlist\n"
 			"	iwinfo <device> freqlist\n"
 			"	iwinfo <device> assoclist\n"
@@ -831,25 +846,37 @@ int main(int argc, char **argv)
 
 	if (argc > 3)
 	{
-		iw = iwinfo_backend_by_name(argv[1]);
-
-		if (!iw)
-		{
-			fprintf(stderr, "No such wireless backend: %s\n", argv[1]);
-			rv = 1;
-		}
-		else
+		switch (argv[2][0])
 		{
-			switch (argv[2][0])
+		case 'p':
+			iw = iwinfo_backend_by_name(argv[1]);
+
+			if (!iw)
 			{
-			case 'p':
-				lookup_phy(iw, argv[3]);
-				break;
+				fprintf(stderr, "No such wireless backend: %s\n", argv[1]);
+				rv = 1;
+				goto finish;
+			}
+
+			lookup_phy(iw, argv[3]);
+			break;
+
+		case 's':
+			iw = iwinfo_backend(argv[1]);
 
-			default:
-				fprintf(stderr, "Unknown command: %s\n", argv[2]);
+			if (!iw)
+			{
+				fprintf(stderr, "No such wireless device: %s\n", argv[1]);
 				rv = 1;
+				goto finish;
 			}
+
+			print_scanlist(iw, argv[1], atoi(argv[3]));
+			break;
+
+		default:
+			fprintf(stderr, "Unknown command: %s\n", argv[2]);
+			rv = 1;
 		}
 	}
 	else
@@ -872,7 +899,7 @@ int main(int argc, char **argv)
 					break;
 
 				case 's':
-					print_scanlist(iw, argv[1]);
+					print_scanlist(iw, argv[1], 0);
 					break;
 
 				case 't':
@@ -903,6 +930,8 @@ int main(int argc, char **argv)
 		}
 	}
 
+finish:
+
 	iwinfo_finish();
 
 	return rv;
diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c
index a65ed1e..de4cdd1 100644
--- a/iwinfo_nl80211.c
+++ b/iwinfo_nl80211.c
@@ -2083,7 +2083,7 @@ static int nl80211_get_scanlist_cb(struct nl_msg *msg, void *arg)
 	return NL_SKIP;
 }
 
-static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len)
+static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len, unsigned int freq)
 {
 	struct nl80211_msg_conveyor *req;
 	struct nl80211_scanlist sl = { .e = (struct iwinfo_scanlist_entry *)buf };
@@ -2091,6 +2091,17 @@ static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len)
 	req = nl80211_msg(ifname, NL80211_CMD_TRIGGER_SCAN, 0);
 	if (req)
 	{
+		if (freq)
+		{
+			struct nlattr *freqs;
+			freqs = nla_nest_start(req->msg, NL80211_ATTR_SCAN_FREQUENCIES);
+			if (!freqs)
+				return -1;
+			if (nla_put_u32(req->msg, 1, freq))
+				return -1;
+			nla_nest_end(req->msg, freqs);
+		}
+
 		nl80211_send(req, NULL, NULL);
 		nl80211_free(req);
 	}
@@ -2298,7 +2309,7 @@ static int nl80211_get_scanlist_wpactl(const char *ifname, char *buf, int *len)
 	return (count >= 0) ? 0 : -1;
 }
 
-static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
+static int nl80211_get_scanlist2(const char *ifname, char *buf, int *len, unsigned int freq)
 {
 	char *res;
 	int rv, mode;
@@ -2311,13 +2322,13 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 		/* Reuse existing interface */
 		if ((res = nl80211_phy2ifname(ifname)) != NULL)
 		{
-			return nl80211_get_scanlist(res, buf, len);
+			return nl80211_get_scanlist2(res, buf, len, freq);
 		}
 
 		/* Need to spawn a temporary iface for scanning */
 		else if ((res = nl80211_ifadd(ifname)) != NULL)
 		{
-			rv = nl80211_get_scanlist(res, buf, len);
+			rv = nl80211_get_scanlist2(res, buf, len, freq);
 			nl80211_ifdel(res);
 			return rv;
 		}
@@ -2337,7 +2348,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 	          mode == IWINFO_OPMODE_MONITOR) &&
 	         iwinfo_ifup(ifname))
 	{
-		return nl80211_get_scanlist_nl(ifname, buf, len);
+		return nl80211_get_scanlist_nl(ifname, buf, len, freq);
 	}
 
 	/* AP scan */
@@ -2349,7 +2360,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 			if (!iwinfo_ifup(ifname))
 				return -1;
 
-			rv = nl80211_get_scanlist_nl(ifname, buf, len);
+			rv = nl80211_get_scanlist_nl(ifname, buf, len, freq);
 			iwinfo_ifdown(ifname);
 			return rv;
 		}
@@ -2366,7 +2377,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 			 * additional interface and there's no need to tear down the ap */
 			if (iwinfo_ifup(res))
 			{
-				rv = nl80211_get_scanlist_nl(res, buf, len);
+				rv = nl80211_get_scanlist_nl(res, buf, len, freq);
 				iwinfo_ifdown(res);
 			}
 
@@ -2374,7 +2385,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 			 * during scan */
 			else if (iwinfo_ifdown(ifname) && iwinfo_ifup(res))
 			{
-				rv = nl80211_get_scanlist_nl(res, buf, len);
+				rv = nl80211_get_scanlist_nl(res, buf, len, freq);
 				iwinfo_ifdown(res);
 				iwinfo_ifup(ifname);
 				nl80211_hostapd_hup(ifname);
@@ -2388,6 +2399,11 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 	return -1;
 }
 
+static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
+{
+	return nl80211_get_scanlist2(ifname, buf, len, 0);
+}
+
 static int nl80211_get_freqlist_cb(struct nl_msg *msg, void *arg)
 {
 	int bands_remain, freqs_remain;
@@ -2814,6 +2830,7 @@ const struct iwinfo_ops nl80211_ops = {
 	.assoclist        = nl80211_get_assoclist,
 	.txpwrlist        = nl80211_get_txpwrlist,
 	.scanlist         = nl80211_get_scanlist,
+	.scanlist2        = nl80211_get_scanlist2,
 	.freqlist         = nl80211_get_freqlist,
 	.countrylist      = nl80211_get_countrylist,
 	.lookup_phy       = nl80211_lookup_phyname,
-- 
2.1.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list