/* $Id: plugin_wireless.c,v 1.9 2005/05/08 04:32:45 reinelt Exp $ * * Wireless Extension plugin * * Copyright (C) 2004 Xavier Vello * Copyright (C) 2004 Martin Hejl * Copyright (C) 2004 The LCD4Linux Team * * Losts of code borrowed from Wireless Tools, which is * Copyright (C) 1997-2002 Jean Tourrilhes * (avaible at http://web.hpl.hp.com/personal/Jean_Tourrilhes/Linux/) * * This file is part of LCD4Linux. * * LCD4Linux is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * LCD4Linux is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * $Log: plugin_wireless.c,v $ * Revision 1.9 2005/05/08 04:32:45 reinelt * CodingStyle added and applied * * Revision 1.8 2005/01/18 06:30:23 reinelt * added (C) to all copyright statements * * Revision 1.7 2004/06/26 12:05:00 reinelt * * uh-oh... the last CVS log message messed up things a lot... * * Revision 1.6 2004/06/26 09:27:21 reinelt * * added '-W' to CFLAGS * changed all C++ comments to C ones * cleaned up a lot of signed/unsigned mistakes * * Revision 1.5 2004/06/20 10:09:56 reinelt * * 'const'ified the whole source * * Revision 1.4 2004/06/17 06:23:43 reinelt * * hash handling rewritten to solve performance issues * * Revision 1.3 2004/05/27 03:39:47 reinelt * * changed function naming scheme to plugin::function * * Revision 1.2 2004/04/17 13:05:58 nicowallmeier * minor bugfix * * Revision 1.1 2004/04/07 08:29:05 hejl * New plugin for wireless info * */ /* * Exported functions: wifi_level wifi_noise wifi_quality wifi_protocol wifi_frequency wifi_bitrate wifi_essid wifi_op_mode wifi_sensitivity wifi_sec_mode All Functions take one parameter (the name of the device, like "wlan0", "ath0" and so on) */ #include "config.h" #include #include #include #include #include #include #include #include #include "debug.h" #include "plugin.h" #include "cfg.h" #include "hash.h" #include "qprintf.h" #ifdef WITH_DMALLOC #include #endif #define HASH_TTL 100 /*#define KILO 1e3 */ /*#define MEGA 1e6 */ /*#define GIGA 1e9 */ #define KEY_LEVEL "level" #define KEY_QUALITY "quality" #define KEY_NOISE "noise" #define KEY_PROTO "proto" #define KEY_FREQUENCY "frequency" #define KEY_BIT_RATE "bit_rate" #define KEY_ESSID "essid" #define KEY_OP_MODE "op_mode" #define KEY_SENS "sens" #define KEY_SEC_MODE "sec_mode" #define FREQ2FLOAT(m,e) (((double) m) * pow(10,e)) #define MWATT2DBM(in) ((int) (ceil(10.0 * log10((double) in)))) static HASH wireless; static int sock = -2; static char *operation_mode[] = { "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor", "n/a" }; static void ioctl_error(const int line) { error("IOCTL call to wireless extensions in line %d returned error", line); } int do_ioctl(const int sock, /* Socket to the kernel */ const char *ifname, /* Device name */ const int request, /* WE ID */ struct iwreq *pwrq) { /* Fixed part of the request */ /* Set device name */ strncpy(pwrq->ifr_name, ifname, IFNAMSIZ); /* Do the request */ return (ioctl(sock, request, pwrq)); } int get_range_info(const int sock, const char *ifname, struct iw_range *range) { struct iwreq req; char buffer[sizeof(struct iw_range) * 2]; /* Large enough */ if (sock <= 0) { return (-1); } /* Cleanup */ memset(buffer, 0, sizeof(buffer)); req.u.data.pointer = (caddr_t) buffer; req.u.data.length = sizeof(buffer); req.u.data.flags = 0; if (do_ioctl(sock, ifname, SIOCGIWRANGE, &req) < 0) return (-1); /* Copy stuff at the right place, ignore extra */ memcpy((char *) range, buffer, sizeof(struct iw_range)); return (0); } static int get_ifname(struct iwreq *preq, const char *dev) {
# Intelsat 1002 @ 1.0W
# freq pol sr fec
S 4175000 V 28000000 AUTO
S 4180000 H 21050000 AUTO
S 11093000 H 19191000 7/8
S 11166000 V 1450000 7/8
S 11182000 V 3100000 7/8
S 11606000 H 13356000 7/8
S 12527000 H 27500000 3/4
S 12563000 H 27500000 3/4
S 12563000 V 27500000 3/4
S 12607000 H 27500000 3/4
S 12607000 V 27500000 3/4
S 12643000 H 27500000 3/4
S 12643000 V 27500000 3/4
S 12687000 H 27500000 3/4
S 12687000 V 27500000 3/4
S 12718000 V 18400000 3/4
S 12723000 H 27500000 3/4
S 12735000 V 8800000 5/6
eq.u.data.flags; key_size = req.u.data.length; } else { return (-1); } /* Display encryption information */ /*if(has_key && (key_flags & IW_ENCODE_INDEX) > 1) */ /* printf(" [%d]", info->key_flags & IW_ENCODE_INDEX); */ if (has_key && (key_flags & IW_ENCODE_RESTRICTED)) hash_put(&wireless, key_buffer, "restricted"); else if (has_key && (key_flags & IW_ENCODE_OPEN)) hash_put(&wireless, key_buffer, "open"); return (0); } static int get_stats(const char *dev, const char *key) { struct iw_statistics stats; struct iwreq req; char qprintf_buffer[1024]; char key_buffer[32]; int age; struct iw_range range; qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key); age = hash_age(&wireless, key); /* reread every HASH_TTL msec only */ if (age > 0 && age <= HASH_TTL) { return (0); } if (get_ifname(&req, dev) != 0) { return (-1); } req.u.data.pointer = (caddr_t) & stats; req.u.data.length = 0; req.u.data.flags = 1; /* Clear updated flag */ if (do_ioctl(sock, dev, SIOCGIWSTATS, &req) < 0) { ioctl_error(__LINE__); return -1; } if (get_range_info(sock, dev, &range) < 0) memset(&range, 0, sizeof(range)); if (stats.qual.level > range.max_qual.level) { qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d", stats.qual.level - 0x100); qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_LEVEL); hash_put(&wireless, key_buffer, qprintf_buffer); qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d", stats.qual.noise - 0x100); qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_NOISE); hash_put(&wireless, key_buffer, qprintf_buffer); qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.qual, range.max_qual.qual); qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_QUALITY); hash_put(&wireless, key_buffer, qprintf_buffer); } else { qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.level, range.max_qual.level); qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_LEVEL);; hash_put(&wireless, key_buffer, qprintf_buffer); qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.noise, range.max_qual.noise); qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_NOISE); hash_put(&wireless, key_buffer, qprintf_buffer); qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.qual, range.max_qual.qual); qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_QUALITY); hash_put(&wireless, key_buffer, qprintf_buffer); } return 0; } static int check_socket() { /* already handled in a previous run */ if (sock == -3) return (-1); /* socket not initialized */ if (sock == -2) sock = socket(AF_INET, SOCK_DGRAM, 0); /* error initilalizing socket */ if (sock <= 0) { error("Error opening socket for reading wireless stats"); sock = -3; return (-1); } return (0); } static void save_result(RESULT * result, const char *dev, const char *key, const int res) { char key_buffer[64]; char *val = NULL; qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, key); if (res < 0) { SetResult(&result, R_STRING, ""); return; } val = hash_get(&wireless, key_buffer, NULL); if (val) { SetResult(&result, R_STRING, val); } else { SetResult(&result, R_STRING, ""); } } /* *functions exported to the evaluator */ static void wireless_quality(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_QUALITY, get_stats(dev, KEY_QUALITY)); } static void wireless_level(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_LEVEL, get_stats(dev, KEY_LEVEL)); } static void wireless_noise(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_NOISE, get_stats(dev, KEY_NOISE)); } static void wireless_protocol(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_PROTO, get_ifname(NULL, dev)); } static void wireless_frequency(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_FREQUENCY, get_frequency(dev, KEY_FREQUENCY)); } static void wireless_bitrate(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_BIT_RATE, get_bitrate(dev, KEY_BIT_RATE)); } static void wireless_essid(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_ESSID, get_essid(dev, KEY_ESSID)); } static void wireless_op_mode(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_OP_MODE, get_op_mode(dev, KEY_OP_MODE)); } static void wireless_sensitivity(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_SENS, get_sens(dev, KEY_SENS)); } static void wireless_sec_mode(RESULT * result, RESULT * arg1) { char *dev = R2S(arg1); if (check_socket() != 0) return; save_result(result, dev, KEY_SEC_MODE, get_sec_mode(dev, KEY_SEC_MODE)); } /* init and cleanup */ int plugin_init_wireless(void) { hash_create(&wireless); AddFunction("wifi::level", 1, wireless_level); AddFunction("wifi::noise", 1, wireless_noise); AddFunction("wifi::quality", 1, wireless_quality); AddFunction("wifi::protocol", 1, wireless_protocol); AddFunction("wifi::frequency", 1, wireless_frequency); AddFunction("wifi::bitrate", 1, wireless_bitrate); AddFunction("wifi::essid", 1, wireless_essid); AddFunction("wifi::op_mode", 1, wireless_op_mode); AddFunction("wifi::sensitivity", 1, wireless_sensitivity); AddFunction("wifi::sec_mode", 1, wireless_sec_mode); return 0; } void plugin_exit_wireless(void) { if (sock > 0) close(sock); hash_destroy(&wireless); }