iwinfo: fix handling of accessing nl80211 interfaces via radio*
[openwrt/openwrt.git] / package / network / utils / iwinfo / src / iwinfo_utils.c
index 164e51f847ad72c95f2b6348d2e2dd7872186ed1..b313ea2049ca540c24b1922d085485a845c346bf 100644 (file)
 
 
 static int ioctl_socket = -1;
+struct uci_context *uci_ctx = NULL;
 
 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 +83,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 +97,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,9 +111,10 @@ 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[0] |= 0x02;
        ifr.ifr_hwaddr.sa_data[1]++;
        ifr.ifr_hwaddr.sa_data[2]++;
 
@@ -121,34 +123,53 @@ 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;
+       struct iwinfo_hardware_entry *rv = NULL;
+
+       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;
+               rv = &e;
+               break;
        }
 
-       return NULL;
+       fclose(db);
+       return rv;
 }
 
 int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
@@ -164,7 +185,7 @@ int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
 
        while (fgets(buf, sizeof(buf), mtd) > 0)
        {
-               if (fscanf(mtd, "mtd%d: %*x %x %127s", &off, &len, buf) < 3 ||
+               if (fscanf(mtd, "mtd%d: %x %*x %127s", &off, &len, buf) < 3 ||
                    (strcmp(buf, "\"boardconfig\"") && strcmp(buf, "\"EEPROM\"") &&
                     strcmp(buf, "\"factory\"")))
                {
@@ -345,3 +366,43 @@ void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
        data += 2 + (count * 4);
        len -= 2 + (count * 4);
 }
+
+struct uci_section *iwinfo_uci_get_radio(const char *name, const char *type)
+{
+       struct uci_ptr ptr = {
+               .package = "wireless",
+               .section = name,
+       };
+       const char *opt;
+
+       if (!uci_ctx) {
+               uci_ctx = uci_alloc_context();
+               if (!uci_ctx)
+                       return NULL;
+       }
+
+       memset(&ptr, 0, sizeof(ptr));
+       ptr.package = "wireless";
+       ptr.section = name;
+
+       if (uci_lookup_ptr(uci_ctx, &ptr, NULL, false))
+               return NULL;
+
+       if (!ptr.s || strcmp(ptr.s->type, "wifi-device") != 0)
+               return NULL;
+
+       opt = uci_lookup_option_string(uci_ctx, ptr.s, "type");
+       if (!opt || strcmp(opt, type) != 0)
+               return NULL;
+
+       return ptr.s;
+}
+
+void iwinfo_uci_free(void)
+{
+       if (!uci_ctx)
+               return;
+
+       uci_free_context(uci_ctx);
+       uci_ctx = NULL;
+}