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 = ⦥
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