diff --git a/package/Config.in b/package/Config.in
index f9d6de650..1a7cfb8c9 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -108,6 +108,7 @@ source "package/wpa_supplicant/Config.in"
source "package/wput/Config.in"
source "package/xinetd/Config.in"
source "package/wificonf/Config.in"
+source "package/wiviz/Config.in"
comment "Libraries"
source "package/cgilib/Config.in"
diff --git a/package/Makefile b/package/Makefile
index 9ee4fa9e5..d081bf98e 100644
--- a/package/Makefile
+++ b/package/Makefile
@@ -157,6 +157,7 @@ package-$(BR2_PACKAGE_USBUTILS) += usbutils
package-$(BR2_PACKAGE_VTUN) += vtun
package-$(BR2_PACKAGE_VSFTPD) += vsftpd
package-$(BR2_PACKAGE_WIFICONF) += wificonf
+package-$(BR2_PACKAGE_WIVIZ) += wiviz
package-$(BR2_PACKAGE_WIRELESS_TOOLS) += wireless-tools
package-$(BR2_PACKAGE_WOL) += wol
package-$(BR2_PACKAGE_WPA_SUPPLICANT) += wpa_supplicant
diff --git a/package/wiviz/Config.in b/package/wiviz/Config.in
new file mode 100644
index 000000000..301bb627f
--- /dev/null
+++ b/package/wiviz/Config.in
@@ -0,0 +1,7 @@
+config BR2_PACKAGE_WIVIZ
+ tristate "wiviz - Wireless Network Visualization"
+ default m if CONFIG_DEVEL
+ help
+ Wireless Network Visualization
+
+ http://students.washington.edu/natetrue/wiviz/
diff --git a/package/wiviz/Makefile b/package/wiviz/Makefile
new file mode 100644
index 000000000..e3453f6cc
--- /dev/null
+++ b/package/wiviz/Makefile
@@ -0,0 +1,42 @@
+# $Id$
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wiviz
+PKG_VERSION:=1.0
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(TOPDIR)/package/rules.mk
+
+$(eval $(call PKG_template,WIVIZ,wiviz,$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH)))
+
+$(PKG_BUILD_DIR)/.prepared:
+ mkdir -p $(PKG_BUILD_DIR)
+ cp -fpR ./src/* $(PKG_BUILD_DIR)/
+ touch $@
+
+$(PKG_BUILD_DIR)/.configured:
+ touch $@
+
+$(PKG_BUILD_DIR)/.built:
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CC)" \
+ COPTS="$(TARGET_CFLAGS)" \
+ INCLUDE="-I$(STAGING_DIR)/include -I$(STAGING_DIR)/usr/include" \
+ LDFLAGS="-L$(STAGING_DIR)/lib -L$(STAGING_DIR)/usr/lib"
+ touch $@
+
+$(IPKG_WIVIZ):
+ mkdir -p $(IDIR_WIVIZ)/usr/sbin
+ cp $(PKG_BUILD_DIR)/$(PKG_NAME) $(IDIR_WIVIZ)/usr/sbin/
+ $(RSTRIP) $(IDIR_WIVIZ)
+ cp -fpR ./files/* $(IDIR_WIVIZ)
+ find $(IDIR_WIVIZ) -name CVS | xargs rm -rf
+ find $(IDIR_WIVIZ) -name .svn | xargs rm -rf
+ $(IPKG_BUILD) $(IDIR_WIVIZ) $(PACKAGE_DIR)
+
+mostlyclean:
+ $(MAKE) -C $(PKG_BUILD_DIR) clean
+ rm -f $(PKG_BUILD_DIR)/.built
diff --git a/package/wiviz/files/www/cgi-bin/wiviz/get.cgi b/package/wiviz/files/www/cgi-bin/wiviz/get.cgi
new file mode 100755
index 000000000..161fc75ee
--- /dev/null
+++ b/package/wiviz/files/www/cgi-bin/wiviz/get.cgi
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+WIVIZ_PATH=wiviz
+
+echo Content-type: text/html
+echo
+killall -USR1 wiviz >/dev/null 2>&1
+if [ 0 -ne $? ]
+ then #### Wi-Viz daemon not running, start it
+ $WIVIZ_PATH >/dev/null &1 &
+ killall -USR1 wiviz > /dev/null
+ fi
+echo "
"
diff --git a/package/wiviz/files/www/cgi-bin/wiviz/set.cgi b/package/wiviz/files/www/cgi-bin/wiviz/set.cgi
new file mode 100755
index 000000000..17b47873a
--- /dev/null
+++ b/package/wiviz/files/www/cgi-bin/wiviz/set.cgi
@@ -0,0 +1,3 @@
+#!/bin/sh
+httpd -d $QUERY_STRING > /tmp/wiviz-cfg
+killall -USR2 wiviz
diff --git a/package/wiviz/files/www/wiviz/adhoc-idle.gif b/package/wiviz/files/www/wiviz/adhoc-idle.gif
new file mode 100755
index 000000000..79db61c4d
Binary files /dev/null and b/package/wiviz/files/www/wiviz/adhoc-idle.gif differ
diff --git a/package/wiviz/files/www/wiviz/adhoc-idle.png b/package/wiviz/files/www/wiviz/adhoc-idle.png
new file mode 100755
index 000000000..24ae2769f
Binary files /dev/null and b/package/wiviz/files/www/wiviz/adhoc-idle.png differ
diff --git a/package/wiviz/files/www/wiviz/adhoc.gif b/package/wiviz/files/www/wiviz/adhoc.gif
new file mode 100755
index 000000000..d07c80cce
Binary files /dev/null and b/package/wiviz/files/www/wiviz/adhoc.gif differ
diff --git a/package/wiviz/files/www/wiviz/adhoc.png b/package/wiviz/files/www/wiviz/adhoc.png
new file mode 100755
index 000000000..7cabb3e8f
Binary files /dev/null and b/package/wiviz/files/www/wiviz/adhoc.png differ
diff --git a/package/wiviz/files/www/wiviz/ap-idle.gif b/package/wiviz/files/www/wiviz/ap-idle.gif
new file mode 100755
index 000000000..376e194da
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap-idle.gif differ
diff --git a/package/wiviz/files/www/wiviz/ap-idle.png b/package/wiviz/files/www/wiviz/ap-idle.png
new file mode 100755
index 000000000..b5e593978
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap-idle.png differ
diff --git a/package/wiviz/files/www/wiviz/ap-wep-idle.gif b/package/wiviz/files/www/wiviz/ap-wep-idle.gif
new file mode 100755
index 000000000..376e194da
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap-wep-idle.gif differ
diff --git a/package/wiviz/files/www/wiviz/ap-wep-idle.png b/package/wiviz/files/www/wiviz/ap-wep-idle.png
new file mode 100755
index 000000000..b5e593978
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap-wep-idle.png differ
diff --git a/package/wiviz/files/www/wiviz/ap-wep.gif b/package/wiviz/files/www/wiviz/ap-wep.gif
new file mode 100755
index 000000000..33debb125
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap-wep.gif differ
diff --git a/package/wiviz/files/www/wiviz/ap-wep.png b/package/wiviz/files/www/wiviz/ap-wep.png
new file mode 100755
index 000000000..2a907f05b
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap-wep.png differ
diff --git a/package/wiviz/files/www/wiviz/ap.gif b/package/wiviz/files/www/wiviz/ap.gif
new file mode 100755
index 000000000..739c18c91
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap.gif differ
diff --git a/package/wiviz/files/www/wiviz/ap.png b/package/wiviz/files/www/wiviz/ap.png
new file mode 100755
index 000000000..038aab83a
Binary files /dev/null and b/package/wiviz/files/www/wiviz/ap.png differ
diff --git a/package/wiviz/files/www/wiviz/pip-idle.gif b/package/wiviz/files/www/wiviz/pip-idle.gif
new file mode 100755
index 000000000..fa923bdf1
Binary files /dev/null and b/package/wiviz/files/www/wiviz/pip-idle.gif differ
diff --git a/package/wiviz/files/www/wiviz/pip-idle.png b/package/wiviz/files/www/wiviz/pip-idle.png
new file mode 100755
index 000000000..33c280ea6
Binary files /dev/null and b/package/wiviz/files/www/wiviz/pip-idle.png differ
diff --git a/package/wiviz/files/www/wiviz/pip.gif b/package/wiviz/files/www/wiviz/pip.gif
new file mode 100755
index 000000000..4d48ff92a
Binary files /dev/null and b/package/wiviz/files/www/wiviz/pip.gif differ
diff --git a/package/wiviz/files/www/wiviz/pip.png b/package/wiviz/files/www/wiviz/pip.png
new file mode 100755
index 000000000..96be6a1e7
Binary files /dev/null and b/package/wiviz/files/www/wiviz/pip.png differ
diff --git a/package/wiviz/files/www/wiviz/station-idle.gif b/package/wiviz/files/www/wiviz/station-idle.gif
new file mode 100755
index 000000000..4abead018
Binary files /dev/null and b/package/wiviz/files/www/wiviz/station-idle.gif differ
diff --git a/package/wiviz/files/www/wiviz/station-idle.png b/package/wiviz/files/www/wiviz/station-idle.png
new file mode 100755
index 000000000..e37469c2f
Binary files /dev/null and b/package/wiviz/files/www/wiviz/station-idle.png differ
diff --git a/package/wiviz/files/www/wiviz/station.gif b/package/wiviz/files/www/wiviz/station.gif
new file mode 100755
index 000000000..0008a706a
Binary files /dev/null and b/package/wiviz/files/www/wiviz/station.gif differ
diff --git a/package/wiviz/files/www/wiviz/station.png b/package/wiviz/files/www/wiviz/station.png
new file mode 100755
index 000000000..2df942058
Binary files /dev/null and b/package/wiviz/files/www/wiviz/station.png differ
diff --git a/package/wiviz/files/www/wiviz/wiviz.css b/package/wiviz/files/www/wiviz/wiviz.css
new file mode 100755
index 000000000..7b5afa706
--- /dev/null
+++ b/package/wiviz/files/www/wiviz/wiviz.css
@@ -0,0 +1,76 @@
+/*
+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
+*/
+body {
+ background-color: #D0D0D0;
+ vertical-align: center;
+ text-align: center;
+}
+div.main {
+ background-color: #D0F0D0;
+ width: 500px;
+ height: 500px;
+ border: 1px solid #555599;
+ vertical-align: center;
+ text-align: center;
+}
+div.floater {
+ background-color: #D0F0D0;
+ width: 125px;
+ height: 300px;
+ border: 1px solid #555599;
+ float: right;
+ z-index: 3;
+}
+span.status {
+ color: #FF0000;
+}
+img.icon {
+ width: 50px;
+ height: 50px;
+}
+img.pip {
+ width: 12px;
+ height: 12px;
+ position: absolute;
+ z-index: 1;
+}
+td {
+ vertical-align: center;
+ text-align: center;
+}
+span.hostdesc {
+ font-size: 10pt;
+}
+span.extrafo {
+ font-size: 10pt;
+ visibility: hidden;
+}
+div.hostdiv {
+ position: absolute;
+ background-color: transparent;
+ text-align: center;
+ width: 150px;
+ z-index: 2;
+}
+div.hostdiv_hov {
+ position: absolute;
+ background-color: #C0E0C0;
+ text-align: center;
+ width: 150px;
+ z-index: 3;
+ border: 1px solid #000000;
+}
diff --git a/package/wiviz/files/www/wiviz/wiviz.html b/package/wiviz/files/www/wiviz/wiviz.html
new file mode 100755
index 000000000..f1356fd82
--- /dev/null
+++ b/package/wiviz/files/www/wiviz/wiviz.html
@@ -0,0 +1,81 @@
+
+
+
+Wi-viz wireless network environment visualization
+
+
+
+
+OpenWRT Wi-viz network visualization
+
+Status:
Monitoring
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package/wiviz/files/www/wiviz/wiviz.js b/package/wiviz/files/www/wiviz/wiviz.js
new file mode 100755
index 000000000..dc67d8f01
--- /dev/null
+++ b/package/wiviz/files/www/wiviz/wiviz.js
@@ -0,0 +1,291 @@
+/*
+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
+*/
+var mv = 353;
+var stupid = eval('window.attachEvent') ? 1 : 0;
+var hosts;
+var idle_timeout = 20;
+var erase_timeout = 35;
+var skew_x = 0; skew_y = 0;
+var listening = 1;
+var wiviz_cgi_url = "/cgi-bin/wiviz/get.cgi";
+
+//What? You mean the POSIX thread API hasn't been ported to Javascript? Bugger.
+function scan_thread() {
+ var loc = document.getElementById('wivizGetFrame').contentWindow.location;
+ if (!listening) return;
+ if (loc.href != wiviz_cgi_url) {
+ loc.replace(wiviz_cgi_url);
+ }
+ else {
+ loc.reload(true);
+ }
+ setTimeout("scan_thread()", 5000);
+}
+
+function toggleListen() {
+ statusel = document.getElementById('status');
+ statusbutton = document.getElementById('togglelisten');
+ listening = 1 - listening;
+ if (listening) {
+ statusel.innerHTML = "Monitoring";
+ statusbutton.value = "Stop monitoring";
+ document.getElementById('content').innerHTML = '';
+ scan_thread();
+ }
+ else {
+ statusel.innerHTML = "Stopped";
+ statusbutton.value = "Start monitoring";
+ }
+}
+
+function channelSet() {
+ channelset = document.getElementById('channelsel').value;
+ if (channelset == 'hop') {
+ document.getElementById('hopoptions').style.display = 'inline';
+ }
+ else {
+ document.getElementById('hopoptions').style.display = 'none';
+ if (channelset != 'nochange') document.forms[0].submit();
+ }
+}
+
+function mousenter(e) {
+ if (stupid) e = event;
+ el = stupid ? e.srcElement : e.currentTarget;
+ el.parentNode.parentNode.className = 'hostdiv_hov';
+ el.nextSibling.nextSibling.nextSibling.style.visibility = 'visible';
+}
+
+function mouseout(e) {
+ if (stupid) e = event;
+ el = stupid ? e.srcElement : e.currentTarget;
+ el.parentNode.parentNode.className = 'hostdiv';
+ el.nextSibling.nextSibling.nextSibling.style.visibility = 'hidden';
+}
+
+function generate_mnemonic(hash) {
+ c = new Array('b','c','d','f','g','h','j','k','l','m','n','p','qu','r','s',
+ 't','v','w','y','z','th','ch','sh','cc','rr');
+ v = new Array('a','e','i','o','u','ae','ai','ao','au','eo','ei','eu','iu','oa','oe');
+ var i, a;
+ var p = hash & 1;
+ var n = '';
+ for (i = 0; i < 4; i++) {
+ a = p ? c : v;
+ n += a[hash % a.length];
+ hash += a.length << 3 + a.length / 2;
+ hash *= hash;
+ p = 1 - p;
+ }
+ return n;
+}
+
+function mkhash(mac) {
+ var macarr = mac.split(/:/);
+ var hash = 0;
+ for (j = 0; j < 6; j++) {
+ hash += parseInt(macarr[j]) * j << j;
+ hash += 11;
+ }
+ if (hash < 0) hash = -hash;
+ return hash;
+}
+
+function wiviz_callback(mhosts, cfgstring) {
+ var nh = '';
+ hosts = mhosts;
+ for (i = 0; i < hosts.length; i++) {
+ hs = hosts[i];
+ if (hs.length == 0) break;
+ hs.mac = hs[0];
+ hs.rssi = hs[1];
+ hs.desc = hs[2];
+ hs.descarr = hs.desc.split(/-/)
+ hs.age = hs[3];
+ hs.hash = mkhash(hs.mac);
+ hs.mnem = generate_mnemonic(hs.hash)
+ hs.name = hs.mnem;
+ el = document.getElementById(hs.mnem);
+ if (el) {
+ if (hs.age > erase_timeout) {
+ el.parentNode.removeChild(el);
+ continue;
+ }
+ el.innerHTML = genHTML(hs);
+ }
+ else {
+ if (hs.age > erase_timeout) continue;
+ hs.x = Math.sin(hs.hash / mv) * hs.rssi * 2 - 67;
+ hs.y = Math.cos(hs.hash / mv) * hs.rssi * 2;
+ nh += "";
+ nh += genHTML(hs) + "
";
+ }
+ }
+ document.getElementById('content').innerHTML += nh;
+
+ cfgarr = cfgstring.split(/-/);
+ if (cfgarr[1]) {
+ if (cfgarr[1] == 'hopping') cfgarr[1] = 'hop';
+ document.getElementById('channelsel').value = cfgarr[1];
+ if (cfgarr[1] == 'hop') channelSet();
+ }
+
+ //repip();
+ setTimeout("declump(); repip();", 250);
+}
+
+function repip() {
+ var nh = "";
+ if (!hosts) return;
+ for (i = 0; i < hosts.length; i++) {
+ hs = hosts[i];
+ if (hs.length == 0) break;
+ mac = hs[0];
+ rssi = hs[1];
+ desc = hs[2].split(/-/);
+ if (desc[0] == 'sta' && desc[1] == 'assoc') {
+ bss = desc[2];
+ hs.apmnem = generate_mnemonic(mkhash(bss));
+ ap = document.getElementById(hs.apmnem);
+ sta = document.getElementById(hs.mnem);
+ if (ap && sta) {
+ x = parseInt(sta.style.left);
+ y = parseInt(sta.style.top);
+ dx = parseInt(ap.style.left) - x;
+ dy = parseInt(ap.style.top) - y;
+ x += 67;
+ y += 10;
+ d = Math.sqrt(dx*dx+dy*dy);
+ for (j = 0; j < d; j += 15) {
+ nh += "";
+ }
+ }
+ }
+ }
+ document.getElementById('pips').innerHTML = nh;
+}
+
+function declump() {
+ var c = 0;
+ var top = 30000,left = 30000,right = -30000,bottom = -30000;
+ for (i = 0; i < hosts.length; i++) {
+ for (j = 0; j < hosts.length; j++) {
+ if (i == j) continue;
+ e1 = document.getElementById(hosts[i].mnem);
+ e2 = document.getElementById(hosts[j].mnem);
+ if (!e1 || !e2) continue;
+ x1 = parseInt(e1.style.left);
+ x2 = parseInt(e2.style.left);
+ y1 = parseInt(e1.style.top);
+ y2 = parseInt(e2.style.top);
+ if (x1 < left) left = x1;
+ if (y1 < top) top = y1;
+ if (x1 > right) right = x1;
+ if (y1 > bottom) bottom = y1;
+ ox = x2;
+ oy = y2;
+ dist = Math.sqrt(Math.pow((x1-x2), 2) + Math.pow((y1-y2), 2));
+ if (dist == 0) {
+ x2 += Math.random() * 5;
+ y2 += Math.random() * 5;
+ dist = 10;
+ }
+ if (dist < 100) {
+ cx = (x1-x2) * 5 / (dist / 3);
+ cy = (y1-y2) * 5 / (dist / 3);
+ x2 -= cx;
+ y2 -= cy;
+ }
+ if (hosts[j].apmnem == hosts[i].mnem
+ || hosts[i].apmnem == hosts[j].mnem) {
+ cx = (x1-x2) * 5 / (dist / 3);
+ cy = (y1-y2) * 5 / (dist / 3);
+ if (dist > 150) {
+ x2 += cx;
+ y2 += cy;
+ }
+ }
+ if (Math.abs(ox-x2) > 2 || Math.abs(oy-y2) > 2) {
+ e2.style.left = parseInt(x2);
+ e2.style.top = parseInt(y2);
+ c++;
+ }
+ }
+ }
+ if (top < bottom && left < right) {
+ document.getElementById('debug').innerHTML = left + "," + right + "," + top + "," +bottom;
+ document.getElementById('content').style.left =
+ document.getElementById('pips').style.left =
+ -(right - left) / 2 - left - 67;
+ document.getElementById('content').style.top =
+ document.getElementById('pips').style.top =
+ -(bottom - top) / 2 - top - 25;
+ }
+ repip();
+ if (c) setTimeout("declump()", 100);
+}
+
+function genHTML(hs) {
+ var nh = '';
+ nh += "
" + hs.mac + "
'" + hs.name;
+ nh += "'";
+ if (hs.channel) {
+ nh += " ch" + hs.channel;
+ }
+ nh += "";
+ return nh;
+}
diff --git a/package/wiviz/ipkg/wiviz.control b/package/wiviz/ipkg/wiviz.control
new file mode 100644
index 000000000..f90cb7930
--- /dev/null
+++ b/package/wiviz/ipkg/wiviz.control
@@ -0,0 +1,7 @@
+Package: wiviz
+Priority: optional
+Section: net
+Maintainer: Felix Fietkau
+Source: buildroot internal
+Depends: libpcap
+Description: Wireless Network Visualization
diff --git a/package/wiviz/src/Makefile b/package/wiviz/src/Makefile
new file mode 100644
index 000000000..6f230359d
--- /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 000000000..0a3e6feb0
--- /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
+#include
+#include
+#include
+#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 000000000..6ab63af08
--- /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 000000000..10f80f336
--- /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 000000000..d2ad9f2ee
--- /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
+#include
+#include
+
+#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 000000000..a5172c366
--- /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
+#include
+#include
+#include
+#include
+#include
+
+#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 000000000..96f239d9b
--- /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);