Created
March 7, 2011 22:17
-
-
Save msantos/859390 to your computer and use it in GitHub Desktop.
Erlang wireless AP scanner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(wierl). | |
-export([start/1]). | |
-define(UINT16, 2/native-unsigned-integer-unit:8). | |
-define(UINT32, 4/native-unsigned-integer-unit:8). | |
-define(UINT64, 8/native-unsigned-integer-unit:8). | |
-define(IFNAMSIZ, 16). | |
-define(SIOCSIWSCAN, 16#8B18). % Trigger a scan | |
-define(SIOCGIWSCAN, 16#8B19). % Retrieve the scan results | |
% Event types | |
-define(SIOCGIWAP, 16#8B15). | |
-define(SIOCGIWAPLIST, 16#8B17). | |
-define(SIOCGIWAUTH, 16#8B33). | |
-define(SIOCGIWENCODE, 16#8B2B). | |
-define(SIOCGIWENCODEEXT, 16#8B35). | |
-define(SIOCGIWESSID, 16#8B1B). | |
-define(SIOCGIWFRAG, 16#8B25). | |
-define(SIOCGIWFREQ, 16#8B05). | |
-define(SIOCGIWGENIE, 16#8B31). | |
-define(SIOCGIWMODE, 16#8B07). | |
-define(SIOCGIWMODUL, 16#8B2F). | |
-define(SIOCGIWNAME, 16#8B01). | |
-define(SIOCGIWNICKN, 16#8B1D). | |
-define(SIOCGIWNWID, 16#8B03). | |
-define(SIOCGIWPOWER, 16#8B2D). | |
-define(SIOCGIWPRIV, 16#8B0D). | |
-define(SIOCGIWRANGE, 16#8B0B). | |
-define(SIOCGIWRATE, 16#8B21). | |
-define(SIOCGIWRETRY, 16#8B29). | |
-define(SIOCGIWRTS, 16#8B23). | |
-define(SIOCGIWSENS, 16#8B09). | |
-define(SIOCGIWSPY, 16#8B11). | |
-define(SIOCGIWSTATS, 16#8B0F). | |
-define(SIOCGIWTHRSPY, 16#8B13). | |
-define(SIOCGIWTXPOW, 16#8B27). | |
-define(IWEVGENIE, 16#8C05). | |
-define(IWEVQUAL, 16#8C01). | |
-define(IWEVCUSTOM, 16#8C02). | |
%% | |
%% Open an unprivileged, datagram socket using | |
%% procket | |
%% | |
start(Dev) when is_binary(Dev) -> | |
{ok, Socket} = procket:socket(inet, dgram, 0), | |
scan(Dev, Socket), | |
procket:close(Socket). | |
%% | |
%% Initiate the scan | |
%% | |
scan(Dev, Socket) when byte_size(Dev) < ?IFNAMSIZ -> | |
Req = <<Dev/binary, 0:((?IFNAMSIZ - byte_size(Dev))*8), 0:(16*8)>>, | |
{ok, _Req} = procket:ioctl(Socket, ?SIOCSIWSCAN, Req), | |
result(Dev, Socket). | |
%% | |
%% Retrieve the scan results by specifying a buffer for the | |
%% kernel to return the results | |
%% | |
result(Dev, Socket) -> | |
{ok, Req, [Res]} = procket:alloc([ | |
<<Dev/bytes, 0:( (?IFNAMSIZ - byte_size(Dev))*8)>>, | |
{ptr, 4096}, | |
<<4096:?UINT16, 0:?UINT16>> | |
]), | |
case procket:ioctl(Socket, ?SIOCGIWSCAN, Req) of | |
{ok, <<_Ifname:16/bytes, _Ptr:?UINT32, Len:?UINT16, _Flag:?UINT16>>} -> | |
{ok, <<Stream:Len/bytes, _/binary>>} = procket:buf(Res), | |
event(Stream); | |
% Poll the socket for the results | |
{error, eagain} -> | |
timer:sleep(1000), | |
result(Dev, Socket); | |
Error -> | |
Error | |
end. | |
% The events are returned in the form: length, command, data | |
% (length bytes) | |
% | |
% We believe the length returned in the packet and print out | |
% the binary data. If the length is wrong, we'll just crash. | |
event(<<>>) -> | |
ok; | |
event(<<Len:?UINT16, Cmd:?UINT16, Bin/binary>>) -> | |
EventLen = Len - 4, | |
<<Event:EventLen/bytes, Rest/binary>> = Bin, | |
io:format("~p:~p~n", [cmd(Cmd), Event]), | |
event(Rest). | |
% Convert the integer command values to almost human readable atoms | |
cmd(?SIOCGIWNAME) -> name; | |
cmd(?SIOCGIWNWID) -> nwid; | |
cmd(?SIOCGIWFREQ) -> freq; | |
cmd(?SIOCGIWMODE) -> mode; | |
cmd(?SIOCGIWSENS) -> sens; | |
cmd(?SIOCGIWRANGE) -> range; | |
cmd(?SIOCGIWPRIV) -> priv; | |
cmd(?SIOCGIWSTATS) -> stats; | |
cmd(?SIOCGIWSPY) -> spy; | |
cmd(?SIOCGIWTHRSPY) -> thrspy; | |
cmd(?SIOCGIWAP) -> bssid; | |
cmd(?SIOCGIWAPLIST) -> aplist; | |
cmd(?SIOCGIWESSID) -> essid; | |
cmd(?SIOCGIWNICKN) -> nickn; | |
cmd(?SIOCGIWRATE) -> rate; | |
cmd(?SIOCGIWRTS) -> rts; | |
cmd(?SIOCGIWFRAG) -> frag; | |
cmd(?SIOCGIWTXPOW) -> txpow; | |
cmd(?SIOCGIWRETRY) -> retry; | |
cmd(?SIOCGIWENCODE) -> encode; | |
cmd(?SIOCGIWPOWER) -> power; | |
cmd(?SIOCGIWMODUL) -> modul; | |
cmd(?SIOCGIWGENIE) -> genie; | |
cmd(?SIOCGIWAUTH) -> auth; | |
cmd(?SIOCGIWENCODEEXT) -> encodeext; | |
cmd(?IWEVGENIE) -> genie; | |
cmd(?IWEVQUAL) -> qual; | |
cmd(?IWEVCUSTOM) -> custom; | |
cmd(Unknown) -> {unknown, Unknown}. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment