]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
Merge branch 'master' into scan-test
authorJohannes Berg <johannes@sipsolutions.net>
Wed, 7 Jan 2009 20:58:47 +0000 (21:58 +0100)
committerJohannes Berg <johannes@sipsolutions.net>
Wed, 7 Jan 2009 20:58:47 +0000 (21:58 +0100)
Makefile
info.c
nl80211.h
scan.c [new file with mode: 0644]

index 2c629fec5974dc09580cc112c86d77945ddfea73..f57d04cfc21d1a4ebe77b2430350ac26e42d0972 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ CC ?= "gcc"
 CFLAGS ?= -O2 -g
 CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration
 
-OBJS = iw.o info.o phy.o interface.o station.o util.o mpath.o reg.o mesh.o genl.o
+OBJS = iw.o info.o phy.o interface.o station.o util.o mpath.o reg.o mesh.o genl.o scan.o
 ALL = iw
 
 NL1FOUND := $(shell pkg-config --atleast-version=1 libnl-1 && echo Y)
diff --git a/info.c b/info.c
index cbc3086df148aac1668ab837f9e88cd56a61d96d..7fb96ac76c5689e6020bc7082604bc7af74648f1 100644 (file)
--- a/info.c
+++ b/info.c
@@ -181,6 +181,10 @@ static int print_phy_handler(struct nl_msg *msg, void *arg)
                }
        }
 
+       if (tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
+               printf("\tmax # scan SSIDs: %d\n",
+                      nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]));
+
        if (!tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES])
                return NL_SKIP;
 
index e86ed59f9ad59b25317ce2be2f084a73063704c5..ea16da7c68df2c370c3d052024897208b3a2eb56 100644 (file)
--- a/nl80211.h
+++ b/nl80211.h
  * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the
  *      interface identified by %NL80211_ATTR_IFINDEX
  *
