+static void * iwinfo_open(void)
+{
+ return dlopen("/usr/lib/lua/iwinfo.so", RTLD_LAZY);
+}
+
+static int iwinfo_update(
+ void *iw, const char *ifname, uint16_t *rate, uint8_t *rssi, uint8_t *noise
+) {
+ int (*probe)(const char *);
+ int val;
+
+ if (!iw_get_rate)
+ {
+ if ((probe = dlsym(iw, "nl80211_probe")) != NULL && probe(ifname))
+ {
+ iw_get_rate = dlsym(iw, "nl80211_get_bitrate");
+ iw_get_rssi = dlsym(iw, "nl80211_get_signal");
+ iw_get_noise = dlsym(iw, "nl80211_get_noise");
+ }
+ else if ((probe = dlsym(iw, "madwifi_probe")) != NULL && probe(ifname))
+ {
+ iw_get_rate = dlsym(iw, "madwifi_get_bitrate");
+ iw_get_rssi = dlsym(iw, "madwifi_get_signal");
+ iw_get_noise = dlsym(iw, "madwifi_get_noise");
+ }
+ else if ((probe = dlsym(iw, "wl_probe")) != NULL && probe(ifname))
+ {
+ iw_get_rate = dlsym(iw, "wl_get_bitrate");
+ iw_get_rssi = dlsym(iw, "wl_get_signal");
+ iw_get_noise = dlsym(iw, "wl_get_noise");
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ *rate = (iw_get_rate && !iw_get_rate(ifname, &val)) ? val : 0;
+ *rssi = (iw_get_rssi && !iw_get_rssi(ifname, &val)) ? val : 0;
+ *noise = (iw_get_noise && !iw_get_noise(ifname, &val)) ? val : 0;
+
+ return 1;
+}
+
+static void iwinfo_close(void *iw)
+{
+ void (*do_close)(void);
+
+ if ((do_close = dlsym(iw, "nl80211_close")) != NULL) do_close();
+ if ((do_close = dlsym(iw, "madwifi_close")) != NULL) do_close();
+ if ((do_close = dlsym(iw, "wl_close")) != NULL) do_close();
+ if ((do_close = dlsym(iw, "wext_close")) != NULL) do_close();
+ if ((do_close = dlsym(iw, "iwinfo_close")) != NULL) do_close();
+
+ dlclose(iw);
+}
+