wifi.c - slstatus - status monitor
git clone git://git.suckless.org/slstatus
Log
Files
Refs
README
LICENSE
---
wifi.c (5951B)
---
     1 /* See LICENSE file for copyright and license details. */
     2 #include 
     3 #include 
     4 #include 
     5 #include 
     6 #include 
     7 #include 
     8 
     9 #include "../slstatus.h"
    10 #include "../util.h"
    11 
    12 #define RSSI_TO_PERC(rssi) \
    13                         rssi >= -50 ? 100 : \
    14                         (rssi <= -100 ? 0 : \
    15                         (2 * (rssi + 100)))
    16 
    17 #if defined(__linux__)
    18         #include 
    19         #include 
    20 
    21         #define NET_OPERSTATE "/sys/class/net/%s/operstate"
    22 
    23         const char *
    24         wifi_perc(const char *interface)
    25         {
    26                 int cur;
    27                 size_t i;
    28                 char *p, *datastart;
    29                 char path[PATH_MAX];
    30                 char status[5];
    31                 FILE *fp;
    32 
    33                 if (esnprintf(path, sizeof(path), NET_OPERSTATE, interface) < 0)
    34                         return NULL;
    35                 if (!(fp = fopen(path, "r"))) {
    36                         warn("fopen '%s':", path);
    37                         return NULL;
    38                 }
    39                 p = fgets(status, 5, fp);
    40                 fclose(fp);
    41                 if (!p || strcmp(status, "up\n") != 0)
    42                         return NULL;
    43 
    44                 if (!(fp = fopen("/proc/net/wireless", "r"))) {
    45                         warn("fopen '/proc/net/wireless':");
    46                         return NULL;
    47                 }
    48 
    49                 for (i = 0; i < 3; i++)
    50                         if (!(p = fgets(buf, sizeof(buf) - 1, fp)))
    51                                 break;
    52 
    53                 fclose(fp);
    54                 if (i < 2 || !p)
    55                         return NULL;
    56 
    57                 if (!(datastart = strstr(buf, interface)))
    58                         return NULL;
    59 
    60                 datastart = (datastart+(strlen(interface)+1));
    61                 sscanf(datastart + 1, " %*d   %d  %*d  %*d\t\t  %*d\t   "
    62                        "%*d\t\t%*d\t\t %*d\t  %*d\t\t %*d", &cur);
    63 
    64                 /* 70 is the max of /proc/net/wireless */
    65                 return bprintf("%d", (int)((float)cur / 70 * 100));
    66         }
    67 
    68         const char *
    69         wifi_essid(const char *interface)
    70         {
    71                 static char id[IW_ESSID_MAX_SIZE+1];
    72                 int sockfd;
    73                 struct iwreq wreq;
    74 
    75                 memset(&wreq, 0, sizeof(struct iwreq));
    76                 wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
    77                 if (esnprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s",
    78                               interface) < 0)
    79                         return NULL;
    80 
    81                 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    82                         warn("socket 'AF_INET':");
    83                         return NULL;
    84                 }
    85                 wreq.u.essid.pointer = id;
    86                 if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) {
    87                         warn("ioctl 'SIOCGIWESSID':");
    88                         close(sockfd);
    89                         return NULL;
    90                 }
    91 
    92                 close(sockfd);
    93 
    94                 if (!strcmp(id, ""))
    95                         return NULL;
    96 
    97                 return id;
    98         }
    99 #elif defined(__OpenBSD__)
   100         #include 
   101         #include 
   102         #include 
   103         #include  /* before  for NBBY */
   104         #include 
   105         #include 
   106         #include 
   107 
   108         static int
   109         load_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr)
   110         {
   111                 struct ieee80211_bssid bssid;
   112                 int sockfd;
   113                 uint8_t zero_bssid[IEEE80211_ADDR_LEN];
   114 
   115                 memset(&bssid, 0, sizeof(bssid));
   116                 memset(nr, 0, sizeof(struct ieee80211_nodereq));
   117                 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
   118                         warn("socket 'AF_INET':");
   119                         return 0;
   120                 }
   121                 strlcpy(bssid.i_name, interface, sizeof(bssid.i_name));
   122                 if ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) {
   123                         warn("ioctl 'SIOCG80211BSSID':");
   124                         close(sockfd);
   125                         return 0;
   126                 }
   127                 memset(&zero_bssid, 0, sizeof(zero_bssid));
   128                 if (memcmp(bssid.i_bssid, zero_bssid,
   129                     IEEE80211_ADDR_LEN) == 0) {
   130                         close(sockfd);
   131                         return 0;
   132                 }
   133                 strlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname));
   134                 memcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr));
   135                 if ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) {
   136                         warn("ioctl 'SIOCG80211NODE':");
   137                         close(sockfd);
   138                         return 0;
   139                 }
   140 
   141                 return close(sockfd), 1;
   142         }
   143 
   144         const char *
   145         wifi_perc(const char *interface)
   146         {
   147                 struct ieee80211_nodereq nr;
   148                 int q;
   149 
   150                 if (load_ieee80211_nodereq(interface, &nr)) {
   151                         if (nr.nr_max_rssi)
   152                                 q = IEEE80211_NODEREQ_RSSI(&nr);
   153                         else
   154                                 q = RSSI_TO_PERC(nr.nr_rssi);
   155 
   156                         return bprintf("%d", q);
   157                 }
   158 
   159                 return NULL;
   160         }
   161 
   162         const char *
   163         wifi_essid(const char *interface)
   164         {
   165                 struct ieee80211_nodereq nr;
   166 
   167                 if (load_ieee80211_nodereq(interface, &nr))
   168                         return bprintf("%s", nr.nr_nwid);
   169 
   170                 return NULL;
   171         }
   172 #elif defined(__FreeBSD__)
   173         #include 
   174         #include 
   175 
   176         int
   177         load_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len)
   178         {
   179                 char warn_buf[256];
   180                 struct ieee80211req ireq;
   181                 memset(&ireq, 0, sizeof(ireq));
   182                 ireq.i_type = type;
   183                 ireq.i_data = (caddr_t) data;
   184                 ireq.i_len = *len;
   185 
   186                 strlcpy(ireq.i_name, interface, sizeof(ireq.i_name));
   187                 if (ioctl(sock, SIOCG80211, &ireq) < 0) {
   188                         snprintf(warn_buf,  sizeof(warn_buf),
   189                                         "ioctl: 'SIOCG80211': %d", type);
   190                         warn(warn_buf);
   191                         return 0;
   192                 }
   193 
   194                 *len = ireq.i_len;
   195                 return 1;
   196         }
   197 
   198         const char *
   199         wifi_perc(const char *interface)
   200         {
   201                 union {
   202                         struct ieee80211req_sta_req sta;
   203                         uint8_t buf[24 * 1024];
   204                 } info;
   205                 uint8_t bssid[IEEE80211_ADDR_LEN];
   206                 int rssi_dbm;
   207                 int sockfd;
   208                 size_t len;
   209                 const char *fmt;
   210 
   211                 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
   212                         warn("socket 'AF_INET':");
   213                         return NULL;
   214                 }
   215 
   216                 /* Retreive MAC address of interface */
   217                 len = IEEE80211_ADDR_LEN;
   218                 fmt = NULL;
   219                 if (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len))
   220                 {
   221                         /* Retrieve info on station with above BSSID */
   222                         memset(&info, 0, sizeof(info));
   223                         memcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid));
   224 
   225                         len = sizeof(info);
   226                         if (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) {
   227                                 rssi_dbm = info.sta.info[0].isi_noise +
   228                                                   info.sta.info[0].isi_rssi / 2;
   229 
   230                                 fmt = bprintf("%d", RSSI_TO_PERC(rssi_dbm));
   231                         }
   232                 }
   233 
   234                 close(sockfd);
   235                 return fmt;
   236         }
   237 
   238         const char *
   239         wifi_essid(const char *interface)
   240         {
   241                 char ssid[IEEE80211_NWID_LEN + 1];
   242                 size_t len;
   243                 int sockfd;
   244                 const char *fmt;
   245 
   246                 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
   247                         warn("socket 'AF_INET':");
   248                         return NULL;
   249                 }
   250 
   251                 fmt = NULL;
   252                 len = sizeof(ssid);
   253                 memset(&ssid, 0, len);
   254                 if (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) {
   255                         if (len < sizeof(ssid))
   256                                 len += 1;
   257                         else
   258                                 len = sizeof(ssid);
   259 
   260                         ssid[len - 1] = '\0';
   261                         fmt = bprintf("%s", ssid);
   262                 }
   263 
   264                 close(sockfd);
   265                 return fmt;
   266         }
   267 #endif