Skip to content

Instantly share code, notes, and snippets.

@msantos
Created June 4, 2010 17:14
Show Gist options
  • Save msantos/425677 to your computer and use it in GitHub Desktop.
Save msantos/425677 to your computer and use it in GitHub Desktop.
%% Copyright (c) 2010, Michael Santos <[email protected]>
%% All rights reserved.
%%
%% Redistribution and use in source and binary forms, with or without
%% modification, are permitted provided that the following conditions
%% are met:
%%
%% Redistributions of source code must retain the above copyright
%% notice, this list of conditions and the following disclaimer.
%%
%% Redistributions in binary form must reproduce the above copyright
%% notice, this list of conditions and the following disclaimer in the
%% documentation and/or other materials provided with the distribution.
%%
%% Neither the name of the author nor the names of its contributors
%% may be used to endorse or promote products derived from this software
%% without specific prior written permission.
%%
%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
%% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
%% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
%% COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
%% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
%% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
%% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
%% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
%% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
%% POSSIBILITY OF SUCH DAMAGE.
-module(packet).
-export([sniff/0]).
-include("epcap_net.hrl").
-define(ETH_P_IP, 16#0008).
-define(ETH_P_ALL, 16#0300).
sniff() ->
{ok, Socket} = procket:listen(0, [
{protocol, ?ETH_P_ALL},
{type, raw},
{family, packet}
]),
loop(Socket).
loop(S) ->
case procket:recvfrom(S, 65535) of
nodata ->
timer:sleep(1000),
loop(S);
{ok, Data} ->
P = epcap_net:decapsulate(Data),
dump(P),
loop(S);
Error ->
error_logger:error_report(Error)
end.
dump([Ether, IP, Hdr, Payload]) ->
error_logger:info_report([
% Source
{source_macaddr, string:join(epcap_net:ether_addr(Ether#ether.shost), ":")},
{source_address, IP#ipv4.saddr},
{source_port, port(sport, Hdr)},
% Destination
{destination_macaddr, string:join(epcap_net:ether_addr(Ether#ether.dhost), ":")},
{destination_address, IP#ipv4.daddr},
{destination_port, port(dport, Hdr)},
{protocol, epcap_net:proto(IP#ipv4.p)},
{protocol_header, header(Hdr)},
{payload_bytes, byte_size(Payload)},
{payload, epcap_net:payload(Payload)}
]);
dump(Packet) ->
error_logger:info_report([{packet, Packet}]).
header(#tcp{ackno = Ackno, seqno = Seqno, win = Win} = Hdr) ->
[{flags, epcap_net:tcp_flags(Hdr)},
{seq, Seqno},
{ack, Ackno},
{win, Win}];
header(#udp{ulen = Ulen}) ->
[{ulen, Ulen}];
header(#icmp{code = Code, type = Type}) ->
[{type, Type},
{code, Code}];
header(Packet) ->
Packet.
port(sport, #tcp{sport = SPort}) -> SPort;
port(sport, #udp{sport = SPort}) -> SPort;
port(dport, #tcp{dport = DPort}) -> DPort;
port(dport, #udp{dport = DPort}) -> DPort;
port(_,_) -> "".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment