AA: iwinfo: merge r34982, r35005, r35007, r35471, r36292, r36339, r36417, r36449...
authorjow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 27 Apr 2013 09:45:06 +0000 (09:45 +0000)
committerjow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 27 Apr 2013 09:45:06 +0000 (09:45 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@36465 3c298f89-4303-0410-b956-a3cf2f4a3e73

package/iwinfo/Makefile
package/iwinfo/src/hardware.txt [new file with mode: 0644]
package/iwinfo/src/include/iwinfo.h
package/iwinfo/src/iwinfo_cli.c
package/iwinfo/src/iwinfo_lib.c
package/iwinfo/src/iwinfo_nl80211.c
package/iwinfo/src/iwinfo_utils.c

index bbef2bd..3758692 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2010-2012 Jo-Philipp Wich <xm@subsignal.org>
+# Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
 #
 # This is free software, licensed under the GPL 2 license.
 #
@@ -7,7 +7,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=libiwinfo
-PKG_RELEASE:=36
+PKG_RELEASE:=43
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 PKG_CONFIG_DEPENDS := \
@@ -39,7 +39,7 @@ define Package/libiwinfo-lua
   SECTION:=lang
   CATEGORY:=Languages
   TITLE:=libiwinfo Lua binding
-  DEPENDS:=+libiwinfo +liblua +lua
+  DEPENDS:=+libiwinfo +liblua
   MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
 endef
 
@@ -101,6 +101,8 @@ endef
 define Package/libiwinfo/install
        $(INSTALL_DIR) $(1)/usr/lib
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so $(1)/usr/lib/libiwinfo.so
+       $(INSTALL_DIR) $(1)/usr/share/libiwinfo
+       $(INSTALL_DATA) $(PKG_BUILD_DIR)/hardware.txt $(1)/usr/share/libiwinfo/hardware.txt
 endef
 
 define Package/libiwinfo-lua/install
diff --git a/package/iwinfo/src/hardware.txt b/package/iwinfo/src/hardware.txt
new file mode 100644 (file)
index 0000000..6b20518
--- /dev/null
@@ -0,0 +1,55 @@
+# libiwinfo hardware database
+# vendor id | device id | subsystem vendor id | subsystem device id |
+# txpower offset | frequency offset | "vendor name" | "device name"
+0xffff 0xffff 0xffff 0xb102    0      0  "Ubiquiti" "PowerStation2 (18V)"
+0xffff 0xffff 0xffff 0xb202    0      0  "Ubiquiti" "PowerStation2 (16D)"
+0xffff 0xffff 0xffff 0xb302    0      0  "Ubiquiti" "PowerStation2 (EXT)"
+0xffff 0xffff 0xffff 0xb105    0      0  "Ubiquiti" "PowerStation5 (22V)"
+0xffff 0xffff 0xffff 0xb305    0      0  "Ubiquiti" "PowerStation5 (EXT)"
+0xffff 0xffff 0xffff 0xc302    0      0  "Ubiquiti" "PicoStation2"
+0xffff 0xffff 0xffff 0xc3a2   10      0  "Ubiquiti" "PicoStation2 HP"
+0xffff 0xffff 0xffff 0xa105    0      0  "Ubiquiti" "WispStation5"
+0xffff 0xffff 0xffff 0xa002   10      0  "Ubiquiti" "LiteStation2"
+0xffff 0xffff 0xffff 0xa005    5      0  "Ubiquiti" "LiteStation5"
+0xffff 0xffff 0xffff 0xc002   10      0  "Ubiquiti" "NanoStation2"
+0xffff 0xffff 0xffff 0xc005    5      0  "Ubiquiti" "NanoStation5"
+0xffff 0xffff 0xffff 0xc102   10      0  "Ubiquiti" "NanoStation Loco2"
+0xffff 0xffff 0xffff 0xc105    5      0  "Ubiquiti" "NanoStation Loco5"
+0xffff 0xffff 0xffff 0xc202   10      0  "Ubiquiti" "Bullet2"
+0xffff 0xffff 0xffff 0xc205    5      0  "Ubiquiti" "Bullet5"
+0x168c 0x001b 0x0777 0x3002   10      0  "Ubiquiti" "XR2"
+0x168c 0x001b 0x7777 0x3002   10      0  "Ubiquiti" "XR2"
+0x168c 0x001b 0x0777 0x3b02   10      0  "Ubiquiti" "XR2.3"
+0x168c 0x001b 0x0777 0x3c02   10      0  "Ubiquiti" "XR2.6"
+0x168c 0x001b 0x0777 0x3b03   10      0  "Ubiquiti" "XR3-2.8"
+0x168c 0x001b 0x0777 0x3c03   10      0  "Ubiquiti" "XR3-3.6"
+0x168c 0x001b 0x0777 0x3003   10      0  "Ubiquiti" "XR3"
+0x168c 0x001b 0x0777 0x3004   10      0  "Ubiquiti" "XR4"
+0x168c 0x001b 0x0777 0x3005   10      0  "Ubiquiti" "XR5"
+0x168c 0x001b 0x7777 0x3005   10      0  "Ubiquiti" "XR5"
+0x168c 0x001b 0x0777 0x3007   10      0  "Ubiquiti" "XR7"
+0x168c 0x001b 0x0777 0x3009   10  -1520  "Ubiquiti" "XR9"
+0x168c 0x001b 0x168c 0x2063    0      0  "Atheros"  "AR5413"
+0x168c 0x0013 0x168c 0x1042    1      0  "Ubiquiti" "SRC"
+0x168c 0x0013 0x0777 0x2041   10      0  "Ubiquiti" "SR2"
+0x168c 0x0013 0x0777 0x2004    6      0  "Ubiquiti" "SR4"
+0x168c 0x0013 0x7777 0x2004    6      0  "Ubiquiti" "SR4"
+0x168c 0x0013 0x0777 0x1004    6      0  "Ubiquiti" "SR4C"
+0x168c 0x0013 0x7777 0x1004    6      0  "Ubiquiti" "SR4C"
+0x168c 0x0013 0x168c 0x2042    7      0  "Ubiquiti" "SR5"
+0x168c 0x0013 0x7777 0x2009   12  -1500  "Ubiquiti" "SR9"
+0x168c 0x0027 0x168c 0x2082    7      0  "Ubiquiti" "SR71A"
+0x168c 0x0027 0x0777 0x4082    7      0  "Ubiquiti" "SR71"
+0x168c 0x0029 0x0777 0x4005    7      0  "Ubiquiti" "SR71-15"
+0x168c 0x002a 0x0777 0xe302   12      0  "Ubiquiti" "PicoStation M2" /* ToDo: confirm offset */
+0x168c 0x002a 0x0777 0xe012   12      0  "Ubiquiti" "NanoStation M2" /* ToDo: confirm offset */
+0x168c 0x002a 0x0777 0xe005    5      0  "Ubiquiti" "NanoStation M5" /* ToDo: confirm offset */
+0x168c 0x002a 0x0777 0xe202   12      0  "Ubiquiti" "Bullet M2"
+0x168c 0x002a 0x0777 0xe805    5      0  "Ubiquiti" "Bullet M5"
+0x168c 0x0029 0x168c 0xa094    0      0  "Atheros"  "AR9220"
+0x168c 0x0029 0x168c 0xa095    0      0  "Atheros"  "AR9223"
+0x168c 0x002a 0x168c 0xa093    0      0  "Atheros"  "AR9280"
+0x168c 0x002b 0x168c 0xa091    0      0  "Atheros"  "AR9285"
+0x1814 0x3050 0x1814 0x0005    0      0  "RaLink"   "Rt3050"
+0x1814 0x3052 0x1814 0x0008    0      0  "RaLink"   "Rt3052"
+0x1814 0x3352 0x1814 0x000c    0      0  "RaLink"   "Rt3352"
index 868c10b..0d92d8d 100644 (file)
@@ -50,11 +50,16 @@ extern const char *IWINFO_AUTH_NAMES[];
 
 
 enum iwinfo_opmode {
-       IWINFO_OPMODE_UNKNOWN = 0,
-       IWINFO_OPMODE_MASTER  = 1,
-       IWINFO_OPMODE_ADHOC   = 2,
-       IWINFO_OPMODE_CLIENT  = 3,
-       IWINFO_OPMODE_MONITOR = 4,
+       IWINFO_OPMODE_UNKNOWN    = 0,
+       IWINFO_OPMODE_MASTER     = 1,
+       IWINFO_OPMODE_ADHOC      = 2,
+       IWINFO_OPMODE_CLIENT     = 3,
+       IWINFO_OPMODE_MONITOR    = 4,
+       IWINFO_OPMODE_AP_VLAN    = 5,
+       IWINFO_OPMODE_WDS        = 6,
+       IWINFO_OPMODE_MESHPOINT  = 7,
+       IWINFO_OPMODE_P2P_CLIENT = 8,
+       IWINFO_OPMODE_P2P_GO     = 9,
 };
 
 extern const char *IWINFO_OPMODE_NAMES[];
@@ -127,8 +132,8 @@ struct iwinfo_hardware_id {
 };
 
 struct iwinfo_hardware_entry {
-       const char *vendor_name;
-       const char *device_name;
+       char vendor_name[64];
+       char device_name[64];
        uint16_t vendor_id;
        uint16_t device_id;
        uint16_t subsystem_vendor_id;
@@ -138,7 +143,8 @@ struct iwinfo_hardware_entry {
 };
 
 extern const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[];
-extern const struct iwinfo_hardware_entry IWINFO_HARDWARE_ENTRIES[];
+
+#define IWINFO_HARDWARE_FILE   "/usr/share/libiwinfo/hardware.txt"
 
 
 struct iwinfo_ops {
index 7ec5aef..8da216a 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <stdio.h>
+#include <glob.h>
 
 #include "iwinfo.h"
 
@@ -735,9 +736,11 @@ static void print_countrylist(const struct iwinfo_ops *iw, const char *ifname)
 int main(int argc, char **argv)
 {
        int i;
+       char *p;
        const struct iwinfo_ops *iw;
+       glob_t globbuf;
 
-       if (argc < 3)
+       if (argc > 1 && argc < 3)
        {
                fprintf(stderr,
                        "Usage:\n"
@@ -752,6 +755,30 @@ int main(int argc, char **argv)
                return 1;
        }
 
+       if (argc == 1)
+       {
+               glob("/sys/class/net/*", 0, NULL, &globbuf);
+
+               for (i = 0; i < globbuf.gl_pathc; i++)
+               {
+                       p = strrchr(globbuf.gl_pathv[i], '/');
+
+                       if (!p)
+                               continue;
+
+                       iw = iwinfo_backend(++p);
+
+                       if (!iw)
+                               continue;
+
+                       print_info(iw, p);
+                       printf("\n");
+               }
+
+               globfree(&globbuf);
+               return 0;
+       }
+
        iw = iwinfo_backend(argv[1]);
 
        if (!iw)
index dd65e45..df1f450 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * iwinfo - Wireless Information Library - Lua Bindings
  *
- *   Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
+ *   Copyright (C) 2009-2013 Jo-Philipp Wich <xm@subsignal.org>
  *
  * The iwinfo library is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -50,6 +50,11 @@ const char *IWINFO_OPMODE_NAMES[] = {
        "Ad-Hoc",
        "Client",
        "Monitor",
+       "Master (VLAN)",
+       "WDS",
+       "Mesh Point",
+       "P2P Client",
+       "P2P Go",
 };
 
 
@@ -308,75 +313,6 @@ const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[] = {
        { 0,               "" }
 };
 
-/*
- * hardware database
- */
-
-const char VENDOR_UBNT[] = "Ubiquiti";
-const char VENDOR_ATH[]  = "Atheros";
-const char VENDOR_RALINK[]  = "RaLink";
-
-const struct iwinfo_hardware_entry IWINFO_HARDWARE_ENTRIES[] = {
-/*     { vendor, model, vendorid, deviceid, subsys vendorid, subsys deviceid, poweroff, freqoff } */
-#if defined(USE_MADWIFI) || defined(USE_NL80211)
-       { VENDOR_UBNT, "PowerStation2 (18V)",   0xffff, 0xffff, 0xffff, 0xb102,  0,     0 },
-       { VENDOR_UBNT, "PowerStation2 (16D)",   0xffff, 0xffff, 0xffff, 0xb202,  0,     0 },
-       { VENDOR_UBNT, "PowerStation2 (EXT)",   0xffff, 0xffff, 0xffff, 0xb302,  0,     0 },
-       { VENDOR_UBNT, "PowerStation5 (22V)",   0xffff, 0xffff, 0xffff, 0xb105,  0,     0 },
-       { VENDOR_UBNT, "PowerStation5 (EXT)",   0xffff, 0xffff, 0xffff, 0xb305,  0,     0 },
-       { VENDOR_UBNT, "PicoStation2",          0xffff, 0xffff, 0xffff, 0xc302,  0,     0 },
-       { VENDOR_UBNT, "PicoStation2 HP",       0xffff, 0xffff, 0xffff, 0xc3a2, 10,     0 },
-       { VENDOR_UBNT, "WispStation5",          0xffff, 0xffff, 0xffff, 0xa105,  0,     0 },
-       { VENDOR_UBNT, "LiteStation2",          0xffff, 0xffff, 0xffff, 0xa002, 10,     0 },
-       { VENDOR_UBNT, "LiteStation5",          0xffff, 0xffff, 0xffff, 0xa005,  5,     0 },
-       { VENDOR_UBNT, "NanoStation2",          0xffff, 0xffff, 0xffff, 0xc002, 10,     0 },
-       { VENDOR_UBNT, "NanoStation5",          0xffff, 0xffff, 0xffff, 0xc005,  5,     0 },
-       { VENDOR_UBNT, "NanoStation Loco2",     0xffff, 0xffff, 0xffff, 0xc102, 10,     0 },
-       { VENDOR_UBNT, "NanoStation Loco5",     0xffff, 0xffff, 0xffff, 0xc105,  5,     0 },
-       { VENDOR_UBNT, "Bullet2",               0xffff, 0xffff, 0xffff, 0xc202, 10,     0 },
-       { VENDOR_UBNT, "Bullet5",               0xffff, 0xffff, 0xffff, 0xc205,  5,     0 },
-       { VENDOR_UBNT, "XR2",                   0x168c, 0x001b, 0x0777, 0x3002, 10,     0 },
-       { VENDOR_UBNT, "XR2",                   0x168c, 0x001b, 0x7777, 0x3002, 10,     0 },
-       { VENDOR_UBNT, "XR2.3",                 0x168c, 0x001b, 0x0777, 0x3b02, 10,     0 },
-       { VENDOR_UBNT, "XR2.6",                 0x168c, 0x001b, 0x0777, 0x3c02, 10,     0 },
-       { VENDOR_UBNT, "XR3-2.8",               0x168c, 0x001b, 0x0777, 0x3b03, 10,     0 },
-       { VENDOR_UBNT, "XR3-3.6",               0x168c, 0x001b, 0x0777, 0x3c03, 10,     0 },
-       { VENDOR_UBNT, "XR3",                   0x168c, 0x001b, 0x0777, 0x3003, 10,     0 },
-       { VENDOR_UBNT, "XR4",                   0x168c, 0x001b, 0x0777, 0x3004, 10,     0 },
-       { VENDOR_UBNT, "XR5",                   0x168c, 0x001b, 0x0777, 0x3005, 10,     0 },
-       { VENDOR_UBNT, "XR5",                   0x168c, 0x001b, 0x7777, 0x3005, 10,     0 },
-       { VENDOR_UBNT, "XR7",                   0x168c, 0x001b, 0x0777, 0x3007, 10,     0 },
-       { VENDOR_UBNT, "XR9",                   0x168c, 0x001b, 0x0777, 0x3009, 10, -1520 },
-       { VENDOR_ATH,  "AR5413",                0x168c, 0x001b, 0x168c, 0x2063,  0,     0 },
-       { VENDOR_UBNT, "SRC",                   0x168c, 0x0013, 0x168c, 0x1042,  1,     0 },
-       { VENDOR_UBNT, "SR2",                   0x168c, 0x0013, 0x0777, 0x2041, 10,     0 },
-       { VENDOR_UBNT, "SR4",                   0x168c, 0x0013, 0x0777, 0x2004,  6,     0 },
-       { VENDOR_UBNT, "SR4",                   0x168c, 0x0013, 0x7777, 0x2004,  6,     0 },
-       { VENDOR_UBNT, "SR4C",                  0x168c, 0x0013, 0x0777, 0x1004,  6,     0 },
-       { VENDOR_UBNT, "SR4C",                  0x168c, 0x0013, 0x7777, 0x1004,  6,     0 },
-       { VENDOR_UBNT, "SR5",                   0x168c, 0x0013, 0x168c, 0x2042,  7,     0 },
-       { VENDOR_UBNT, "SR9",                   0x168c, 0x0013, 0x7777, 0x2009, 12, -1500 },
-       { VENDOR_UBNT, "SR71A",                 0x168c, 0x0027, 0x168c, 0x2082, 10,     0 },
-       { VENDOR_UBNT, "SR71",                  0x168c, 0x0027, 0x0777, 0x4082, 10,     0 },
-#endif
-#ifdef USE_NL80211
-       { VENDOR_UBNT, "PicoStation M2",        0x168c, 0x002a, 0x0777, 0xe302, 12,     0 }, /* ToDo: confirm offset */
-       { VENDOR_UBNT, "NanoStation M2",        0x168c, 0x002a, 0x0777, 0xe012, 12,     0 }, /* ToDo: confirm offset */
-       { VENDOR_UBNT, "NanoStation M5",        0x168c, 0x002a, 0x0777, 0xe005,  5,     0 }, /* ToDo: confirm offset */
-       { VENDOR_UBNT, "Bullet M2",             0x168c, 0x002a, 0x0777, 0xe202, 12,     0 },
-       { VENDOR_UBNT, "Bullet M5",             0x168c, 0x002a, 0x0777, 0xe805,  5,     0 },
-
-       { VENDOR_ATH,  "AR9220",                0x168c, 0x0029, 0x168c, 0xa094,  0,     0 },
-       { VENDOR_ATH,  "AR9223",                0x168c, 0x0029, 0x168c, 0xa095,  0,     0 },
-       { VENDOR_ATH,  "AR9280",                0x168c, 0x002a, 0x168c, 0xa093,  0,     0 },
-       { VENDOR_ATH,  "AR9285",                0x168c, 0x002b, 0x168c, 0xa091,  0,     0 },
-       { VENDOR_RALINK,  "Rt3050",             0x1814, 0x3050, 0x1814, 0x0005,  0,     0 },
-       { VENDOR_RALINK,  "Rt3052",             0x1814, 0x3052, 0x1814, 0x0008,  0,     0 },
-       { VENDOR_RALINK,  "Rt3352",             0x1814, 0x3352, 0x1814, 0x000c,  0,     0 },
-#endif
-       { NULL }
-};
-
 
 const char * iwinfo_type(const char *ifname)
 {
index 763ed61..dd619e2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * iwinfo - Wireless Information Library - NL80211 Backend
  *
- *   Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *   Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
  *
  * The iwinfo library is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -346,23 +346,30 @@ static int nl80211_freq2channel(int freq)
 {
        if (freq == 2484)
                return 14;
-
-       if (freq < 2484)
+       else if (freq < 2484)
                return (freq - 2407) / 5;
-
-       return (freq / 5) - 1000;
+       else if (freq >= 4910 && freq <= 4980)
+               return (freq - 4000) / 5;
+       else
+               return (freq - 5000) / 5;
 }
 
 static int nl80211_channel2freq(int channel, const char *band)
 {
-       if (channel == 14)
-               return 2484;
-
-       if ((channel < 14) && (!band || band[0] != 'a'))
-               return (channel * 5) + 2407;
-
-       if (channel > 0)
-               return (1000 + channel) * 5;
+       if (!band || band[0] != 'a')
+       {
+               if (channel == 14)
+                       return 2484;
+               else if (channel < 14)
+                       return (channel * 5) + 2407;
+       }
+       else
+       {
+               if (channel >= 182 && channel <= 196)
+                       return (channel * 5) + 4000;
+               else
+                       return (channel * 5) + 5000;
+       }
 
        return 0;
 }
@@ -448,12 +455,17 @@ static char * nl80211_ifname2phy(const char *ifname)
 
 static char * nl80211_hostapd_info(const char *ifname)
 {
+       int mode;
        char *phy;
        char path[32] = { 0 };
        static char buf[4096] = { 0 };
        FILE *conf;
 
-       if ((phy = nl80211_ifname2phy(ifname)) != NULL)
+       if (nl80211_get_mode(ifname, &mode))
+               return NULL;
+
+       if ((mode == IWINFO_OPMODE_MASTER || mode == IWINFO_OPMODE_AP_VLAN) &&
+           (phy = nl80211_ifname2phy(ifname)) != NULL)
        {
                snprintf(path, sizeof(path), "/var/run/hostapd-%s.conf", phy);
 
@@ -716,50 +728,180 @@ void nl80211_close(void)
        }
 }
 
+
+static int nl80211_get_mode_cb(struct nl_msg *msg, void *arg)
+{
+       int *mode = arg;
+       struct nlattr **tb = nl80211_parse(msg);
+       const int ifmodes[NL80211_IFTYPE_MAX + 1] = {
+               IWINFO_OPMODE_UNKNOWN,          /* unspecified */
+               IWINFO_OPMODE_ADHOC,            /* IBSS */
+               IWINFO_OPMODE_CLIENT,           /* managed */
+               IWINFO_OPMODE_MASTER,           /* AP */
+               IWINFO_OPMODE_AP_VLAN,          /* AP/VLAN */
+               IWINFO_OPMODE_WDS,                      /* WDS */
+               IWINFO_OPMODE_MONITOR,          /* monitor */
+               IWINFO_OPMODE_MESHPOINT,        /* mesh point */
+               IWINFO_OPMODE_P2P_CLIENT,       /* P2P-client */
+               IWINFO_OPMODE_P2P_GO,           /* P2P-GO */
+       };
+
+       if (tb[NL80211_ATTR_IFTYPE])
+               *mode = ifmodes[nla_get_u32(tb[NL80211_ATTR_IFTYPE])];
+
+       return NL_SKIP;
+}
+
 int nl80211_get_mode(const char *ifname, int *buf)
 {
-       return wext_get_mode(ifname, buf);
+       char *res;
+       struct nl80211_msg_conveyor *req;
+
+       res = nl80211_phy2ifname(ifname);
+       req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0);
+       *buf = IWINFO_OPMODE_UNKNOWN;
+
+       if (req)
+       {
+               nl80211_send(req, nl80211_get_mode_cb, buf);
+               nl80211_free(req);
+       }
+
+       return (*buf == IWINFO_OPMODE_UNKNOWN) ? -1 : 0;
+}
+
+
+struct nl80211_ssid_bssid {
+       unsigned char *ssid;
+       unsigned char bssid[7];
+};
+
+static int nl80211_get_ssid_bssid_cb(struct nl_msg *msg, void *arg)
+{
+       int ielen;
+       unsigned char *ie;
+       struct nl80211_ssid_bssid *sb = arg;
+       struct nlattr **tb = nl80211_parse(msg);
+       struct nlattr *bss[NL80211_BSS_MAX + 1];
+
+       static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
+               [NL80211_BSS_INFORMATION_ELEMENTS] = {                 },
+               [NL80211_BSS_STATUS]               = { .type = NLA_U32 },
+       };
+
+       if (!tb[NL80211_ATTR_BSS] ||
+           nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
+                            bss_policy) ||
+           !bss[NL80211_BSS_BSSID] ||
+           !bss[NL80211_BSS_STATUS] ||
+           !bss[NL80211_BSS_INFORMATION_ELEMENTS])
+       {
+               return NL_SKIP;
+       }
+
+       switch (nla_get_u32(bss[NL80211_BSS_STATUS]))
+       {
+       case NL80211_BSS_STATUS_ASSOCIATED:
+       case NL80211_BSS_STATUS_AUTHENTICATED:
+       case NL80211_BSS_STATUS_IBSS_JOINED:
+
+               if (sb->ssid)
+               {
+                       ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+                       ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
+
+                       while (ielen >= 2 && ielen >= ie[1])
+                       {
+                               if (ie[0] == 0)
+                               {
+                                       memcpy(sb->ssid, ie + 2, min(ie[1], IWINFO_ESSID_MAX_SIZE));
+                                       return NL_SKIP;
+                               }
+
+                               ielen -= ie[1] + 2;
+                               ie += ie[1] + 2;
+                       }
+               }
+               else
+               {
+                       sb->bssid[0] = 1;
+                       memcpy(sb->bssid + 1, nla_data(bss[NL80211_BSS_BSSID]), 6);
+                       return NL_SKIP;
+               }
+
+       default:
+               return NL_SKIP;
+       }
 }
 
 int nl80211_get_ssid(const char *ifname, char *buf)
 {
-       char *ssid;
+       char *res;
+       struct nl80211_msg_conveyor *req;
+       struct nl80211_ssid_bssid sb;
+
+       /* try to find ssid from scan dump results */
+       res = nl80211_phy2ifname(ifname);
+       req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
+
+       sb.ssid = buf;
+       *buf = 0;
 
-       if (!wext_get_ssid(ifname, buf))
+       if (req)
        {
-               return 0;
+               nl80211_send(req, nl80211_get_ssid_bssid_cb, &sb);
+               nl80211_free(req);
        }
-       else if ((ssid = nl80211_hostapd_info(ifname)) &&
-                (ssid = nl80211_getval(ifname, ssid, "ssid")))
+
+       /* failed, try to find from hostapd info */
+       if ((*buf == 0) &&
+           (res = nl80211_hostapd_info(ifname)) &&
+           (res = nl80211_getval(ifname, res, "ssid")))
        {
-               memcpy(buf, ssid, strlen(ssid));
-               return 0;
+               memcpy(buf, res, strlen(res));
        }
 
-       return -1;
+       return (*buf == 0) ? -1 : 0;
 }
 
 int nl80211_get_bssid(const char *ifname, char *buf)
 {
-       char *bssid;
-       unsigned char mac[6];
+       char *res;
+       struct nl80211_msg_conveyor *req;
+       struct nl80211_ssid_bssid sb;
+
+       /* try to find bssid from scan dump results */
+       res = nl80211_phy2ifname(ifname);
+       req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
 
-       if (!wext_get_bssid(ifname, buf))
+       sb.ssid = NULL;
+       sb.bssid[0] = 0;
+
+       if (req)
        {
-               return 0;
+               nl80211_send(req, nl80211_get_ssid_bssid_cb, &sb);
+               nl80211_free(req);
        }
-       else if ((bssid = nl80211_hostapd_info(ifname)) &&
-                (bssid = nl80211_getval(ifname, bssid, "bssid")))
+
+       /* failed, try to find mac from hostapd info */
+       if ((sb.bssid[0] == 0) &&
+           (res = nl80211_hostapd_info(ifname)) &&
+           (res = nl80211_getval(ifname, res, "bssid")))
        {
-               mac[0] = strtol(&bssid[0],  NULL, 16);
-               mac[1] = strtol(&bssid[3],  NULL, 16);
-               mac[2] = strtol(&bssid[6],  NULL, 16);
-               mac[3] = strtol(&bssid[9],  NULL, 16);
-               mac[4] = strtol(&bssid[12], NULL, 16);
-               mac[5] = strtol(&bssid[15], NULL, 16);
+               sb.bssid[0] = 1;
+               sb.bssid[1] = strtol(&res[0],  NULL, 16);
+               sb.bssid[2] = strtol(&res[3],  NULL, 16);
+               sb.bssid[3] = strtol(&res[6],  NULL, 16);
+               sb.bssid[4] = strtol(&res[9],  NULL, 16);
+               sb.bssid[5] = strtol(&res[12], NULL, 16);
+               sb.bssid[6] = strtol(&res[15], NULL, 16);
+       }
 
+       if (sb.bssid[0])
+       {
                sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
-                       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+                       sb.bssid[1], sb.bssid[2], sb.bssid[3],
+                       sb.bssid[4], sb.bssid[5], sb.bssid[6]);
 
                return 0;
        }
@@ -768,7 +910,7 @@ int nl80211_get_bssid(const char *ifname, char *buf)
 }
 
 
-static int nl80211_get_frequency_cb(struct nl_msg *msg, void *arg)
+static int nl80211_get_frequency_scan_cb(struct nl_msg *msg, void *arg)
 {
        int *freq = arg;
        struct nlattr **attr = nl80211_parse(msg);
@@ -789,28 +931,56 @@ static int nl80211_get_frequency_cb(struct nl_msg *msg, void *arg)
        return NL_SKIP;
 }
 
+static int nl80211_get_frequency_info_cb(struct nl_msg *msg, void *arg)
+{
+       int *freq = arg;
+       struct nlattr **tb = nl80211_parse(msg);
+
+       if (tb[NL80211_ATTR_WIPHY_FREQ])
+               *freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
+
+       return NL_SKIP;
+}
+
 int nl80211_get_frequency(const char *ifname, int *buf)
 {
+       int chn;
        char *res, *channel;
        struct nl80211_msg_conveyor *req;
 
+       /* try to find frequency from interface info */
+       res = nl80211_phy2ifname(ifname);
+       req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0);
        *buf = 0;
 
-       if ((res = nl80211_hostapd_info(ifname)) &&
+       if (req)
+       {
+               nl80211_send(req, nl80211_get_frequency_info_cb, buf);
+               nl80211_free(req);
+       }
+
+       /* failed, try to find frequency from hostapd info */
+       if ((*buf == 0) &&
+           (res = nl80211_hostapd_info(ifname)) &&
            (channel = nl80211_getval(NULL, res, "channel")))
        {
-               *buf = nl80211_channel2freq(atoi(channel),
-                                           nl80211_getval(NULL, res, "hw_mode"));
+               chn = atoi(channel);
+               *buf = nl80211_channel2freq(chn, nl80211_getval(NULL, res, "hw_mode"));
        }
        else
        {
-               res = nl80211_phy2ifname(ifname);
-               req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP);
-
-               if (req)
+               /* failed, try to find frequency from scan results */
+               if (*buf == 0)
                {
-                       nl80211_send(req, nl80211_get_frequency_cb, buf);
-                       nl80211_free(req);
+                       res = nl80211_phy2ifname(ifname);
+                       req = nl80211_msg(res ? res : ifname, NL80211_CMD_GET_SCAN,
+                                         NLM_F_DUMP);
+
+                       if (req)
+                       {
+                               nl80211_send(req, nl80211_get_frequency_scan_cb, buf);
+                               nl80211_free(req);
+                       }
                }
        }
 
@@ -831,6 +1001,18 @@ int nl80211_get_channel(const char *ifname, int *buf)
 
 int nl80211_get_txpower(const char *ifname, int *buf)
 {
+#if 0
+       char *res;
+       char path[PATH_MAX];
+
+       res = nl80211_ifname2phy(ifname);
+       snprintf(path, sizeof(path), "/sys/kernel/debug/ieee80211/%s/power",
+                res ? res : ifname);
+
+       if ((*buf = nl80211_readint(path)) > -1)
+               return 0;
+#endif
+
        return wext_get_txpower(ifname, buf);
 }
 
@@ -931,9 +1113,6 @@ int nl80211_get_bitrate(const char *ifname, int *buf)
 {
        struct nl80211_rssi_rate rr;
 
-       if (!wext_get_bitrate(ifname, buf))
-               return 0;
-
        nl80211_fill_signal(ifname, &rr);
 
        if (rr.rate)
@@ -949,9 +1128,6 @@ int nl80211_get_signal(const char *ifname, int *buf)
 {
        struct nl80211_rssi_rate rr;
 
-       if (!wext_get_signal(ifname, buf))
-               return 0;
-
        nl80211_fill_signal(ifname, &rr);
 
        if (rr.rssi)
@@ -1018,43 +1194,39 @@ int nl80211_get_quality(const char *ifname, int *buf)
 {
        int signal;
 
-       if (wext_get_quality(ifname, buf))
+       if (!nl80211_get_signal(ifname, &signal))
        {
-               *buf = 0;
-
-               if (!nl80211_get_signal(ifname, &signal))
+               /* A positive signal level is usually just a quality
+                * value, pass through as-is */
+               if (signal >= 0)
                {
-                       /* A positive signal level is usually just a quality
-                        * value, pass through as-is */
-                       if (signal >= 0)
-                       {
-                               *buf = signal;
-                       }
+                       *buf = signal;
+               }
 
-                       /* The cfg80211 wext compat layer assumes a signal range
-                        * of -110 dBm to -40 dBm, the quality value is derived
-                        * by adding 110 to the signal level */
-                       else
-                       {
-                               if (signal < -110)
-                                       signal = -110;
-                               else if (signal > -40)
-                                       signal = -40;
+               /* The cfg80211 wext compat layer assumes a signal range
+                * of -110 dBm to -40 dBm, the quality value is derived
+                * by adding 110 to the signal level */
+               else
+               {
+                       if (signal < -110)
+                               signal = -110;
+                       else if (signal > -40)
+                               signal = -40;
 
-                               *buf = (signal + 110);
-                       }
+                       *buf = (signal + 110);
                }
+
+               return 0;
        }
 
-       return 0;
+       return -1;
 }
 
 int nl80211_get_quality_max(const char *ifname, int *buf)
 {
-       if (wext_get_quality_max(ifname, buf))
-               /* The cfg80211 wext compat layer assumes a maximum
-                * quality of 70 */
-               *buf = 70;
+       /* The cfg80211 wext compat layer assumes a maximum
+        * quality of 70 */
+       *buf = 70;
 
        return 0;
 }
index 164e51f..b6760c3 100644 (file)
@@ -28,7 +28,7 @@ static int ioctl_socket = -1;
 static int iwinfo_ioctl_socket(void)
 {
        /* Prepare socket */
-       if( ioctl_socket == -1 )
+       if (ioctl_socket == -1)
        {
                ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
                fcntl(ioctl_socket, F_SETFD, fcntl(ioctl_socket, F_GETFD) | FD_CLOEXEC);
@@ -82,7 +82,7 @@ int iwinfo_ifup(const char *ifname)
 
        strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
 
-       if( iwinfo_ioctl(SIOCGIFFLAGS, &ifr) )
+       if (iwinfo_ioctl(SIOCGIFFLAGS, &ifr))
                return 0;
 
        ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
@@ -96,7 +96,7 @@ int iwinfo_ifdown(const char *ifname)
 
        strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
 
-       if( iwinfo_ioctl(SIOCGIFFLAGS, &ifr) )
+       if (iwinfo_ioctl(SIOCGIFFLAGS, &ifr))
                return 0;
 
        ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
@@ -110,7 +110,7 @@ int iwinfo_ifmac(const char *ifname)
 
        strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
 
-       if( iwinfo_ioctl(SIOCGIFHWADDR, &ifr) )
+       if (iwinfo_ioctl(SIOCGIFHWADDR, &ifr))
                return 0;
 
        ifr.ifr_hwaddr.sa_data[1]++;
@@ -121,33 +121,54 @@ int iwinfo_ifmac(const char *ifname)
 
 void iwinfo_close(void)
 {
-       if( ioctl_socket > -1 )
+       if (ioctl_socket > -1)
                close(ioctl_socket);
+
+       ioctl_socket = -1;
 }
 
 struct iwinfo_hardware_entry * iwinfo_hardware(struct iwinfo_hardware_id *id)
 {
-       const struct iwinfo_hardware_entry *e;
+       FILE *db;
+       char buf[256] = { 0 };
+       static struct iwinfo_hardware_entry e;
+
+       if (!(db = fopen(IWINFO_HARDWARE_FILE, "r")))
+               return NULL;
 
-       for (e = IWINFO_HARDWARE_ENTRIES; e->vendor_name; e++)
+       while (fgets(buf, sizeof(buf) - 1, db) != NULL)
        {
-               if ((e->vendor_id != 0xffff) && (e->vendor_id != id->vendor_id))
+               memset(&e, 0, sizeof(e));
+
+               if (sscanf(buf, "%hx %hx %hx %hx %hd %hd \"%63[^\"]\" \"%63[^\"]\"",
+                              &e.vendor_id, &e.device_id,
+                              &e.subsystem_vendor_id, &e.subsystem_device_id,
+                              &e.txpower_offset, &e.frequency_offset,
+                              e.vendor_name, e.device_name) < 8)
+                       continue;
+
+               if ((e.vendor_id != 0xffff) && (e.vendor_id != id->vendor_id))
                        continue;
 
-               if ((e->device_id != 0xffff) && (e->device_id != id->device_id))
+               if ((e.device_id != 0xffff) && (e.device_id != id->device_id))
                        continue;
 
-               if ((e->subsystem_vendor_id != 0xffff) &&
-                       (e->subsystem_vendor_id != id->subsystem_vendor_id))
+               if ((e.subsystem_vendor_id != 0xffff) &&
+                       (e.subsystem_vendor_id != id->subsystem_vendor_id))
                        continue;
 
-               if ((e->subsystem_device_id != 0xffff) &&
-                       (e->subsystem_device_id != id->subsystem_device_id))
+               if ((e.subsystem_device_id != 0xffff) &&
+                       (e.subsystem_device_id != id->subsystem_device_id))
                        continue;
 
-               return (struct iwinfo_hardware_entry *)e;
+               break;
        }
 
+       fclose(db);
+
+       if (e.device_name[0])
+               return &e;
+
        return NULL;
 }