diff options
author | Felix Fietkau <nbd@openwrt.org> | 2005-08-29 11:30:35 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2005-08-29 11:30:35 +0000 |
commit | 308827eb4d3165053f5bfaeeb3ae10bbc995fd14 (patch) | |
tree | c83c02bec0dc98cc7d7f2287c1be5733ec238dae /package/wiviz/src | |
parent | dfd060f33a8b97c131207384da765de77f1f45f3 (diff) | |
download | upstream-308827eb4d3165053f5bfaeeb3ae10bbc995fd14.tar.gz upstream-308827eb4d3165053f5bfaeeb3ae10bbc995fd14.tar.bz2 upstream-308827eb4d3165053f5bfaeeb3ae10bbc995fd14.zip |
add Wi-viz
git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@1785 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/wiviz/src')
-rw-r--r-- | package/wiviz/src/Makefile | 25 | ||||
-rw-r--r-- | package/wiviz/src/channelhopper.c | 48 | ||||
-rw-r--r-- | package/wiviz/src/channelhopper.h | 19 | ||||
-rw-r--r-- | package/wiviz/src/structs.h | 169 | ||||
-rw-r--r-- | package/wiviz/src/wiviz.c | 572 | ||||
-rw-r--r-- | package/wiviz/src/wl_access.c | 73 | ||||
-rw-r--r-- | package/wiviz/src/wl_access.h | 77 |
7 files changed, 983 insertions, 0 deletions
diff --git a/package/wiviz/src/Makefile b/package/wiviz/src/Makefile new file mode 100644 index 0000000000..6f230359df --- /dev/null +++ b/package/wiviz/src/Makefile @@ -0,0 +1,25 @@ +## Wi-viz makefile +# Supply your own C cross-compiler; I recommend the one from the OpenWRT buildroot +# Also requires a libpcap to link with, use libpcap.a for static, .so for shared +CC=~/buildroot/staging_dir_mipsel/bin/mipsel-linux-gcc +LDFLAGS=-L~/buildroot/staging_dir_mipsel/lib +LIBS=-lpcap + +CCOPTS=-O2 -Os -pipe -mips32 -mtune=mips32 +INCLUDE=-I~/buildroot/staging_dir_mipsel/include +SOURCES=wiviz.c wl_access.c channelhopper.c +OBJS=wiviz.o wl_access.o channelhopper.o +TARGET=wiviz + +wiviz: ${OBJS} + ${CC} ${CCOPTS} ${INCLUDE} -o ${TARGET} ${OBJS} ${LDFLAGS} ${LIBS} + +wiviz.o: wiviz.c + ${CC} ${CCOPTS} ${INCLUDE} -c ${SOURCES} +wl_access.o: wl_access.c + ${CC} ${CCOPTS} ${INCLUDE} -c ${SOURCES} +channelhopper.o: channelhopper.c + ${CC} ${CCOPTS} ${INCLUDE} -c ${SOURCES} + +remake: + touch wiviz.c wl_access.c channelhopper.c diff --git a/package/wiviz/src/channelhopper.c b/package/wiviz/src/channelhopper.c new file mode 100644 index 0000000000..0a3e6feb08 --- /dev/null +++ b/package/wiviz/src/channelhopper.c @@ -0,0 +1,48 @@ +/* +This file is part of Wi-viz (http://wiviz.natetrue.com). + +Wi-viz is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License v2 as published by +the Free Software Foundation. + +Wi-viz 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 Wi-viz; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <stdio.h> +#include <pcap.h> +#include <signal.h> +#include <sys/time.h> +#include "wl_access.h" +#include "channelhopper.h" +#include "structs.h" + +void ch_sig_handler(int i) { + + } + +void channelHopper(wiviz_cfg * cfg) { + int hopPos; + int nc; + + //Turn off signal handling from parent process + signal(SIGUSR1, &ch_sig_handler); + signal(SIGUSR2, &ch_sig_handler); + + //Start hoppin'! + hopPos = 0; + while (1) { + nc = cfg->channelHopSeq[hopPos]; + hopPos = (hopPos + 1) % cfg->channelHopSeqLen; + //Set the channel + fprintf(stderr, "It sets the channel to %i\n", nc); + wl_ioctl(WL_DEVICE, WLC_SET_CHANNEL, &nc, 4); + //Sleep + usleep(cfg->channelDwellTime * 1000); + } + } diff --git a/package/wiviz/src/channelhopper.h b/package/wiviz/src/channelhopper.h new file mode 100644 index 0000000000..6ab63af088 --- /dev/null +++ b/package/wiviz/src/channelhopper.h @@ -0,0 +1,19 @@ +/* +This file is part of Wi-viz (http://wiviz.natetrue.com). + +Wi-viz is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License v2 as published by +the Free Software Foundation. + +Wi-viz 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 Wi-viz; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +// Channel hopper definition + +void channelHopper(); diff --git a/package/wiviz/src/structs.h b/package/wiviz/src/structs.h new file mode 100644 index 0000000000..10f80f336e --- /dev/null +++ b/package/wiviz/src/structs.h @@ -0,0 +1,169 @@ +/* +This file is part of Wi-viz (http://wiviz.natetrue.com). + +Wi-viz is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License v2 as published by +the Free Software Foundation. + +Wi-viz 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 Wi-viz; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +//Structure definitions for wireless packets + +#define MAX_HOSTS 257 + +#ifdef DEFINE_TYPES +typedef unsigned short u_short; +typedef unsigned char u_char; +typedef unsigned int u_int; +#endif + +typedef enum { + mgt_assocRequest = 0, + mgt_assocResponse = 1, + mgt_reassocRequest = 2, + mgt_reassocResponse = 3, + mgt_probeRequest = 4, + mgt_probeResponse = 5, + mgt_beacon = 8, + mgt_disassoc = 10, + mgt_auth = 11, + mgt_deauth = 12 + } wifi_frametype; + +typedef struct ieee802_11_hdr { + u_char frame_control; + u_char flags; +#define IEEE80211_TO_DS 0x01 +#define IEEE80211_FROM_DS 0x02 +#define IEEE80211_MORE_FRAG 0x04 +#define IEEE80211_RETRY 0x08 +#define IEEE80211_PWR_MGT 0x10 +#define IEEE80211_MORE_DATA 0x20 +#define IEEE80211_WEP_FLAG 0x40 +#define IEEE80211_ORDER_FLAG 0x80 + u_short duration; + u_char addr1[6]; + u_char addr2[6]; + u_char addr3[6]; + u_short frag_and_seq; + } ieee802_11_hdr; + +typedef struct { + u_char timestamp[8]; + u_short bcn_interval; + u_short caps; +#define MGT_CAPS_AP 0x1 +#define MGT_CAPS_IBSS 0x2 +#define MGT_CAPS_WEP 0x10 + } ieee_802_11_mgt_frame; + +typedef struct { + u_char tag; + u_char length; + } ieee_802_11_tag; + +typedef enum { + tagSSID = 0, + tagRates = 1, + tagChannel = 3, + tagVendorSpecific = 0xDD + } i81tag; + +typedef struct prism_hdr { + u_int msg_code; + u_int msg_length; + char cap_device[16]; + //char dids[0]; + } prism_hdr; + +typedef struct prism_did { + u_short did; + u_short status1; + u_short status2; + u_short length; + //int value[0]; + } prism_did; + +typedef enum prism_did_num { + pdn_host_time = 0x1041, + pdn_mac_time = 0x2041, + pdn_rssi = 0x4041, + pdn_sq = 0x5041, + pdn_datarate = 0x8041, + pdn_framelen = 0xa041 + } prism_did_num; + + + +//Structure definitions for data collection + +typedef enum { + typeUnknown, + typeAP, + typeSta, + typeAdhocHub + } host_type; + +typedef enum { + ssUnknown, + ssUnassociated, + ssAssociated + } sta_state; + +typedef enum { + aetUnknown, + aetUnencrypted, + aetEncUnknown, + aetEncWEP, + aetEncWPA + } ap_enc_type; + +typedef struct { + u_char bssid[6]; + char * ssid[32]; + u_char ssidlen; + u_char channel; + u_short flags; + ap_enc_type encryption; + } ap_info; + +typedef struct { + sta_state state; + u_char connectedBSSID[6]; + } sta_info; + +typedef struct { + u_char occupied; + u_char mac[6]; + host_type type; + time_t lastSeen; + int RSSI; + ap_info * apInfo; + sta_info * staInfo; + } wiviz_host; + +//Primary config struct +typedef struct { + wiviz_host hosts[MAX_HOSTS]; + int numHosts; + int readFromWl; + time_t lastKeepAlive; + int channelHopping; + int channelDwellTime; + int channelHopSeq[14]; + int channelHopSeqLen; + int curChannel; + int channelHopperPID; + } wiviz_cfg; + + + + + diff --git a/package/wiviz/src/wiviz.c b/package/wiviz/src/wiviz.c new file mode 100644 index 0000000000..d2ad9f2ee4 --- /dev/null +++ b/package/wiviz/src/wiviz.c @@ -0,0 +1,572 @@ +/* +This file is part of Wi-viz (http://wiviz.natetrue.com). + +Wi-viz is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License v2 as published by +the Free Software Foundation. + +Wi-viz 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 Wi-viz; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <stdio.h> +#include <pcap.h> +#include <signal.h> + +#define HOST_TIMEOUT 300 + +#include "wl_access.h" +#include "structs.h" +#include "channelhopper.h" + +#ifdef WIN32 +#define OFFLINE +#endif +#ifndef __cplusplus +#define __cdecl +#endif + +#define nonzeromac(x) memcmp(x, "\0\0\0\0\0\0", 6) + +void dealWithPacket(wiviz_cfg * cfg, struct pcap_pkthdr * header, const u_char * packet); +wiviz_host * gotHost(wiviz_cfg * cfg, u_char * mac, host_type type); +void fprint_mac(FILE * outf, u_char * mac, char * extra); +void print_mac(u_char * mac, char * extra); +void print_host(FILE * outf, wiviz_host * host); +void __cdecl signal_handler(int); +void readWL(wiviz_cfg * cfg); +void reloadConfig(); + +wiviz_cfg * global_cfg; + +//////////////////////////////////////////////////////////////////////////////// +int main(int argc, char * * argv) { + pcap_t *handle; + char *dev; + char errbuf[PCAP_ERRBUF_SIZE]; + int stop = 0; + int oldMonitor, newMonitor; + struct pcap_pkthdr header; + const u_char *packet; + wiviz_cfg cfg; + int i; + int defaultHopSeq[] = { 1, 3, 6, 8, 11 }; + + global_cfg = &cfg; + signal(SIGUSR1, &signal_handler); + signal(SIGUSR2, &signal_handler); + + fprintf(stderr, "Wi-Viz infogathering daemon by Nathan True\n"); + + memset(&cfg, 0, sizeof(wiviz_cfg)); + cfg.numHosts = 0; + cfg.lastKeepAlive = time(NULL); + cfg.channelHopping = 0; + cfg.channelDwellTime = 1000; + cfg.channelHopSeqLen = 5; + memcpy(cfg.channelHopSeq, defaultHopSeq, sizeof(defaultHopSeq)); + + wl_ioctl(WL_DEVICE, WLC_GET_MAGIC, &i, 4); + if (i != WLC_IOCTL_MAGIC) { + fprintf(stderr, "Wireless magic not correct, not querying wl for info\n"); + cfg.readFromWl = 0; + } + else { + cfg.readFromWl = 1; + wl_ioctl(WL_DEVICE, WLC_GET_MONITOR, &oldMonitor, 4); + newMonitor = 1; + wl_ioctl(WL_DEVICE, WLC_SET_MONITOR, &newMonitor, 4); + } + + reloadConfig(); + +#ifndef OFFLINE + dev = "prism0"; + handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); +#else + dev = "c:\\cifsroot\\wdump2.pcap"; + handle = pcap_open_offline(dev, errbuf); +#endif + + if (cfg.readFromWl) { + readWL(&cfg); + } + + if (!handle) { + fprintf(stderr, "Failure to open pcap!\nErr=%s\n", errbuf); + return -1; + } + while (!stop) { + packet = pcap_next(handle, &header); + if (!packet) break; + dealWithPacket(&cfg, &header, packet); + if (time(NULL) - cfg.lastKeepAlive > 30) stop = 1; + } + + signal_handler(SIGUSR1); + + if (cfg.channelHopperPID) kill(cfg.channelHopperPID, SIGKILL); + + for (i = 0; i < MAX_HOSTS; i++) { + print_host(stderr, cfg.hosts + i); + if (cfg.hosts[i].occupied) printf("\n"); + if (cfg.hosts[i].apInfo) free(cfg.hosts[i].apInfo); + if (cfg.hosts[i].staInfo) free(cfg.hosts[i].staInfo); + } + + wl_ioctl(WL_DEVICE, WLC_SET_MONITOR, &oldMonitor, 4); + + pcap_close(handle); + return 0; + } + +//////////////////////////////////////////////////////////////////////////////// +void writeJavascript() { + int i; + FILE * outf; + wiviz_host * h; + + outf = fopen("/tmp/wiviz-pipe", "w"); + if (!outf) { + fprintf(stderr, "Failure to open output file\n"); + return; + } + + global_cfg->lastKeepAlive = time(NULL); + + if(global_cfg->readFromWl) readWL(global_cfg); + + fprintf(outf, "top.hosts = new Array(\n"); + for (i = 0; i < MAX_HOSTS; i++) { + h = global_cfg->hosts + i; + if (h->occupied == 0) continue; + if (time(NULL) - h->lastSeen > HOST_TIMEOUT) { + h->occupied = 0; + } + fprintf(outf, " new Array("); + print_host(outf, h); + fprintf(outf, "),\n"); + } + fprintf(outf, "new Array());\n"); + fprintf(outf, "var cfg_string = 'channel-"); + if (global_cfg->channelHopping) { + fprintf(outf, "hopping"); + } + else { + fprintf(outf, "%i", global_cfg->curChannel); + } + fprintf(outf, "';\ntop.wiviz_callback(top.hosts, cfg_string);\n"); + fclose(outf); + } + +//////////////////////////////////////////////////////////////////////////////// +void reloadConfig() { + FILE * cnf; + wiviz_cfg * cfg = global_cfg; + char filebuffer[512]; + char * fbptr, * p, * v, * vv; + int fblen, val; + int hopCfgChanged = 0; + int newHopSeq[12]; + int newHopSeqLen = 0; + + fprintf(stderr, "Loading config file\n"); + + cnf = fopen("/tmp/wiviz-cfg", "r"); + if (!cnf) { + fprintf(stderr, "Wiviz: No config file (/tmp/wiviz-cfg) present, using defaults\n"); + return; + } + + fblen = fread(filebuffer, 1, 512, cnf); + fclose(cnf); + if (fblen >= 512) { + fprintf(stderr, "Error reading config file\n"); + return; + } + filebuffer[fblen] = 0; + fprintf(stderr, "Read %i bytes from config file\n", fblen); + + fbptr = filebuffer; + + while (fbptr < filebuffer + fblen && *fbptr != 0) { + p = fbptr; + //Find end of parameter + for (; *fbptr != '=' && *fbptr != 0; fbptr++); + *fbptr = 0; + v = ++fbptr; + //Find end of value + for (; *fbptr != '&' && *fbptr != 0; fbptr++); + *(fbptr++) = 0; + fprintf(stderr, "Config: %s=%s\n", p, v); + //Apply configuration + if (!strcmp(p, "channelsel")) { + //Channel selector + cfg->channelHopping = 0; + if (!strcmp(v, "hop")) { + //Set channel hopping + cfg->channelHopping = 1; + hopCfgChanged = 1; + } + else if (!strcmp(v, "nochange")) { + //Don't change anything, read channel from wireless card + readWL(cfg); + } + else { + val = atoi(v); + if (val < 1 || val > 14) { + fprintf(stderr, "Channel setting in config file invalid (%i)\n", cfg->curChannel); + } + else { + cfg->curChannel = val; + if (cfg->readFromWl) { + if (wl_ioctl(WL_DEVICE, WLC_SET_CHANNEL, &cfg->curChannel, 4) < 0) { + fprintf(stderr, "Channel set to %i failed\n", cfg->curChannel); + } + } + else { + fprintf(stderr, "Can't set channel, no Broadcom wireless device present\n"); + } + } + } + } + if (!strcmp(p, "hopdwell")) { + val = atoi(v); + if (val < 100) val = 100; + if (val > 30000) val = 30000; + if (cfg->channelDwellTime != val) hopCfgChanged = 1; + cfg->channelDwellTime = val; + } + if (!strcmp(p, "hopseq")) { + cfg->channelHopSeqLen = 0; + while (v < fbptr) { + for (vv = v; *vv != ',' && *vv != 0; vv++); + if (*vv == 0) { + cfg->channelHopSeq[cfg->channelHopSeqLen++] = atoi(v); + break; + } + *vv = 0; + cfg->channelHopSeq[cfg->channelHopSeqLen++] = atoi(v); + v = vv + 1; + } + } + /* + if (!strcmp(p, "")) { + } + */ + } + //Apply channel hopper settings + if (cfg->channelHopping == 0 && cfg->channelHopperPID) { + kill(cfg->channelHopperPID, SIGKILL); + cfg->channelHopperPID = 0; + } + if (cfg->channelHopping == 1 && hopCfgChanged) { + if (cfg->channelHopperPID) kill(cfg->channelHopperPID, SIGKILL); + if ((cfg->channelHopperPID = fork()) == 0) { + channelHopper(cfg); + } + } + } + +//////////////////////////////////////////////////////////////////////////////// +void __cdecl signal_handler(int signum) { + if (signum == SIGUSR1) writeJavascript(); + if (signum == SIGUSR2) reloadConfig(); + } + +//////////////////////////////////////////////////////////////////////////////// +void dealWithPacket(wiviz_cfg * cfg, struct pcap_pkthdr * header, const u_char * packet) { + ieee802_11_hdr * hWifi; + prism_hdr * hPrism; + wiviz_host * host; + wiviz_host * emergebss; + host_type type = typeUnknown; + int wfType; + int rssi = 0; + int to_ds, from_ds; + prism_did * i; + ieee_802_11_tag * e; + ieee_802_11_mgt_frame * m; + char * src = "\0\0\0\0\0\0"; + char * dst = "\0\0\0\0\0\0"; + char * bss = "\0\0\0\0\0\0"; + char * ssid = ""; + int channel = 0; + int adhocbeacon = 0; + u_char ssidlen = 0; + ap_enc_type encType = aetUnknown; + + if (!packet) return; + if (header->len < sizeof(prism_hdr) + sizeof(ieee802_11_hdr)) return; + hPrism = (prism_hdr *) packet; + hWifi = (ieee802_11_hdr *) (packet + (hPrism->msg_length)); + + //Parse the prism DIDs + i = (prism_did *)((char *)hPrism + sizeof(prism_hdr)); + while ((int)i < (int)hWifi) { + if (i->did == pdn_rssi) rssi = *(int *)(i+1); + i = (prism_did *) ((int)(i+1) + i->length); + } + + //Establish the frame type + wfType = ((hWifi->frame_control & 0xF0) >> 4) + ((hWifi->frame_control & 0xC) << 2); + switch (wfType) { + case mgt_assocRequest: + case mgt_reassocRequest: + case mgt_probeRequest: + type = typeSta; + src=hWifi->addr2; + dst=hWifi->addr1; + break; + case mgt_assocResponse: + case mgt_reassocResponse: + case mgt_probeResponse: + case mgt_beacon: + src=hWifi->addr2; + dst=hWifi->addr1; + bss=hWifi->addr3; + type = typeAP; + break; + } + to_ds = hWifi->flags & IEEE80211_TO_DS; + from_ds = hWifi->flags & IEEE80211_FROM_DS; + if ((wfType & 0xF0) == 0x20 && (wfType & 0xF) < 4) { + //Data frame + src=hWifi->addr2; + dst=hWifi->addr1; + if (!from_ds) type = typeSta; + else type = typeAP; + if (!to_ds && !from_ds) bss = hWifi->addr3; + if (to_ds && !from_ds) bss = hWifi->addr1; + if (!to_ds && from_ds) bss = hWifi->addr2; + } + if (type == typeUnknown) return; + + //Parse the 802.11 tags + if (wfType == mgt_probeResponse || wfType == mgt_beacon) { + m = (ieee_802_11_mgt_frame *) (hWifi + 1); + if (m->caps & MGT_CAPS_IBSS) { + type = typeSta; + adhocbeacon = 1; + } + if (m->caps & MGT_CAPS_WEP) encType = aetEncWEP; + else encType = aetUnencrypted; + e = (ieee_802_11_tag *) ((int) m + sizeof(ieee_802_11_mgt_frame)); + while ((u_int)e < (u_int)packet + header->len) { + if (e->tag == tagSSID) { + ssidlen = e->length; + ssid = (char *)(e + 1); + } + if (e->tag == tagChannel) { + channel = *(char *)(e + 1); + } + if (e->tag == tagVendorSpecific) { + if (e->length >= 4 && memcmp(e + 1, "\x00\x50\xf2\x01", 4) == 0) { + //WPA encryption + encType = aetEncWPA; + } + } + e = (ieee_802_11_tag *) ((int)(e + 1) + e->length); + } + } + + //Look up the host in the hash table + host = gotHost(cfg, src, type); + + //Add any info we received + if (host->RSSI) { + host->RSSI = host->RSSI * 9 / 10 + (-rssi * 10); + } + else { + host->RSSI = -rssi * 100; + } + if (type == typeSta) { + if (nonzeromac(bss)) { + memcpy(host->staInfo->connectedBSSID, bss, 6); + host->staInfo->state = ssAssociated; + emergebss = gotHost(cfg, bss, typeAP); + if (emergebss->RSSI == 0) emergebss->RSSI = 10000; + memcpy(emergebss->apInfo->bssid, bss, 6); + if (adhocbeacon) { + emergebss->type = typeAdhocHub; + if (ssidlen > 0 && ssidlen <= 32) { + memcpy(emergebss->apInfo->ssid, ssid, ssidlen); + emergebss->apInfo->ssidlen = ssidlen; + } + if (channel) emergebss->apInfo->channel = channel; + emergebss->apInfo->flags = hWifi->flags; + emergebss->RSSI = host->RSSI; + if (encType != aetUnknown) emergebss->apInfo->encryption = encType; + } + } + if (wfType == mgt_probeRequest && host->staInfo->state == ssUnknown) host->staInfo->state = ssUnassociated; + } + if (type == typeAP) { + if (nonzeromac(bss)) { + memcpy(host->apInfo->bssid, bss, 6); + } + if (ssidlen > 0 && ssidlen <= 32) { + memcpy(host->apInfo->ssid, ssid, ssidlen); + host->apInfo->ssidlen = ssidlen; + } + if (channel) host->apInfo->channel = channel; + host->apInfo->flags = hWifi->flags; + if (encType != aetUnknown) host->apInfo->encryption = encType; + } + } + +//////////////////////////////////////////////////////////////////////////////// +void print_mac(u_char * mac, char * extra) { + fprint_mac(stdout, mac, extra); + } + +//////////////////////////////////////////////////////////////////////////////// +void fprint_mac(FILE * outf, u_char * mac, char * extra) { + fprintf(outf, "%02X:%02X:%02X:%02X:%02X:%02X%s", + mac[0] & 0xFF, + mac[1] & 0xFF, + mac[2] & 0xFF, + mac[3] & 0xFF, + mac[4] & 0xFF, + mac[5] & 0xFF, + extra); + } + +//////////////////////////////////////////////////////////////////////////////// +#define MAX_PROBES MAX_HOSTS/2 +wiviz_host * gotHost(wiviz_cfg * cfg, u_char * mac, host_type type) { + int i = (mac[5] + (mac[4] << 8)) % MAX_HOSTS; + int c = 0; + wiviz_host * h = cfg->hosts + i; + while (h->occupied && memcmp(h->mac, mac, 6)) { + i++; h++; c++; + if (i >= MAX_HOSTS) { + i = 0; + h = cfg->hosts; + } + if (c > MAX_PROBES) break; + } + if (!h->occupied) { + fprintf(stderr, "New host, "); + fprint_mac(stderr, mac, ", type="); + fprintf(stderr, "%s\n", (type==typeAP) ? "AP" : ((type==typeSta) ? "Sta" : "Unk")); + } + h->occupied = 1; + h->lastSeen = time(NULL); + h->type = type; + memcpy(h->mac, mac, 6); + if (h->type == typeAP && !h->apInfo) { + h->apInfo = (ap_info *) malloc(sizeof(ap_info)); + memset(h->apInfo, 0, sizeof(ap_info)); + } + if (h->type == typeSta && !h->staInfo) { + h->staInfo = (sta_info *) malloc(sizeof(sta_info)); + memset(h->staInfo, 0, sizeof(sta_info)); + } + return h; + } + +//////////////////////////////////////////////////////////////////////////////// +void print_host(FILE * outf, wiviz_host * host) { + int i; + + if (!host->occupied) return; + fprintf(outf, "'"); + fprint_mac(outf, host->mac, "'"); + fprintf(outf, ", -%i, '", host->RSSI / 100); + switch (host->type) { + case typeAP: fprintf(outf, "ap"); break; + case typeSta: fprintf(outf, "sta"); break; + case typeAdhocHub: fprintf(outf, "adhoc"); break; + } + if (host->type == typeSta) { + switch(host->staInfo->state) { + case ssAssociated: + fprintf(outf, "-assoc-"); + fprint_mac(outf, host->staInfo->connectedBSSID, ""); + break; + case ssUnassociated: + fprintf(outf, "-unassoc"); + } + } + if (host->type == typeAP || host->type == typeAdhocHub) { + fprintf(outf, "-channel-%i-ssid-", host->apInfo->channel & 0xFF); + for (i = 0; i < host->apInfo->ssidlen; i++) { + fprintf(outf, "\\x%02X", *((char *)host->apInfo->ssid + i) & 0xFF); + } + switch (host->apInfo->encryption) { + case aetUnknown: fprintf(outf, "-?enc-?alg"); break; + case aetUnencrypted: fprintf(outf, "-unenc-na"); break; + case aetEncUnknown: fprintf(outf, "-enc-unknown"); break; + case aetEncWEP: fprintf(outf, "-enc-wep"); break; + case aetEncWPA: fprintf(outf, "-enc-wpa"); break; + } + } + fprintf(outf, "', %i", time(0) - host->lastSeen); + } + +//////////////////////////////////////////////////////////////////////////////// +#define MAX_STA_COUNT 64 +void readWL(wiviz_cfg * cfg) { + int ap, i; + wiviz_host * host, * sta; + uchar mac[6]; + wlc_ssid_t ssid; + channel_info_t channel; + maclist_t * macs; + sta_rssi_t starssi; + + get_mac(WL_DEVICE, mac); + printf("AP mac: "); + print_mac(mac, "\n"); + if (!nonzeromac(mac)) return; + wl_ioctl(WL_DEVICE, WLC_GET_AP, &ap, 4); + if (ap) { + host = gotHost(cfg, mac, typeAP); + wl_ioctl(WL_DEVICE, WLC_GET_BSSID, host->apInfo->bssid, 6); + wl_ioctl(WL_DEVICE, WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t)); + memcpy(host->apInfo->ssid, ssid.SSID, 32); + host->apInfo->ssidlen = ssid.SSID_len; + host->RSSI = 0; + wl_ioctl(WL_DEVICE, WLC_GET_CHANNEL, &channel, sizeof(channel_info_t)); + host->apInfo->channel = channel.hw_channel; + macs = (maclist_t *) malloc(4 + MAX_STA_COUNT * sizeof(ether_addr_t)); + macs->count = MAX_STA_COUNT; + if (wl_ioctl(WL_DEVICE, WLC_GET_ASSOCLIST, macs, 4 + MAX_STA_COUNT * sizeof(ether_addr_t)) > -1) { + for (i = 0; i < macs->count; i++) { + sta = gotHost(cfg, (char *)&macs->ea[i], typeSta); + memcpy(starssi.mac, &macs->ea[i], 6); + starssi.RSSI = 3000; + starssi.zero_ex_forty_one = 0x41; + if (wl_ioctl(WL_DEVICE, WLC_GET_RSSI, &starssi, 12) < 0) printf("rssifail\n"); + sta->RSSI = -starssi.RSSI * 100; + sta->staInfo->state = ssAssociated; + memcpy(sta->staInfo->connectedBSSID, host->apInfo->bssid, 6); + } + } + } + else { + host = gotHost(cfg, mac, typeSta); + host->RSSI = 0; + if (wl_ioctl(WL_DEVICE, WLC_GET_BSSID, &host->staInfo->connectedBSSID, 6) < 0) { + host->staInfo->state = ssUnassociated; + } + else { + host->staInfo->state = ssAssociated; + } + } + if (wl_ioctl(WL_DEVICE, WLC_GET_CHANNEL, &channel, sizeof(channel_info_t)) >= 0) { + cfg->curChannel = channel.hw_channel; + fprintf(stderr, "Current channel is %i\n", cfg->curChannel); + } +} + + + + + diff --git a/package/wiviz/src/wl_access.c b/package/wiviz/src/wl_access.c new file mode 100644 index 0000000000..a5172c3665 --- /dev/null +++ b/package/wiviz/src/wl_access.c @@ -0,0 +1,73 @@ +/* +This file is part of Wi-viz (http://wiviz.natetrue.com). + +Wi-viz is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License v2 as published by +the Free Software Foundation. + +Wi-viz 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 Wi-viz; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <net/if.h> + +#include "wl_access.h" + +int wl_ioctl(char *name, int cmd, void *buf, int len) +{ + struct ifreq ifr; + wl_ioctl_t ioc; + int ret = 0; + int s; + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return errno; + } + + /* do it */ + ioc.cmd = cmd; + ioc.buf = buf; + ioc.len = len; + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_data = (caddr_t) &ioc; + ret = ioctl(s, SIOCDEVPRIVATE, &ifr); + + /* cleanup */ + close(s); + return ret; +} + +int get_mac(char *name, void *buf) +{ + struct ifreq ifr; + int ret = 0; + int s; + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return errno; + } + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + //ifr.ifr_data = (caddr_t) buf; + if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) < 0) + perror(ifr.ifr_name); + + /* cleanup */ + close(s); + memcpy(buf, &ifr.ifr_hwaddr.sa_data, 6); + return ret; +} diff --git a/package/wiviz/src/wl_access.h b/package/wiviz/src/wl_access.h new file mode 100644 index 0000000000..96f239d9b7 --- /dev/null +++ b/package/wiviz/src/wl_access.h @@ -0,0 +1,77 @@ +/* +This file is part of Wi-viz (http://wiviz.natetrue.com). + +Wi-viz is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License v2 as published by +the Free Software Foundation. + +Wi-viz 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 Wi-viz; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +//wl_access.h - functions for accessing broadcom crap + +#define WL_DEVICE "eth1" + +typedef unsigned int uint32; +typedef unsigned char uchar; +typedef int bool; + +typedef struct ether_addr { + uchar addr[6]; +} ether_addr_t; + +typedef struct wlc_ssid { + uint32 SSID_len; + uchar SSID[32]; +} wlc_ssid_t; +/* For ioctls that take a list of MAC addresses */ +typedef struct maclist { + uint count; /* number of MAC addresses */ + struct ether_addr ea[1]; /* variable length array of MAC addresses */ +} maclist_t; +/* Linux network driver ioctl encoding */ +typedef struct wl_ioctl { + uint cmd; /* common ioctl definition */ + void *buf; /* pointer to user buffer */ + uint len; /* length of user buffer */ + bool set; /* get or set request (optional) */ + uint used; /* bytes read or written (optional) */ + uint needed; /* bytes needed (optional) */ +} wl_ioctl_t; +/* channel encoding */ +typedef struct channel_info { + int hw_channel; + int target_channel; + int scan_channel; +} channel_info_t; +/* RSSI info for sta */ +typedef struct sta_rssi { + int RSSI; + char mac[6]; + u_short zero_ex_forty_one; + } sta_rssi_t; +/* check this magic number */ +#define WLC_IOCTL_MAGIC 0x14e46c77 + +#define WLC_GET_MAGIC 0 +#define WLC_GET_BSSID 23 +#define WLC_SET_BSSID 24 +#define WLC_GET_SSID 25 +#define WLC_SET_SSID 26 +#define WLC_GET_CHANNEL 29 +#define WLC_SET_CHANNEL 30 +#define WLC_GET_MONITOR 107 /* discovered by nbd */ +#define WLC_SET_MONITOR 108 /* discovered by nbd */ +#define WLC_GET_AP 117 +#define WLC_SET_AP 118 +#define WLC_GET_RSSI 127 +#define WLC_GET_ASSOCLIST 159 + + +int wl_ioctl(char *name, int cmd, void *buf, int len); |