+ * @NL80211_CMD_GET_SCAN: get scan results
+ * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
+ * @NL80211_CMD_NEW_SCAN: scan notification (as a reply to NL80211_CMD_GET_SCAN
+ *     and on the "scan" multicast group)
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -178,6 +183,10 @@ enum nl80211_commands {
        NL80211_CMD_GET_MESH_PARAMS,
        NL80211_CMD_SET_MESH_PARAMS,
 
+       NL80211_CMD_GET_SCAN,
+       NL80211_CMD_TRIGGER_SCAN,
+       NL80211_CMD_NEW_SCAN,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -284,6 +293,13 @@ enum nl80211_commands {
  *     supported interface types, each a flag attribute with the number
  *     of the interface mode.
  *
+ * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with
+ *     a single scan request, a wiphy attribute.
+ *
+ * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies
+ * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs
+ * @NL80211_ATTR_BSS: scan result BSS
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -346,6 +362,13 @@ enum nl80211_attrs {
        NL80211_ATTR_WIPHY_FREQ,
        NL80211_ATTR_WIPHY_CHANNEL_TYPE,
 
+       NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
+
+       NL80211_ATTR_SCAN_FREQUENCIES,
+       NL80211_ATTR_SCAN_SSIDS,
+       NL80211_ATTR_SCAN_GENERATION,
+       NL80211_ATTR_BSS,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -811,4 +834,19 @@ enum nl80211_channel_type {
        NL80211_CHAN_HT40MINUS,
        NL80211_CHAN_HT40PLUS
 };
+
+enum nl80211_bss {
+       __NL80211_BSS_INVALID,
+       NL80211_BSS_BSSID,
+       NL80211_BSS_FREQUENCY,
+       NL80211_BSS_TSF,
+       NL80211_BSS_BEACON_INTERVAL,
+       NL80211_BSS_CAPABILITY,
+       NL80211_BSS_INFORMATION_ELEMENTS,
+
+       /* keep last */
+       __NL80211_BSS_AFTER_LAST,
+       NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/scan.c b/scan.c
new file mode 100644 (file)
index 0000000..218d853
--- /dev/null
+++ b/scan.c
@@ -0,0 +1,180 @@
+#include <net/if.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+
+#include "nl80211.h"
+#include "iw.h"
+
+static int handle_scan(struct nl_cb *cb,
+                      struct nl_msg *msg,
+                      int argc, char **argv)
+{
+       struct nl_msg *ssids = NULL;
+       int err = -ENOBUFS;
+
+       ssids = nlmsg_alloc();
+       if (!ssids)
+               return -ENOMEM;
+       NLA_PUT(ssids, 1, 0, "");
+       nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
+
+       err = 0;
+ nla_put_failure:
+       nlmsg_free(ssids);
+       return err;
+}
+COMMAND(scan, trigger, NULL,
+       NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan);
+
+typedef void (*printfn)(unsigned char type, unsigned char len, unsigned char *data);
+
+static void print_ssid(unsigned char type, unsigned char len, unsigned char *data)
+{
+       int i;
+       printf("\tSSID: ");
+       for (i=0; i<len; i++) {
+               if (isprint(data[i]))
+                       printf("%c", data[i]);
+               else
+                       printf("\\x%.2x", data[i]);
+       }
+       printf("\n");
+}
+
+static void print_supprates(unsigned char type, unsigned char len, unsigned char *data)
+{
+       int i;
+
+       if (type == 1)
+               printf("\tSupported rates: ");
+       else
+               printf("\tExtended supported rates: ");
+
+       for (i=0; i<len; i++) {
+               int r = data[i] & 0x7f;
+               printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":"");
+       }
+       printf("\n");
+}
+
+static void print_ds(unsigned char type, unsigned char len, unsigned char *data)
+{
+       printf("\tDS Parameter set: channel %d\n", data[0]);
+}
+
+static void print_ign(unsigned char type, unsigned char len, unsigned char *data)
+{
+       /* ignore for now, not too useful */
+}
+
+static void print_vendor(unsigned char type, unsigned char len, unsigned char *data)
+{
+       int i;
+
+       printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data: ",
+               data[0], data[1], data[2]);
+       for (i=3; i<len; i++)
+               printf("\\x%.2x", data[i]);
+       printf("\n");
+}
+
+static const printfn ieprinters[] = {
+       [0] = print_ssid,
+       [1] = print_supprates,
+       [3] = print_ds,
+       [5] = print_ign,
+       [50] = print_supprates,
+       [221] = print_vendor,
+};
+
+static void print_ies(unsigned char *ie, int ielen)
+{
+       while (ielen >= 2 && ielen >= ie[1]) {
+               if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]]) {
+                       ieprinters[ie[0]](ie[0], ie[1], ie + 2);
+               } else {
+                       int i;
+
+                       printf("\tUnknown IE (%d): ", ie[0]);
+                       for (i=0; i<ie[1]; i++)
+                               printf("\\x%.2x", ie[2+i]);
+                       printf("\n");
+               }
+               ielen -= ie[1] + 2;
+               ie += ie[1] + 2;
+       }
+}
+
+static int print_bss_handler(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *bss[NL80211_BSS_MAX + 1];
+       char mac_addr[20], dev[20];
+       static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+               [NL80211_BSS_TSF] = { .type = NLA_U64 },
+               [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
+               [NL80211_BSS_BSSID] = { },
+               [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
+               [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
+               [NL80211_BSS_INFORMATION_ELEMENTS] = { },
+       };
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+
+       if (!tb[NL80211_ATTR_BSS]) {
+               fprintf(stderr, "bss info missing!");
+               return NL_SKIP;
+       }
+       if (nla_parse_nested(bss, NL80211_BSS_MAX,
+                            tb[NL80211_ATTR_BSS],
+                            bss_policy)) {
+               fprintf(stderr, "failed to parse nested attributes!");
+               return NL_SKIP;
+       }
+
+       if (!bss[NL80211_BSS_BSSID])
+               return NL_SKIP;
+
+       mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
+       if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
+       printf("BSS %s (on %s)\n", mac_addr, dev);
+
+       if (bss[NL80211_BSS_TSF])
+               printf("\tTSF: %llu usec\n",
+                       (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]));
+       if (bss[NL80211_BSS_FREQUENCY])
+               printf("\tfreq: %d\n",
+                       nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
+       if (bss[NL80211_BSS_BEACON_INTERVAL])
+               printf("\tbeacon interval: %d\n",
+                       nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
+       if (bss[NL80211_BSS_CAPABILITY])
+               printf("\tcapability: 0x%.4x\n",
+                       nla_get_u16(bss[NL80211_BSS_CAPABILITY]));
+       if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
+               print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
+                         nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
+
+       return NL_SKIP;
+}
+
+
+
+static int handle_scan_dump(struct nl_cb *cb,
+                           struct nl_msg *msg,
+                           int argc, char **argv)
+{
+       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler, NULL);
+       return 0;
+}
+COMMAND(scan, dump, NULL,
+       NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump);