Skip to content

Commit

Permalink
Try to figure out the default interface
Browse files Browse the repository at this point in the history
Use a dumb algorithm (whether an interface has a self-assigned IP address)
to determine the default network device. Really should check the routing
table instead for the interface associated with the default route.
  • Loading branch information
msantos committed Sep 17, 2010
1 parent be109e2 commit a56fb0b
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
23 changes: 17 additions & 6 deletions README
Expand Up @@ -25,11 +25,26 @@ HOW TO USE IT
perv:start() -> ok
perv:start(Options) -> ok

Types Options = list()
Types Options = [EpcapArgs | Keyword]
EpcapArgs = list()
Keyword = [exclude]

See epcap documentation for options.

Files are written to priv/files/<mime type>.
perv will try to find the default interface to snoop (and will
probably get it wrong if there is more than one network interface). To
exclude the local host from packet dumps, use:

> perv:start(exclude).

To override the defaults, manually specify the device using the
epcap options, e.g.:

> perv:start([
{interface, "eth0"},
{filter, "tcp and src port 80 and not host 10.11.11.11"}]).

Content is written to priv/files/<mime type>.

A trace file containing the HTTP response is written to priv/tmp. The
trace file can be unpacked by using pervon:content/3.
Expand Down Expand Up @@ -99,9 +114,5 @@ TODO
* pervon:content/3 should return a list of tuples containing the name,
file type and file contents, rather than writing them directly to disk

* since the interface being snooped is known, grab the device's IP
address using inet:ifget/2. Provide an option for including/excluding
the user's address.

* add option to enable/disable debug messages and tracing

39 changes: 32 additions & 7 deletions src/perv.erl
Expand Up @@ -37,6 +37,8 @@
-define(SERVER, ?MODULE).

-export([start/0, start/1, stop/0]).
-export([dev/0]).
-export([getip/1]).
-export([start_link/0, start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
Expand All @@ -46,27 +48,35 @@
}).

-define(EPCAP_DEFAULT_ARG, [{filter, "tcp and src port 80"},
{interface, "wlan0"},
{promiscuous, true},
{chroot, "priv/tmp"}]).


start() ->
start_link().
start(EpcapArg) ->
start_link(EpcapArg).
start(Options) ->
start_link(Options).

stop() ->
gen_server:call(?SERVER, [stop]).

start_link() ->
start_link([]).

start_link(EpcapArg) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [EpcapArg], []).
start_link(Options) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [Options], []).

init([EpcapArg]) ->
epcap:start(EpcapArg ++ ?EPCAP_DEFAULT_ARG),
init([Options]) ->
{Dev, Address} = dev(),

EpcapArgs = case Options of
exclude ->
[{filter, "tcp and src port 80 and not host " ++ inet_parse:ntoa(Address)}];
Opt when is_list(Opt) ->
Options
end,

epcap:start(EpcapArgs ++ [{interface, Dev}] ++ ?EPCAP_DEFAULT_ARG),
{ok, #state{c = dict:new()}}.


Expand Down Expand Up @@ -199,3 +209,18 @@ buf(Pid, SeqNo, Payload, PayloadSize) when PayloadSize < byte_size(Payload) ->
pervon:buf(Pid, SeqNo, <<Payload:PayloadSize/bytes>>).


% Try to autostupidly figure out the local host's network device.
% Guaranteed to annoy.
dev() ->
{ok, Devs} = inet:getiflist(),
Ifs = [ {N, getip(N)} || N <- Devs ],
hd(lists:filter(
fun ({_, {127,_,_,_}}) -> false;
({_, {169,_,_,_}}) -> false;
({_, {_,_,_,_}}) -> true
end, Ifs)).

getip(Dev) ->
{ok, Addr} = inet:ifget(Dev, [addr]),
proplists:get_value(addr, Addr).

0 comments on commit a56fb0b

Please sign in to comment.