wmbiff: fixed leaks.
[dockapps.git] / wmwlmon / wl.c
blob23d124e0be15ac4c9a3a83e44a842d0b309f5da1
1 /* $Id: wl.c,v 1.18 2008/05/13 04:42:17 hacki Exp $ */
3 /*
4 * Copyright (c) 2005, 2006 Marcus Glocker <marcus@nazgul.ch>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 /* Ported to FreeBSD by Nathan Lay <nslay@hotmail.com> 4/30/06 */
21 #include <sys/param.h>
22 #include <sys/ioctl.h>
23 #include <sys/socket.h>
25 #ifdef __OpenBSD__
26 #include <dev/ic/if_wi_ieee.h>
27 #endif
28 #ifdef __FreeBSD__
29 #include <dev/wi/if_wavelan_ieee.h>
30 #endif
31 #include <err.h>
32 #include <ifaddrs.h>
33 #include <net/if.h>
34 #include <net/if_media.h>
35 #include <net80211/ieee80211.h>
36 #include <net80211/ieee80211_ioctl.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <unistd.h>
41 #include "wl.h"
44 * global variables for this file
46 #ifdef __OpenBSD__
47 static char *speed[25] = {
48 "DS1", "1",
49 "DS2", "2",
50 "DS5", "5.5",
51 "DS11", "11",
52 "OFDM6", "6",
53 "OFDM9", "9",
54 "OFDM12", "12s",
55 "OFDM18", "18",
56 "OFDM24", "24",
57 "OFDM36", "36",
58 "OFDM48", "48",
59 "OFDM54", "54",
60 NULL
62 #endif
64 #ifdef __FreeBSD__
65 static char *speed[] = {
66 "FH/1Mbps", "1",
67 "FH/2Mbps", "2",
68 "DS/1Mbps", "1",
69 "DS/2Mbps", "2",
70 "DS/5.5Mbps", "5.5",
71 "DS/11Mbps", "11",
72 "DS/22Mbps", "22",
73 "OFDM/6Mbps", "6",
74 "OFDM/9Mbps", "9",
75 "OFDM/12Mbps", "12",
76 "OFDM/18Mbps", "18",
77 "OFDM/24Mbps", "24",
78 "OFDM/36Mbps", "36",
79 "OFDM/48Mbps", "48",
80 "OFDM/54Mbps", "54",
81 "OFDM/72Mbps", "72",
82 "DS/354Kbps", "0.354",
83 "DS/512Kbps", "0.512",
84 NULL
86 #endif
89 * get_wep()
90 * get wep status
91 * Return:
92 * 0 = wep disabled, 1 = wep enabled, -1 = error
94 int
95 get_wep(const char *interface)
97 int r = 0, s, inwkey;
98 #ifdef __OpenBSD__
99 struct ieee80211_nwkey nwkey;
100 #endif
101 #ifdef __FreeBSD__
102 struct ieee80211req nwkey;
103 #endif
105 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
106 return (-1);
108 memset(&nwkey, 0, sizeof(nwkey));
109 #ifdef __FreeBSD__
110 nwkey.i_type = IEEE80211_IOC_WEP;
111 #endif
112 strlcpy(nwkey.i_name, interface, sizeof(nwkey.i_name));
113 #ifdef __OpenBSD__
114 if ((inwkey = ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey)) == -1) {
115 close(s);
116 return (-1);
118 #endif
119 #ifdef __FreeBSD__
120 if ((inwkey = ioctl(s, SIOCG80211, (caddr_t)&nwkey)) == -1) {
121 close(s);
122 return (-1);
124 #endif
125 close(s);
127 #ifdef __OpenBSD__
128 if (inwkey == 0 && nwkey.i_wepon > 0)
129 r = 1;
130 #endif
131 #ifdef __FreeBSD__
132 if (inwkey == 0 && nwkey.i_val > 0)
133 r = 1;
134 #endif
136 return (r);
140 * get_channel()
141 * get channel number
142 * Return:
143 * <channel number> = success, 0 = no data, -1 = error
146 get_channel(const char *interface)
148 int s, ichan;
149 #ifdef __OpenBSD__
150 struct ieee80211chanreq channel;
151 #endif
152 #ifdef __FreeBSD__
153 struct ieee80211req channel;
154 #endif
156 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
157 return (-1);
159 memset(&channel, 0, sizeof(channel));
160 #ifdef __FreeBSD__
161 channel.i_type = IEEE80211_IOC_CHANNEL;
162 #endif
163 strlcpy(channel.i_name, interface, sizeof(channel.i_name));
164 #ifdef __OpenBSD__
165 if ((ichan = ioctl(s, SIOCG80211CHANNEL, (caddr_t)&channel)) == -1) {
166 close(s);
167 return (-1);
169 #endif
170 #ifdef __FreeBSD__
171 if ((ichan = ioctl(s, SIOCG80211, (caddr_t)&channel)) == -1) {
172 close(s);
173 return (-1);
175 #endif
176 close(s);
178 if (ichan == 0) {
179 #ifdef __OpenBSD__
180 if (channel.i_channel < 1000)
181 return (channel.i_channel);
182 #endif
183 #ifdef __FreeBSD__
184 if (channel.i_val < 1000)
185 return (channel.i_val);
186 #endif
189 return (0);
193 * get_signal()
194 * get signal strength
195 * Return:
196 * <signal strength> = success, 0 = no data, -1 = error
199 get_signal(const char *interface, const char *network)
202 #ifdef __OpenBSD__
203 int i = 0, s, len;
204 struct ieee80211_nodereq_all na;
205 struct ieee80211_nodereq nr[8];
206 #endif
207 #ifdef __FreeBSD__
208 int s, len;
209 uint8_t buf[24 * 1024], *cp;
210 struct ieee80211req na;
211 #endif
212 char network_id[IEEE80211_NWID_LEN + 1];
214 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
215 return (-1);
217 memset(&na, 0, sizeof(na));
218 #ifdef __OpenBSD__
219 memset(&nr, 0, sizeof(nr));
220 na.na_node = nr;
221 na.na_size = sizeof(nr);
222 strlcpy(na.na_ifname, interface, sizeof(na.na_ifname));
223 #endif
224 #ifdef __FreeBSD__
225 strlcpy(na.i_name, interface, sizeof(na.i_name));
226 na.i_type = IEEE80211_IOC_SCAN_RESULTS;
227 na.i_data = buf;
228 na.i_len = sizeof(buf);
229 #endif
230 #ifdef __OpenBSD__
231 if (ioctl(s, SIOCG80211ALLNODES, &na) == -1) {
232 close(s);
233 return (-1);
235 #endif
236 #ifdef __FreeBSD__
237 if (ioctl(s, SIOCG80211, (caddr_t)&na) == -1) {
238 close(s);
239 return (-1);
241 #endif
242 close(s);
244 #ifdef __OpenBSD__
245 for (i = 0; i < na.na_nodes; i++) {
246 if (nr[i].nr_nwid_len < sizeof(network_id))
247 len = nr[i].nr_nwid_len + 1;
248 else
249 len = sizeof(network_id);
250 strlcpy(network_id, (const char *)nr[i].nr_nwid, len);
251 if (!strcmp(network_id, network))
252 return (nr[i].nr_rssi);
254 #endif
255 #ifdef __FreeBSD__
256 /* This is how ifconfig does it */
257 len = na.i_len;
258 cp = buf;
259 do {
260 struct ieee80211req_scan_result *sr;
261 uint8_t *vp;
262 sr = (struct ieee80211req_scan_result *)cp;
263 vp = (u_int8_t *)(sr + 1);
264 strlcpy(network_id, (const char *)vp, sr->isr_ssid_len + 1);
265 if (!strcmp(network_id, network))
266 return (sr->isr_rssi);
267 cp += sr->isr_len;
268 len -= sr->isr_len;
269 if (sr->isr_len <= 0) /* Some weird lockup */
270 break;
271 } while (len >= sizeof(struct ieee80211req_scan_result));
272 #endif
274 return (0);
278 * get_wi_signal()
279 * get signal strength for wi interfaces
280 * Return:
281 * <signal strength> = success, -1 = error
284 get_wi_signal(const char *interface)
286 int s;
287 struct ifreq ifr;
288 struct wi_req wreq;
289 #ifdef __OpenBSD__
290 float link;
291 #endif
293 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
294 return (-1);
296 bzero((char *)&wreq, sizeof(wreq));
297 bzero((char *)&ifr, sizeof(ifr));
299 wreq.wi_len = WI_MAX_DATALEN;
300 wreq.wi_type = WI_RID_COMMS_QUALITY;
301 ifr.ifr_data = (caddr_t)&wreq;
302 strlcpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
304 if (ioctl(s, SIOCGWAVELAN, &ifr) == -1) {
305 close(s);
306 return (-1);
308 close(s);
310 #ifdef __OpenBSD__
311 link = wreq.wi_val[0];
313 * for future reference ...
314 * level = wreq.wi_val[1];
315 * noise = wreq.wi_val[2];
317 return (letoh16(link));
318 #endif
319 #ifdef __FreeBSD__
320 return (wreq.wi_val[1]);
321 #endif
325 * get_speed()
326 * get media speed
327 * Return:
328 * <pointer to speed> = success, NULL = no data / error
330 char *
331 get_speed(const char *interface)
333 int s, mword;
334 struct ifmediareq ifmr;
335 const struct ifmedia_description *desc;
336 #ifdef __OpenBSD__
337 const struct ifmedia_description ifm_subtype_descriptions[] =
338 IFM_SUBTYPE_DESCRIPTIONS;
339 #endif
340 #ifdef __FreeBSD__
341 const struct ifmedia_description ifm_subtype_descriptions[] =
342 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
343 #endif
345 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
346 return (NULL);
348 memset(&ifmr, 0, sizeof(ifmr));
349 strlcpy(ifmr.ifm_name, interface, sizeof(ifmr.ifm_name));
350 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
351 close(s);
352 return (NULL);
354 close(s);
356 mword = ifmr.ifm_active;
357 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL;
358 desc++) {
359 if (IFM_TYPE_MATCH(desc->ifmt_word, mword) &&
360 IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword))
361 return (translate_speed(desc->ifmt_string));
364 return (NULL);
368 * get_status()
369 * get network status
370 * Return:
371 * <pointer to status> = success, NULL = no data / error
373 char *
374 get_status(const char *interface)
376 #ifdef __OpenBSD__
377 int s, bitno;
378 static char status[64];
379 const struct ifmedia_status_description *ifms;
380 const struct ifmedia_status_description ifm_status_descriptions[] =
381 IFM_STATUS_DESCRIPTIONS;
382 const int ifm_status_valid_list[] =
383 IFM_STATUS_VALID_LIST;
384 #endif
385 #ifdef __FreeBSD__
386 int s;
387 #endif
388 struct ifmediareq ifmr;
390 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
391 return (NULL);
393 memset(&ifmr, 0, sizeof(ifmr));
394 strlcpy(ifmr.ifm_name, interface, sizeof(ifmr.ifm_name));
395 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
396 close(s);
397 return (NULL);
399 close(s);
401 #ifdef __OpenBSD__
402 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) {
403 for (ifms = ifm_status_descriptions; ifms->ifms_valid != 0;
404 ifms++) {
405 if (ifms->ifms_type != IFM_TYPE(ifmr.ifm_current) ||
406 ifms->ifms_valid != ifm_status_valid_list[bitno])
407 continue;
408 strlcpy(status, IFM_STATUS_DESC(ifms, ifmr.ifm_status),
409 sizeof(status));
410 return (status);
415 return (NULL);
416 #endif
417 #ifdef __FreeBSD__
418 if (ifmr.ifm_status & IFM_ACTIVE)
419 return ("active");
420 return ("no carrier");
421 #endif
425 * get_nwid()
426 * get wireless network id
427 * Return:
428 * pointer to network id = success, NULL = no data / error
430 char *
431 get_nwid(const char *interface)
433 int s, len, inwid;
434 static char network_id[IEEE80211_NWID_LEN + 1];
435 #ifdef __OpenBSD__
436 struct ifreq ifr;
437 struct ieee80211_nwid nwid;
438 #endif
439 #ifdef __FreeBSD__
440 struct ieee80211req nwid;
441 #endif
443 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
444 return (NULL);
446 #ifdef __OpenBSD__
447 memset(&ifr, 0, sizeof(ifr));
448 ifr.ifr_data = (caddr_t)&nwid;
449 strlcpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
450 #endif
451 #ifdef __FreeBSD__
452 memset(&nwid, 0, sizeof(nwid));
453 strlcpy(nwid.i_name, interface, sizeof(nwid.i_name));
454 nwid.i_type = IEEE80211_IOC_SSID;
455 nwid.i_data = network_id;
456 nwid.i_len = sizeof(network_id);
457 #endif
458 #ifdef __OpenBSD__
459 if ((inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr)) == -1) {
460 close(s);
461 return (NULL);
463 #endif
464 #ifdef __FreeBSD__
465 if ((inwid = ioctl(s, SIOCG80211, (caddr_t)&nwid)) == -1) {
466 close(s);
467 return (NULL);
469 #endif
470 close(s);
472 if (inwid == 0) {
473 if (nwid.i_len < sizeof(network_id))
474 len = nwid.i_len + 1;
475 else
476 len = sizeof(network_id);
477 #ifdef __OpenBSD__
478 strlcpy(network_id, (const char *)nwid.i_nwid, len);
479 #endif
480 #ifdef __FreeBSD__
481 network_id[len - 1] = '\0';
482 #endif
484 return (network_id);
487 return (NULL);
491 * get_first_wnic()
492 * scans interfaces and returns the first found wireless interface
493 * Return:
494 * <pointer to wnic> = success, NULL = no nic found
496 char *
497 get_first_wnic(void)
499 char *r = NULL;
500 char nic[IF_NAMESIZE];
501 struct ifaddrs *ifap = NULL, *ifa = NULL;
503 memset(nic, 0, sizeof(nic));
505 if (getifaddrs(&ifap) != 0)
506 errx(1, "getifaddrs");
508 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
509 if (strcmp(nic, ifa->ifa_name)) {
510 if (get_wep(ifa->ifa_name) != -1) {
511 r = strdup(ifa->ifa_name);
512 break;
515 strlcpy(nic, ifa->ifa_name, sizeof(nic));
518 freeifaddrs(ifap);
520 return (r);
524 * check_nic()
525 * check if the monitored interface still exists
526 * Return:
527 * 0 = interface gone, 1 = interface exists
530 check_nic(const char *interface)
532 int r = 0;
533 char nic[IF_NAMESIZE];
534 struct ifaddrs *ifap = NULL, *ifa = NULL;
536 memset(nic, 0, sizeof(nic));
538 if (getifaddrs(&ifap) != 0)
539 errx(1, "getifaddrs");
541 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
542 if (strcmp(nic, ifa->ifa_name)) {
543 if (!strcmp(ifa->ifa_name, interface)) {
544 r = 1;
545 break;
548 strlcpy(nic, ifa->ifa_name, sizeof(nic));
551 freeifaddrs(ifap);
553 return (r);
557 * translate_speed()
558 * translate the result of media speed to human readable string
559 * Return:
560 * <pointer to speed> = success, NULL = no data / error
562 char *
563 translate_speed(const char *mode)
565 int i;
567 for (i = 0; speed[i] != NULL; i++) {
568 if (!strcmp(mode, speed[i]))
569 return (speed[i + 1]);
572 return (NULL);