Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Begin receiving packets upon opening the device

Simplify the interface by immediately receiving packets when the device
is opened. By default, all packets are sniffed. A filter can be applied
when the device is opened or changed later using filter/3.

Remove the loop/1 function. This also prevents multiple threads being
spawned to handle the same pcap descriptor.
  • Loading branch information...
commit 39db696f4597f9f414d43fe165b293ab93bb5374 1 parent 941bda3
Michael Santos authored
Showing with 49 additions and 30 deletions.
  1. +26 −27 README.md
  2. +0 −1  c_src/ewpcap.c
  3. +23 −2 src/ewpcap.erl
53 README.md
View
@@ -66,6 +66,10 @@ SMP erlang must be enabled (erl -smp -pa ebin).
Option = {promisc, boolean()}
| {snaplen, integer()}
| {to_ms, integer()}
+ | {filter, binary() | string()}
+ | FilterOpts
+
+ Open a network interface and begin receiving packets.
Dev is the name of the network device. If an empty binary (<<>>)
is passed in, pcap will select a default interface.
@@ -73,7 +77,7 @@ SMP erlang must be enabled (erl -smp -pa ebin).
If an error occurs, the PCAP string describing the error is
returned to the caller.
- open/1 and open/2 defaults to:
+ open/1 and open/2 default to:
* promiscuous mode disabled
@@ -81,26 +85,11 @@ SMP erlang must be enabled (erl -smp -pa ebin).
* timeout set to 500 ms
- close(Socket) -> ok
+ * no filter (all packets are received)
- Closes the pcap descriptor.
+ For filter options, see filter/3.
- filter(Socket, Filter, Options) -> ok | {error, Error}
-
- Types Socket = resource()
- Error = enomem | pcap_error_string()
- Options = [ Option ]
- Option = {optimize, boolean()}
- | {netmask, integer()}
-
- Compile a PCAP filter and apply it to the PCAP descriptor.
-
- loop(Socket) -> ok | {error, posix()}
-
- Types Socket = resource()
-
- Begin sniffing the network. Packets are returned as messages to
- the caller:
+ Packets are returned as messages to the caller:
{ewpcap, Ref, DatalinkType, Time, Length, Packet}
@@ -118,6 +107,21 @@ SMP erlang must be enabled (erl -smp -pa ebin).
The Packet is a binary holding the captured data.
+ close(Socket) -> ok
+
+ Closes the pcap descriptor.
+
+ filter(Socket, Filter) -> ok | {error, Error}
+ filter(Socket, Filter, Options) -> ok | {error, Error}
+
+ Types Socket = resource()
+ Error = enomem | pcap_error_string()
+ Options = [ Option ]
+ Option = {optimize, boolean()}
+ | {netmask, integer()}
+
+ Compile a PCAP filter and apply it to the PCAP descriptor.
+
read(Socket) -> {ok, Packet}
read(Socket, Timeout) -> {ok, Packet} | {error, eagain}
@@ -168,12 +172,7 @@ SMP erlang must be enabled (erl -smp -pa ebin).
% icmp_resend:start("eth0").
start(Dev) ->
- {ok, Socket} = ewpcap:open(Dev),
- ok = ewpcap:filter(Socket, "icmp"),
-
- % begin reading from the network
- ok = ewpcap:loop(Socket),
-
+ {ok, Socket} = ewpcap:open(Dev, [{filter, "icmp"}]),
resend(Socket).
resend(Socket) ->
@@ -183,10 +182,10 @@ SMP erlang must be enabled (erl -smp -pa ebin).
## TODO
-* rename loop/1
-
* ewpcap, epcap, epcap\_compile ... confusing!
* pcap\_sendpacket may block
+* pcap\_findalldevices blocks
+
* re-write as a port driver?
1  c_src/ewpcap.c
View
@@ -303,7 +303,6 @@ nif_pcap_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
pcap_breakloop(ep->p);
pcap_close(ep->p);
- /* XXX safe? pcap_loop may still be running */
ep->p = NULL;
return atom_ok;
25 src/ewpcap.erl
View
@@ -35,7 +35,6 @@
open/0, open/1, open/2,
close/1,
filter/2, filter/3,
- loop/1,
read/1, read/2,
write/2,
getifaddrs/0
@@ -94,8 +93,30 @@ open(Dev, Options) when is_list(Options) ->
Snaplen = proplists:get_value(snaplen, Options, 16#ffff),
Promisc = bool(proplists:get_value(promisc, Options, false)),
To_ms = proplists:get_value(to_ms, Options, 500),
+ Filter = proplists:get_value(filter, Options, <<>>),
- pcap_open_live(Dev, Snaplen, Promisc, To_ms).
+ case pcap_open_live(Dev, Snaplen, Promisc, To_ms) of
+ {ok, Socket} ->
+ open_1(Socket, Options, Filter);
+ Error ->
+ Error
+ end.
+
+open_1(Socket, _Options, <<>>) ->
+ open_2(Socket);
+open_1(Socket, Options, Filter) ->
+ case filter(Socket, Filter, Options) of
+ ok ->
+ open_2(Socket);
+ Error ->
+ Error
+ end.
+
+open_2(Socket) ->
+ case loop(Socket) of
+ ok -> {ok, Socket};
+ Error -> Error
+ end.
close(#ewpcap_resource{res = Res}) ->
pcap_close(Res).
Please sign in to comment.
Something went wrong with that request. Please try again.