diff options
Diffstat (limited to 'package')
37 files changed, 1507 insertions, 0 deletions
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 </dev/null 2>&1 & + killall -USR1 wiviz > /dev/null + fi +echo "<html><head><script language='JavaScript1.2'>" +cat /tmp/wiviz-pipe +echo "</script></head><body></body></html>" 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 Binary files differnew file mode 100755 index 000000000..79db61c4d --- /dev/null +++ b/package/wiviz/files/www/wiviz/adhoc-idle.gif diff --git a/package/wiviz/files/www/wiviz/adhoc-idle.png b/package/wiviz/files/www/wiviz/adhoc-idle.png Binary files differnew file mode 100755 index 000000000..24ae2769f --- /dev/null +++ b/package/wiviz/files/www/wiviz/adhoc-idle.png diff --git a/package/wiviz/files/www/wiviz/adhoc.gif b/package/wiviz/files/www/wiviz/adhoc.gif Binary files differnew file mode 100755 index 000000000..d07c80cce --- /dev/null +++ b/package/wiviz/files/www/wiviz/adhoc.gif diff --git a/package/wiviz/files/www/wiviz/adhoc.png b/package/wiviz/files/www/wiviz/adhoc.png Binary files differnew file mode 100755 index 000000000..7cabb3e8f --- /dev/null +++ b/package/wiviz/files/www/wiviz/adhoc.png diff --git a/package/wiviz/files/www/wiviz/ap-idle.gif b/package/wiviz/files/www/wiviz/ap-idle.gif Binary files differnew file mode 100755 index 000000000..376e194da --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap-idle.gif diff --git a/package/wiviz/files/www/wiviz/ap-idle.png b/package/wiviz/files/www/wiviz/ap-idle.png Binary files differnew file mode 100755 index 000000000..b5e593978 --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap-idle.png diff --git a/package/wiviz/files/www/wiviz/ap-wep-idle.gif b/package/wiviz/files/www/wiviz/ap-wep-idle.gif Binary files differnew file mode 100755 index 000000000..376e194da --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap-wep-idle.gif diff --git a/package/wiviz/files/www/wiviz/ap-wep-idle.png b/package/wiviz/files/www/wiviz/ap-wep-idle.png Binary files differnew file mode 100755 index 000000000..b5e593978 --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap-wep-idle.png diff --git a/package/wiviz/files/www/wiviz/ap-wep.gif b/package/wiviz/files/www/wiviz/ap-wep.gif Binary files differnew file mode 100755 index 000000000..33debb125 --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap-wep.gif diff --git a/package/wiviz/files/www/wiviz/ap-wep.png b/package/wiviz/files/www/wiviz/ap-wep.png Binary files differnew file mode 100755 index 000000000..2a907f05b --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap-wep.png diff --git a/package/wiviz/files/www/wiviz/ap.gif b/package/wiviz/files/www/wiviz/ap.gif Binary files differnew file mode 100755 index 000000000..739c18c91 --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap.gif diff --git a/package/wiviz/files/www/wiviz/ap.png b/package/wiviz/files/www/wiviz/ap.png Binary files differnew file mode 100755 index 000000000..038aab83a --- /dev/null +++ b/package/wiviz/files/www/wiviz/ap.png diff --git a/package/wiviz/files/www/wiviz/pip-idle.gif b/package/wiviz/files/www/wiviz/pip-idle.gif Binary files differnew file mode 100755 index 000000000..fa923bdf1 --- /dev/null +++ b/package/wiviz/files/www/wiviz/pip-idle.gif diff --git a/package/wiviz/files/www/wiviz/pip-idle.png b/package/wiviz/files/www/wiviz/pip-idle.png Binary files differnew file mode 100755 index 000000000..33c280ea6 --- /dev/null +++ b/package/wiviz/files/www/wiviz/pip-idle.png diff --git a/package/wiviz/files/www/wiviz/pip.gif b/package/wiviz/files/www/wiviz/pip.gif Binary files differnew file mode 100755 index 000000000..4d48ff92a --- /dev/null +++ b/package/wiviz/files/www/wiviz/pip.gif diff --git a/package/wiviz/files/www/wiviz/pip.png b/package/wiviz/files/www/wiviz/pip.png Binary files differnew file mode 100755 index 000000000..96be6a1e7 --- /dev/null +++ b/package/wiviz/files/www/wiviz/pip.png diff --git a/package/wiviz/files/www/wiviz/station-idle.gif b/package/wiviz/files/www/wiviz/station-idle.gif Binary files differnew file mode 100755 index 000000000..4abead018 --- /dev/null +++ b/package/wiviz/files/www/wiviz/station-idle.gif diff --git a/package/wiviz/files/www/wiviz/station-idle.png b/package/wiviz/files/www/wiviz/station-idle.png Binary files differnew file mode 100755 index 000000000..e37469c2f --- /dev/null +++ b/package/wiviz/files/www/wiviz/station-idle.png diff --git a/package/wiviz/files/www/wiviz/station.gif b/package/wiviz/files/www/wiviz/station.gif Binary files differnew file mode 100755 index 000000000..0008a706a --- /dev/null +++ b/package/wiviz/files/www/wiviz/station.gif diff --git a/package/wiviz/files/www/wiviz/station.png b/package/wiviz/files/www/wiviz/station.png Binary files differnew file mode 100755 index 000000000..2df942058 --- /dev/null +++ b/package/wiviz/files/www/wiviz/station.png 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 @@ +<html> +<head> +<!-- +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 +--> +<title>Wi-viz wireless network environment visualization</title> +<link rel='stylesheet' type='text/css' href='wiviz.css'> +<script language='JavaScript1.2' src='wiviz.js'> +</script> +</head> +<body> +<h2>OpenWRT Wi-viz network visualization</h2> +<div class='floater'> +Status: <span id='status' class='status'>Monitoring</span><br> +<input type='button' id='togglelisten' value='Stop monitoring' onclick='toggleListen()'> +<p><form name='channelform' action='/cgi-bin/wiviz/set.cgi' method='get' target='wivizGetFrame'> +Channel setting: +<select id='channelsel' name='channelsel' onchange='channelSet()'> +<option value='nochange' selected>No change</option> +<option value='hop'>Hopping</option> +<option>1</option> +<option>2</option> +<option>3</option> +<option>4</option> +<option>5</option> +<option>6</option> +<option>7</option> +<option>8</option> +<option>9</option> +<option>10</option> +<option>11</option> +<option>12</option> +<option>13</option> +<option>14</option> +</select><br> +<span id='hopoptions' style='display: none'> +Time/channel: <select name='hopdwell'> +<option value='500'>0.5 sec</option> +<option selected value='1000'>1 sec</option> +<option value='2000'>2 sec</option> +<option value='5000'>5 sec</option> +</select><br> +Hop sequence: <select name='hopseq'> +<option selected>1,3,6,8,11</option> +<option>1,3,6,8,11,14</option> +<option>1,6,11</option> +<option value='1,2,3,4,5,6,7,8,9,10,11'>1 to 11</option> +<option value='1,2,3,4,5,6,7,8,9,10,11,12,13,14'>1 to 14</option> +</select><br> +<input type='submit' value='Set'> +</form> +</span> +</div> +<center> +<div id='infodiv' class='main'> +<table height=100% width=100%><tr><td> +<span id='pips' style='position: relative'></span> +<span id='content' style='position: relative'></span> +</td></tr></table> +</div> +</center> +<span id='debug' style='display: none'></span> +<iframe style='display:none' id='wivizGetFrame' name='wivizGetFrame' src='about:blank'></iframe> +<script language='JavaScript1.2'> + scan_thread(); +</script> +</body> +</html> 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 += "<div class='hostdiv' id='" + hs.mnem + "' style='top: "; + nh += parseInt(hs.y) + "px; left: " + parseInt(hs.x) + "px'>"; + nh += genHTML(hs) + "</div>"; + } + } + 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 += "<img src='" + + ((hs.age < idle_timeout) ? "pip" : "pip-idle") + + (stupid ? ".gif" : ".png") + + "' class='pip' style='top:" + + parseInt(y+dy * j / d) + "; left:" + + parseInt(x+dx * j / d) + "'>"; + } + } + } + } + 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 += "<center><img class='icon' src='" + a = hs.descarr; + if (a[0] == 'ap' || a[0] == 'adhoc') { + if (a[0] == 'ap') { + nh += "ap"; + if (a[5] == 'enc') nh += "-wep"; + } + else { + nh += "adhoc"; + } + hs.channel = a[2]; + hs.name = a[4]; + } + else if (a[0] == 'sta') { + nh += "station"; + hs.channel = 0; + } + nh += (hs.age < idle_timeout) ? "": "-idle"; + nh += stupid ? ".gif" : ".png"; + nh += "' onmouseover='mousenter(event)' onmouseout='mouseout(event)'" + + "><br><span class='hostdesc'>" + hs.mac + "<br><i>'" + hs.name; + nh += "'</i>"; + if (hs.channel) { + nh += " ch" + hs.channel; + } + nh += "</span><span class='extrafo'><br>"; + if (a[0] == 'ap') nh += "Access point"; + if (a[0] == 'sta') nh += "Station"; + if (a[0] == 'adhoc') nh += "Logical ad-hoc entity"; + if (a[0] == 'ap' || a[0] == 'adhoc') { + nh += "<br>"; + if (a[5] == '?enc') nh += "Encryption unknown"; + if (a[5] == 'enc') nh += "Encrypted"; + if (a[5] == 'unenc') nh += "Unencrypted"; + if (a[6] == 'wep') nh += "-WEP"; + if (a[6] == 'wpa') nh += "-WPA"; + } + nh += "<br>RSSI: " + hs.rssi + " dBm<br>" + + "Seen " + hs.age + " seconds ago<br>"; + nh += "</span></center>"; + 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 <openwrt@nbd.name> +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 <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 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 <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 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 <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 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); |