1
/* $Id: plugin_wireless.c 1136 2010-11-28 16:07:16Z mzuther $
2
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_wireless.c $
4
* Wireless Extension plugin
6
* Copyright (C) 2004 Xavier Vello <xavier66@free.fr>
7
* Copyright (C) 2004 Martin Hejl <martin@hejl.de>
8
* Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
10
* Losts of code borrowed from Wireless Tools, which is
11
* Copyright (C) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com>
12
* (avaible at http://web.hpl.hp.com/personal/Jean_Tourrilhes/Linux/)
14
* This file is part of LCD4Linux.
16
* LCD4Linux is free software; you can redistribute it and/or modify
17
* it under the terms of the GNU General Public License as published by
18
* the Free Software Foundation; either version 2, or (at your option)
21
* LCD4Linux is distributed in the hope that it will be useful,
22
* but WITHOUT ANY WARRANTY; without even the implied warranty of
23
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
* GNU General Public License for more details.
26
* You should have received a copy of the GNU General Public License
27
* along with this program; if not, write to the Free Software
28
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
46
All Functions take one parameter
47
(the name of the device, like "wlan0", "ath0" and so on)
60
#include <sys/ioctl.h>
61
#include <net/if_arp.h>
63
#include <linux/wireless.h>
83
#define KEY_LEVEL "level"
84
#define KEY_QUALITY "quality"
85
#define KEY_NOISE "noise"
86
#define KEY_PROTO "proto"
87
#define KEY_FREQUENCY "frequency"
88
#define KEY_BIT_RATE "bit_rate"
89
#define KEY_ESSID "essid"
90
#define KEY_OP_MODE "op_mode"
91
#define KEY_SENS "sens"
92
#define KEY_SEC_MODE "sec_mode"
94
#define FREQ2FLOAT(m,e) (((double) m) * pow(10,e))
95
#define MWATT2DBM(in) ((int) (ceil(10.0 * log10((double) in))))
101
static char *operation_mode[] = {
113
static void ioctl_error(const int line)
115
error("IOCTL call to wireless extensions in line %d returned error", line);
118
int do_ioctl(const int sock, /* Socket to the kernel */
119
const char *ifname, /* Device name */
120
const int request, /* WE ID */
122
{ /* Fixed part of the request */
125
/* Set device name */
126
strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
129
ret = ioctl(sock, request, pwrq);
131
debug("ioctl(0x%04x) failed: %d '%s'", request, errno, strerror(errno));
138
int get_range_info(const int sock, const char *ifname, struct iw_range *range)
141
char buffer[sizeof(struct iw_range) * 2]; /* Large enough */
148
memset(buffer, 0, sizeof(buffer));
150
req.u.data.pointer = (caddr_t) buffer;
151
req.u.data.length = sizeof(buffer);
152
req.u.data.flags = 0;
153
if (do_ioctl(sock, ifname, SIOCGIWRANGE, &req) < 0)
156
/* Copy stuff at the right place, ignore extra */
157
memcpy((char *) range, buffer, sizeof(struct iw_range));
164
static int get_ifname(struct iwreq *preq, const char *dev)
166
/* do not cache this call !!! */
174
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_PROTO);
179
if (do_ioctl(sock, dev, SIOCGIWNAME, preq)) {
180
debug("%s isn't a wirelesss interface !", dev);
184
hash_put(&wireless, key_buffer, preq->u.name);
189
static int get_frequency(const char *dev, const char *key)
191
/* Get frequency / channel */
193
char qprintf_buffer[1024];
198
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
199
age = hash_age(&wireless, key);
201
/* reread every HASH_TTL msec only */
202
if (age > 0 && age <= HASH_TTL) {
206
if (get_ifname(&req, dev) != 0) {
210
req.u.data.length = 0;
211
req.u.data.flags = 1; /* Clear updated flag */
213
if (do_ioctl(sock, dev, SIOCGIWFREQ, &req) < 0) {
214
ioctl_error(__LINE__);
218
freq = FREQ2FLOAT(req.u.freq.m, req.u.freq.e);
221
snprintf(qprintf_buffer,sizeof(qprintf_buffer), "%g GHz", freq / GIGA);
224
snprintf(qprintf_buffer,sizeof(qprintf_buffer), "%g MHz", freq / MEGA);
226
snprintf(qprintf_buffer,sizeof(qprintf_buffer), "%g kHz", freq / KILO);
228
snprintf(qprintf_buffer, sizeof(qprintf_buffer), "%g", freq);
230
hash_put(&wireless, key_buffer, qprintf_buffer);
235
static int get_essid(const char *dev, const char *key)
240
char essid_buffer[IW_ESSID_MAX_SIZE + 1];
244
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
245
age = hash_age(&wireless, key);
247
/* reread every HASH_TTL msec only */
248
if (age > 0 && age <= HASH_TTL) {
252
if (get_ifname(&req, dev) != 0) {
256
memset(essid_buffer, 0, sizeof(essid_buffer));
257
req.u.essid.pointer = (caddr_t) essid_buffer;
258
req.u.essid.length = IW_ESSID_MAX_SIZE + 1;
259
req.u.essid.flags = 0;
261
if (do_ioctl(sock, dev, SIOCGIWESSID, &req) < 0) {
262
ioctl_error(__LINE__);
266
hash_put(&wireless, key_buffer, essid_buffer);
271
static int get_op_mode(const char *dev, const char *key)
273
/* Get operation mode */
278
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
279
age = hash_age(&wireless, key);
281
/* reread every HASH_TTL msec only */
282
if (age > 0 && age <= HASH_TTL) {
286
if (get_ifname(&req, dev) != 0) {
290
if (do_ioctl(sock, dev, SIOCGIWMODE, &req) < 0) {
291
ioctl_error(__LINE__);
295
/* Fixme: req.u.mode is unsigned and therefore never < 0 */
296
/* if((req.u.mode > 6) || (req.u.mode < 0)) { */
298
if (req.u.mode > 6) {
299
req.u.mode = 7; /* mode not available */
302
hash_put(&wireless, key_buffer, operation_mode[req.u.mode]);
307
static int get_bitrate(const char *dev, const char *key)
312
char bitrate_buffer[64];
316
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
317
age = hash_age(&wireless, key);
319
/* reread every HASH_TTL msec only */
320
if (age > 0 && age <= HASH_TTL) {
324
if (get_ifname(&req, dev) != 0) {
328
if (do_ioctl(sock, dev, SIOCGIWRATE, &req) < 0) {
329
ioctl_error(__LINE__);
333
bitrate_buffer[0] = '\0';
334
bitrate = (double) (req.u.bitrate.value);
335
/* if( bitrate>= GIGA)
336
snprintf(bitrate_buffer,sizeof(bitrate_buffer), "%gGb/s", bitrate / GIGA);
339
snprintf(bitrate_buffer,sizeof(bitrate_buffer), "%gMb/s", bitrate / MEGA);
341
snprintf(bitrate_buffer,sizeof(bitrate_buffer), "%gkb/s", bitrate / KILO);
343
snprintf(bitrate_buffer, sizeof(bitrate_buffer), "%g", bitrate);
345
hash_put(&wireless, key_buffer, bitrate_buffer);
350
static int get_sens(const char *dev, const char *key)
352
/* Get sensitivity */
354
struct iw_range range;
361
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
362
age = hash_age(&wireless, key);
364
/* reread every HASH_TTL msec only */
365
if (age > 0 && age <= HASH_TTL) {
369
if (get_ifname(&req, dev) != 0) {
373
if (do_ioctl(sock, dev, SIOCGIWSENS, &req) >= 0) {
377
if (get_range_info(sock, dev, &range) < 0) {
378
memset(&range, 0, sizeof(range));
384
if (req.u.sens.value < 0) {
385
qprintf(buffer, sizeof(buffer), "%d dBm", req.u.sens.value);
387
qprintf(buffer, sizeof(buffer), "%d/%d", req.u.sens.value, range.sensitivity);
390
qprintf(buffer, sizeof(buffer), "%d", req.u.sens.value);
393
hash_put(&wireless, key_buffer, buffer);
398
static int get_sec_mode(const char *dev, const char *key)
400
/* Get encryption information */
403
char encrypt_key[IW_ENCODING_TOKEN_MAX + 1];
409
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
410
age = hash_age(&wireless, key);
412
/* reread every HASH_TTL msec only */
413
if (age > 0 && age <= HASH_TTL) {
417
if (get_ifname(&req, dev) != 0) {
421
req.u.data.pointer = (caddr_t) & encrypt_key;
422
req.u.data.length = IW_ENCODING_TOKEN_MAX;
423
req.u.data.flags = 0;
425
if (do_ioctl(sock, dev, SIOCGIWENCODE, &req) >= 0) {
427
key_flags = req.u.data.flags;
428
key_size = req.u.data.length;
433
/* Display encryption information */
434
/*if(has_key && (key_flags & IW_ENCODE_INDEX) > 1) */
435
/* printf(" [%d]", info->key_flags & IW_ENCODE_INDEX); */
437
if (has_key && (key_flags & IW_ENCODE_RESTRICTED))
438
hash_put(&wireless, key_buffer, "restricted");
439
else if (has_key && (key_flags & IW_ENCODE_OPEN))
440
hash_put(&wireless, key_buffer, "open");
445
static int get_stats(const char *dev, const char *key)
447
struct iw_statistics stats;
449
char qprintf_buffer[1024];
452
struct iw_range range;
454
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
455
age = hash_age(&wireless, key);
457
/* reread every HASH_TTL msec only */
458
if (age > 0 && age <= HASH_TTL) {
462
if (get_ifname(&req, dev) != 0) {
466
req.u.data.pointer = (caddr_t) & stats;
467
req.u.data.length = sizeof(stats);
468
req.u.data.flags = 1; /* Clear updated flag */
470
if (do_ioctl(sock, dev, SIOCGIWSTATS, &req) < 0) {
471
ioctl_error(__LINE__);
475
if (get_range_info(sock, dev, &range) < 0)
476
memset(&range, 0, sizeof(range));
478
if (stats.qual.level > range.max_qual.level) {
479
qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d", stats.qual.level - 0x100);
480
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_LEVEL);
481
hash_put(&wireless, key_buffer, qprintf_buffer);
483
qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d", stats.qual.noise - 0x100);
484
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_NOISE);
485
hash_put(&wireless, key_buffer, qprintf_buffer);
487
qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.qual, range.max_qual.qual);
488
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_QUALITY);
489
hash_put(&wireless, key_buffer, qprintf_buffer);
492
qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.level, range.max_qual.level);
493
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_LEVEL);
494
hash_put(&wireless, key_buffer, qprintf_buffer);
496
qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.noise, range.max_qual.noise);
497
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_NOISE);
498
hash_put(&wireless, key_buffer, qprintf_buffer);
500
qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.qual, range.max_qual.qual);
501
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_QUALITY);
502
hash_put(&wireless, key_buffer, qprintf_buffer);
508
static int check_socket()
511
/* already handled in a previous run */
515
/* socket not initialized */
517
sock = socket(AF_INET, SOCK_DGRAM, 0);
519
/* error initilalizing socket */
521
error("Error opening socket for reading wireless stats");
530
static void save_result(RESULT * result, const char *dev, const char *key, const int res)
534
qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key);
537
SetResult(&result, R_STRING, "");
541
val = hash_get(&wireless, key_buffer, NULL);
544
SetResult(&result, R_STRING, val);
546
SetResult(&result, R_STRING, "");
553
*functions exported to the evaluator
556
static void wireless_quality(RESULT * result, RESULT * arg1)
558
char *dev = R2S(arg1);
559
if (check_socket() != 0)
562
save_result(result, dev, KEY_QUALITY, get_stats(dev, KEY_QUALITY));
565
static void wireless_level(RESULT * result, RESULT * arg1)
567
char *dev = R2S(arg1);
568
if (check_socket() != 0)
571
save_result(result, dev, KEY_LEVEL, get_stats(dev, KEY_LEVEL));
575
static void wireless_noise(RESULT * result, RESULT * arg1)
577
char *dev = R2S(arg1);
578
if (check_socket() != 0)
581
save_result(result, dev, KEY_NOISE, get_stats(dev, KEY_NOISE));
585
static void wireless_protocol(RESULT * result, RESULT * arg1)
587
char *dev = R2S(arg1);
588
if (check_socket() != 0)
591
save_result(result, dev, KEY_PROTO, get_ifname(NULL, dev));
594
static void wireless_frequency(RESULT * result, RESULT * arg1)
596
char *dev = R2S(arg1);
597
if (check_socket() != 0)
600
save_result(result, dev, KEY_FREQUENCY, get_frequency(dev, KEY_FREQUENCY));
603
static void wireless_bitrate(RESULT * result, RESULT * arg1)
605
char *dev = R2S(arg1);
606
if (check_socket() != 0)
609
save_result(result, dev, KEY_BIT_RATE, get_bitrate(dev, KEY_BIT_RATE));
612
static void wireless_essid(RESULT * result, RESULT * arg1)
614
char *dev = R2S(arg1);
615
if (check_socket() != 0)
618
save_result(result, dev, KEY_ESSID, get_essid(dev, KEY_ESSID));
621
static void wireless_op_mode(RESULT * result, RESULT * arg1)
623
char *dev = R2S(arg1);
624
if (check_socket() != 0)
627
save_result(result, dev, KEY_OP_MODE, get_op_mode(dev, KEY_OP_MODE));
630
static void wireless_sensitivity(RESULT * result, RESULT * arg1)
632
char *dev = R2S(arg1);
633
if (check_socket() != 0)
636
save_result(result, dev, KEY_SENS, get_sens(dev, KEY_SENS));
639
static void wireless_sec_mode(RESULT * result, RESULT * arg1)
641
char *dev = R2S(arg1);
642
if (check_socket() != 0)
645
save_result(result, dev, KEY_SEC_MODE, get_sec_mode(dev, KEY_SEC_MODE));
652
int plugin_init_wireless(void)
654
hash_create(&wireless);
656
AddFunction("wifi::level", 1, wireless_level);
657
AddFunction("wifi::noise", 1, wireless_noise);
658
AddFunction("wifi::quality", 1, wireless_quality);
659
AddFunction("wifi::protocol", 1, wireless_protocol);
660
AddFunction("wifi::frequency", 1, wireless_frequency);
661
AddFunction("wifi::bitrate", 1, wireless_bitrate);
662
AddFunction("wifi::essid", 1, wireless_essid);
663
AddFunction("wifi::op_mode", 1, wireless_op_mode);
664
AddFunction("wifi::sensitivity", 1, wireless_sensitivity);
665
AddFunction("wifi::sec_mode", 1, wireless_sec_mode);
670
void plugin_exit_wireless(void)
674
hash_destroy(&wireless);