+/******************* WIRELESS INTERFACE DATABASE *******************/
+/*
+ * We keep a few information about each wireless interface on the
+ * system. This avoid to query this info at each event, therefore
+ * reducing overhead.
+ *
+ * Each interface is indexed by the 'ifindex'. As opposed to interface
+ * names, 'ifindex' are never reused (even if you reactivate the same
+ * hardware), so the data we cache will never apply to the wrong
+ * interface.
+ * Because of that, we are pretty lazy when it come to purging the
+ * cache...
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Get name of interface based on interface index...
+ */
+static inline int
+index2name(int skfd,
+ int ifindex,
+ char * name)
+{
+ struct ifreq irq;
+ int ret = 0;
+
+ memset(name, 0, IFNAMSIZ + 1);
+
+ /* Get interface name */
+ irq.ifr_ifindex = ifindex;
+ if(ioctl(skfd, SIOCGIFNAME, &irq) < 0)
+ ret = -1;
+ else
+ strncpy(name, irq.ifr_name, IFNAMSIZ);
+
+ return(ret);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Get interface data from cache or live interface
+ */
+static struct wireless_iface *
+iw_get_interface_data(int ifindex)
+{
+ struct wireless_iface * curr;
+ int skfd = -1; /* ioctl socket */
+
+ /* Search for it in the database */
+ curr = interface_cache;
+ while(curr != NULL)
+ {
+ /* Match ? */
+ if(curr->ifindex == ifindex)
+ {
+ //printf("Cache : found %d-%s\n", curr->ifindex, curr->ifname);
+
+ /* Return */
+ return(curr);
+ }
+ /* Next entry */
+ curr = curr->next;
+ }
+
+ /* Create a channel to the NET kernel. Doesn't happen too often, so
+ * socket creation overhead is minimal... */
+ if((skfd = iw_sockets_open()) < 0)
+ {
+ perror("iw_sockets_open");
+ return(NULL);
+ }
+
+ /* Create new entry, zero, init */
+ curr = calloc(1, sizeof(struct wireless_iface));
+ if(!curr)
+ {
+ fprintf(stderr, "Malloc failed\n");
+ return(NULL);
+ }
+ curr->ifindex = ifindex;
+
+ /* Extract static data */
+ if(index2name(skfd, ifindex, curr->ifname) < 0)
+ {
+ perror("index2name");
+ free(curr);
+ return(NULL);
+ }
+ curr->has_range = (iw_get_range_info(skfd, curr->ifname, &curr->range) >= 0);
+ //printf("Cache : create %d-%s\n", curr->ifindex, curr->ifname);
+
+ /* Done */
+ iw_sockets_close(skfd);
+
+ /* Link it */
+ curr->next = interface_cache;
+ interface_cache = curr;
+
+ return(curr);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Remove interface data from cache (if it exist)
+ */
+static void
+iw_del_interface_data(int ifindex)
+{
+ struct wireless_iface * curr;
+ struct wireless_iface * prev = NULL;
+ struct wireless_iface * next;
+
+ /* Go through the list, find the interface, kills it */
+ curr = interface_cache;
+ while(curr)
+ {
+ next = curr->next;
+
+ /* Got a match ? */
+ if(curr->ifindex == ifindex)
+ {
+ /* Unlink. Root ? */
+ if(!prev)
+ interface_cache = next;
+ else
+ prev->next = next;
+ //printf("Cache : purge %d-%s\n", curr->ifindex, curr->ifname);
+
+ /* Destroy */
+ free(curr);
+ }
+ else
+ {
+ /* Keep as previous */
+ prev = curr;
+ }
+
+ /* Next entry */
+ curr = next;
+ }
+}
+