twifi.c - spoon - [fork] customized build of spoon, the dwm status utility
 (HTM) git clone git://src.adamsgaard.dk/spoon
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
       twifi.c (4302B)
       ---
            1 #include <sys/ioctl.h>
            2 
            3 #include <err.h>
            4 #include <ifaddrs.h>
            5 #include <stdio.h>
            6 #include <string.h>
            7 #include <unistd.h>
            8 
            9 #include "util.h"
           10 
           11 void
           12 wifiprint(char *buf, size_t len, int quality, u_int8_t *ssid)
           13 {
           14         char *icon;
           15 
           16         if (quality == 100)
           17                 icon = ":D";
           18         else if (quality >= 75)
           19                 icon = ":)";
           20         else if (quality >= 50)
           21                 icon = ":|";
           22         else if (quality >= 25)
           23                 icon = ":(";
           24         else
           25                 icon = ":o";
           26         snprintf(buf, len, "%s %s", ssid, icon);
           27 }
           28 
           29 #ifdef __OpenBSD__
           30 #include <sys/types.h>
           31 #include <sys/socket.h>
           32 #include <sys/select.h>
           33 
           34 #include <net/if.h>
           35 #include <net/if_media.h>
           36 #include <net80211/ieee80211.h>
           37 #include <net80211/ieee80211_ioctl.h>
           38 
           39 int
           40 wifiread(void *arg, char *buf, size_t len)
           41 {
           42         struct ifaddrs *ifa, *ifas;
           43         struct ifmediareq ifmr;
           44         struct ieee80211_nodereq nr;
           45         struct ieee80211_bssid bssid;
           46         int quality = -1;
           47         int fd, ibssid;
           48 
           49         if (getifaddrs(&ifas) < 0) {
           50                 warn("getifaddrs");
           51                 return -1;
           52         }
           53         fd = socket(AF_INET, SOCK_DGRAM, 0);
           54         if (fd < 0) {
           55                 warn("socket");
           56                 return -1;
           57         }
           58         for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
           59                 memset(&ifmr, 0, sizeof(ifmr));
           60                 strlcpy(ifmr.ifm_name, ifa->ifa_name, IF_NAMESIZE);
           61                 if (ioctl(fd, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
           62                         continue;
           63                 if ((ifmr.ifm_active & IFM_IEEE80211) == 0)
           64                         continue;
           65                 if ((ifmr.ifm_active & IFM_IEEE80211_HOSTAP) != 0)
           66                         continue;
           67                 memset(&bssid, 0, sizeof(bssid));
           68                 strlcpy(bssid.i_name, ifa->ifa_name, sizeof(bssid.i_name));
           69                 ibssid = ioctl(fd, SIOCG80211BSSID, &bssid);
           70                 if (ibssid < 0)
           71                         continue;
           72                 memset(&nr, 0, sizeof(nr));
           73                 memcpy(&nr.nr_macaddr, bssid.i_bssid, sizeof(nr.nr_macaddr));
           74                 strlcpy(nr.nr_ifname, ifa->ifa_name, sizeof(nr.nr_ifname));
           75                 if (ioctl(fd, SIOCG80211NODE, &nr) < 0)
           76                         continue;
           77                 if (nr.nr_rssi == 0)
           78                         continue;
           79                 if (nr.nr_max_rssi == 0) {
           80                         if (nr.nr_rssi <= -100)
           81                                 quality = 0;
           82                         else if (nr.nr_rssi >= -50)
           83                                 quality = 100;
           84                         else
           85                                 quality = 2 * (nr.nr_rssi + 100);
           86                 } else {
           87                         quality = IEEE80211_NODEREQ_RSSI(&nr);
           88                 }
           89                 break;
           90         }
           91         close(fd);
           92         freeifaddrs(ifas);
           93 
           94         DPRINTF_D(quality);
           95         if (quality == -1)
           96                 return -1;
           97         wifiprint(buf, len, quality, nr.nr_nwid);
           98         return 0;
           99 }
          100 #elif __linux__
          101 #include <sys/types.h>
          102 #include <sys/socket.h>
          103 
          104 #include <linux/wireless.h>
          105 
          106 int
          107 wifiread(void *arg, char *buf, size_t len)
          108 {
          109         struct ifaddrs *ifa, *ifas;
          110         struct iw_quality *max_qual, *qual;
          111         struct iw_statistics stats;
          112         struct iw_range range;
          113         struct iwreq wrq;
          114         int quality = -1;
          115         int level;
          116         int ret, fd;
          117 
          118         if (getifaddrs(&ifas) < 0) {
          119                 warn("getifaddrs");
          120                 return -1;
          121         }
          122         fd = socket(PF_INET, SOCK_DGRAM, 0);
          123         if (fd == -1) {
          124                 warn("socket");
          125                 return -1;
          126         }
          127         for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
          128                 DPRINTF_S(ifa->ifa_name);
          129                 memset(&wrq, 0, sizeof(wrq));
          130                 strlcpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ);
          131                 ret = ioctl(fd, SIOCGIWNAME, &wrq);
          132                 if (ret != 0)
          133                         continue;
          134                 memset(&wrq, 0, sizeof(wrq));
          135                 strlcpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ);
          136                 wrq.u.data.pointer = &range;
          137                 wrq.u.data.length = sizeof(range);
          138                 memset(&range, 0, sizeof(range));
          139                 ret = ioctl(fd, SIOCGIWRANGE, &wrq);
          140                 if (ret < 0) {
          141                         warnx("cannot get wifi range");
          142                         continue;
          143                 }
          144                 memset(&wrq, 0, sizeof(wrq));
          145                 strlcpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ);
          146                 wrq.u.data.pointer = &stats;
          147                 wrq.u.data.length = sizeof(stats);
          148                 wrq.u.data.flags = 1;
          149                 memset(&stats, 0, sizeof(stats));
          150                 ret = ioctl(fd, SIOCGIWSTATS, &wrq);
          151                 if (ret < 0) {
          152                         warnx("cannot get wifi stats");
          153                         continue;
          154                 }
          155                 max_qual = &range.max_qual;
          156                 qual = &stats.qual;
          157                 DPRINTF_U(max_qual->qual);
          158                 DPRINTF_U(max_qual->level);
          159                 DPRINTF_U(qual->qual);
          160                 DPRINTF_U(qual->level);
          161                 if (max_qual->qual != 0) {
          162                         /* driver provides a quality metric */
          163                         quality = (((float)qual->qual / max_qual->qual) * 100);
          164                 } else if (max_qual->level != 0) {
          165                         /* driver provides signal strength (RSSI) */
          166                         quality = (((float)qual->level / max_qual->level) * 100);
          167                 } else if (max_qual->level == 0) {
          168                         /* driver provides absolute dBm values */
          169                         level = qual->level - 0x100;
          170                         if (level <= -100)
          171                                 quality = 0;
          172                         else if (level >= -50)
          173                                 quality = 100;
          174                         else
          175                                 quality = 2 * (level + 100);
          176                 }
          177                 break;
          178         }
          179         close(fd);
          180         freeifaddrs(ifas);
          181 
          182         DPRINTF_D(quality);
          183         if (quality == -1)
          184                 return -1;
          185         wifiprint(buf, len, quality, "wlan");
          186         return 0;
          187 }
          188 #endif