diff --git a/README.md b/README.md index c97cc20..eb59bb2 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ the packets in the file. Examples -------- - +```erlang 48> {ok,FD}=pran:open_file("mtp2.pcap", ""). {ok,<0.152.0>} 49> pran:read(FD). @@ -37,7 +37,7 @@ Examples 1,17,19,...>>}] 51> pran:close(FD). ok - +``` Protocols --------- diff --git a/src/elibpcap.erl b/src/elibpcap.erl deleted file mode 100644 index 7a0991a..0000000 --- a/src/elibpcap.erl +++ /dev/null @@ -1,153 +0,0 @@ -%%%------------------------------------------------------------------- -%%% File : elibpcap.erl -%%% Author : Anders Nygren -%%% Description : Library for reading libpcap files. -%%% -%%% Created : 25 Nov 2010 by Anders Nygren -%%%------------------------------------------------------------------- --module(elibpcap). - --compile(export_all). - -%% API --export([file_header/1, - decode_frame/4]). - --include("elibpcap.hrl"). - --define(MAGIC, 16#a1b2c3d4). --define(NET_ETHERNET,1). --define(NET_MTP_2,140). - --define(PROTOCOLS,[{{udp,5060},sip}, {{tcp,5060},sip}, - {{udp,5062},sip}, {{tcp,5062},sip}, - {{udp,5063},sip}, {{tcp,5063},sip} - ]). - -%%==================================================================== -%% API -%%==================================================================== -%%-------------------------------------------------------------------- -%% Function: -%% Description: -%%-------------------------------------------------------------------- -file(File) -> - {ok,Bin} = file:read_file(File), - {#file_hdr{order=Order,major=2,minor=4,network=Net},Rest} = file_header(Bin), - dec_packets(Order, Net, Rest). - -%%==================================================================== -%% Internal functions -%%==================================================================== -dec_packets(Order, Net, Rest) -> - dec_frames(Order, Net, Rest, 1, []). - -dec_frames(_Order, _Network, <<>>, _N, Acc) -> - lists:reverse(Acc); -dec_frames(Order, Network, Bin, N, Acc) -> - {P,Rest} = decode_frame(Order, Network, N, Bin), - dec_frames(Order, Network, Rest, N+1, [P|Acc]). - -file_header(<>) -> - {#file_hdr{order = little, - major = Major, - minor = Minor, - gmt_to_localtime = GMT_to_localtime, - sigfigs= Sigfigs, - snaplen = Snaplen, - network = network(Network)}, - Data}; -file_header(<>) -> - {#file_hdr{order = big, - major = Major, - minor = Minor, - gmt_to_localtime = GMT_to_localtime, - sigfigs= Sigfigs, - snaplen = Snaplen, - network = network(Network)}, - Data}. - -network(?NET_ETHERNET) -> - ethernet; -network(?NET_MTP_2) -> - mtp_2. - -decode_frame(little, Network, Seq, - <>) -> - Truncated= Incl_payload_len>) -> - Truncated= Incl_payload_len - pran_ethernet:decode(big, Payload); -dec_pk_payload(little, ethernet, Payload) -> - pran_ethernet:decode(little, Payload). - -decode_tcp_udp_payload(Proto, Src, Dst, Payload) -> - case payload_protocol(Proto, Src,Dst) of - sip -> - case (rfc3261:'SIP-message'())(erlang:binary_to_list(Payload)) of - {ok, PDU, []} -> {sip,PDU}; - fail -> Payload - end; - unknown -> Payload - end. - -payload_protocol(Proto, FromPort, ToPort) -> - case {port_to_protocol(Proto, FromPort), - port_to_protocol(Proto, ToPort)} of - {undefined,undefined} -> unknown; - {AppProto, undefined} -> AppProto; - {undefined, AppProto} -> AppProto; - {AppProto, AppProto} -> AppProto; - _ -> unknown - end. - -port_to_protocol(Proto,Port) -> - case lists:keysearch({Proto,Port},1,?PROTOCOLS) of - {value,{_Key, Prot}} -> - Prot; - false -> - undefined - end. diff --git a/src/pran.app.src b/src/pran.app.src new file mode 100644 index 0000000..33c619f --- /dev/null +++ b/src/pran.app.src @@ -0,0 +1,11 @@ +{application, pran, + [ + {description, ""}, + {vsn, "1"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {env, []} + ]}. diff --git a/src/pran.erl b/src/pran.erl index 0454000..d4ed69b 100644 --- a/src/pran.erl +++ b/src/pran.erl @@ -7,10 +7,9 @@ %%%------------------------------------------------------------------- -module(pran). --compile(export_all). - %% API -export([open_file/2, + open_file_from_ram/2, read/1, close/1, grep_file/2]). @@ -31,7 +30,16 @@ open_file(File, Pat) when is_binary(Pat) -> open_file(File, {filters,[{pcap,{contain,CP}}]}); open_file(File, Filter) when is_tuple(Filter) -> Opts = pran_utils:load_config(), - {ok,_FD}=pran_pcap_file:open(File, [Filter|Opts]). + {ok,_FD}=pran_pcap_file:open(File, disk, [Filter|Opts]). + +open_file_from_ram(File, Pat) when is_list(Pat) -> + open_file_from_ram(File, list_to_binary(Pat)); +open_file_from_ram(File, Pat) when is_binary(Pat) -> + CP = pran_utils:mk_pattern(Pat), + open_file_from_ram(File, {filters,[{pcap,{contain,CP}}]}); +open_file_from_ram(File, Filter) when is_tuple(Filter) -> + Opts = pran_utils:load_config(), + {ok,_FD}=pran_pcap_file:open(File, memory, [Filter|Opts]). read(FD) -> pran_pcap_file:read(FD). diff --git a/src/pran_pcap_file.erl b/src/pran_pcap_file.erl index 2394637..99e99f1 100644 --- a/src/pran_pcap_file.erl +++ b/src/pran_pcap_file.erl @@ -10,7 +10,7 @@ -behaviour(gen_server). %% API --export([open/2, +-export([open/3, read/1, close/1]). @@ -44,8 +44,8 @@ %% Function: open() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- -open(File, Opts) -> - gen_server:start_link(?MODULE, [File,Opts], []). +open(File, Type, Opts) -> + gen_server:start_link(?MODULE, [File, Type, Opts], []). read(Fd) -> gen_server:call(Fd,read). @@ -64,11 +64,19 @@ close(Fd) -> %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- -init([File,Opts]) -> +init([File, Type, Opts]) -> Decoders = proplists:get_value(decoders, Opts), Filters = proplists:get_value(filters, Opts, []), - {ok, Fd} = file:open(File, [read, raw, binary]), - {ok, Bin} = file:pread(Fd, 0, ?BLOCKSIZE), + {Fd, Bin} = case Type of + disk -> + {ok, F} = file:open(File, [read, raw, binary]), + {ok, B} = file:pread(F, 0, ?BLOCKSIZE), + {F, B}; + memory -> + {ok, F} = file:open(File, [ram, read, binary]), + {ok, B} = file:pread(F, 0, ?BLOCKSIZE), + {F, B} + end, case pran_pcap:file_header(Bin) of {#file_hdr{order = Endian, major = _Major, minor = _Minor, @@ -188,13 +196,13 @@ read_block(#state{fd=Fd, offset=Offset}=State) -> %%-------------------------------------------------------------------- test_read_file(File) -> et:trace_me(80, test_read_frames,pcap_file,open,[]), - {ok,Pid} = open(File,[]), + {ok,Pid} = open(File, disk, []), F=read(Pid), test_read_frames(F,Pid). -test_read_frames(eof,Pid) -> +test_read_frames(eof,_Pid) -> ok; -test_read_frames(F,Pid) -> +test_read_frames(_F,Pid) -> et:trace_me(80, test_read_frames,pcap_file,read,[]), F1=read(Pid), test_read_frames(F1,Pid). diff --git a/src/pran_tcap.erl b/src/pran_tcap.erl deleted file mode 100644 index 0cc9a90..0000000 --- a/src/pran_tcap.erl +++ /dev/null @@ -1,109 +0,0 @@ -%%%------------------------------------------------------------------- -%%% File : pran_tcap.erl -%%% Author : Anders Nygren <> -%%% Description : -%%% -%%% Created : 4 Dec 2010 by Anders Nygren <> -%%%------------------------------------------------------------------- --module(pran_tcap). - -%% API --export([decode/3]). - -%% Dummy function used when no decoder is found --export([nothing/2]). - --include_lib("tcap/include/DialoguePDUs.hrl"). --include_lib("tcap/include/TCAPMessagesBasic.hrl"). - --record(operation, {ac, name, op_code, module, function, arg, res}). - -%%==================================================================== -%% API -%%==================================================================== -%%-------------------------------------------------------------------- -%% Function: -%% Description: -%%-------------------------------------------------------------------- -decode(Bin,Stack,Opts) -> - {ok,Rec}='TCAPMessagesBasic':decode('TCMessage',Bin), - {{dialogue,Dlg},{components,Cs}} = decode1(Rec, Opts), - {Cs++[{tcap,Dlg}]++Stack,<<>>,undefined}. - -%%==================================================================== -%% Internal functions -%%==================================================================== -decode1({'begin',#'Begin'{components=asn1_NOVALUE}=B}, Opts) -> - B; -decode1({'begin',#'Begin'{dialoguePortion=DP, - components=Cs}=B}, - Opts) when is_list(Cs) -> - Dlg = decode_dialoguePortion(DP), - AC = get_ac(Dlg), - Cs1 = [decode_component(AC,C,Opts) || C<-Cs], - {{dialogue,B#'Begin'{dialoguePortion=Dlg}},{components,Cs1}}; - -decode1({'continue',#'Continue'{dialoguePortion=DP, - components=Cs}=C}, - Opts) when is_list(Cs) -> - Dlg = decode_dialoguePortion(DP), - AC = get_ac(Dlg), - Cs1 = [decode_component(AC,C,Opts) || C<-Cs], - C#'Continue'{dialoguePortion=Dlg,components=Cs1}; -decode1({abort,#'Abort'{}=A}, Opts) -> - A; -decode1({'end',#'End'{}=E}, Opts) -> - E. - -decode_dialoguePortion({'EXTERNAL',{syntax,?'dialogue-as-id'},_,Bin}) -> - {ok,{_Alt,Value}} = 'DialoguePDUs':decode('DialoguePDU',Bin), - Value; -decode_dialoguePortion(asn1_NOVALUE) -> - asn1_NOVALUE. - -get_ac(#'AARQ-apdu'{'application-context-name'=AC}) -> - AC; -get_ac(#'AARE-apdu'{'application-context-name'=AC}) -> - AC; -get_ac(asn1_NOVALUE) -> - asn1_NOVALUE. - -decode_component(AC,{invoke,#'Invoke'{operationCode=OpCode,parameter=Param}=I}, - Opts) -> - #operation{module=Mod,function=Fun,arg=Type} = find_decoder(AC,OpCode,Opts), - Result = case Mod:Fun(Type,Param) of - {ok,Arg} -> Arg; - Error -> Error - end, - %% I#'Invoke'{parameter={map,Result}}; - {map,Result}; -decode_component(AC,{returnResultLast, - #'ReturnResult'{ - result=#'ReturnResult_result'{operationCode=OpCode, - parameter=Param}=R}=I}, - Opts) -> - #operation{module=Mod,function=Fun,arg=Type} = find_decoder(AC,OpCode,Opts), - Result = case Mod:Fun(Type,Param) of - {ok,Arg} -> Arg; - Error -> Error - end, - %% I#'ReturnResult'{result=R#'ReturnResult_result'{parameter={map,Result}}}; - {map,Result}; -decode_component(AC,{returnResultLast, - #'ReturnResult'{result=asn1_NOVALUE}=I},_Opts) -> - I. - -find_decoder(AC,OpCode,Opts) -> - Ops = pran_utils:get_conf_par(tcap,operations,Opts), - case [Op || #operation{ac=AC1,op_code=Op1}=Op <- Ops, AC==AC1,Op1==OpCode] of - [] -> - ORec = #operation{ac=AC,op_code=OpCode, - module=?MODULE,function=nothing}, - ORec; - [#operation{}=ORec] -> - ORec - end. - -%% Dummy function used when no decoder is found -nothing(_Type,Bin) -> - Bin.