1 |
|
%% Copyright (c) 2015 Peter Morgan <peter.james.morgan@gmail.com> |
2 |
|
%% |
3 |
|
%% Licensed under the Apache License, Version 2.0 (the "License"); |
4 |
|
%% you may not use this file except in compliance with the License. |
5 |
|
%% You may obtain a copy of the License at |
6 |
|
%% |
7 |
|
%% http://www.apache.org/licenses/LICENSE-2.0 |
8 |
|
%% |
9 |
|
%% Unless required by applicable law or agreed to in writing, software |
10 |
|
%% distributed under the License is distributed on an "AS IS" BASIS, |
11 |
|
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 |
|
%% See the License for the specific language governing permissions and |
13 |
|
%% limitations under the License. |
14 |
|
|
15 |
|
-module(pcapng). |
16 |
|
-export([get_env/1]). |
17 |
|
-export([parse/1]). |
18 |
|
-export([process/1]). |
19 |
|
-export([variable_length/2]). |
20 |
|
-export([variable_length/3]). |
21 |
|
|
22 |
|
-define(SECTION_HEADER, 16#0A0D0D0A). |
23 |
|
-define(BYTE_ORDER_MAGIC, 16#1A2B3C4D). |
24 |
|
-define(INTERFACE_DESCRIPTION, 1). |
25 |
|
-define(PACKET, 2). |
26 |
|
-define(SIMPLE_PACKET, 3). |
27 |
|
-define(NAME_RESOLUTION, 4). |
28 |
|
-define(INTERFACE_STATISTICS, 5). |
29 |
|
-define(ENHANCED_PACKET, 6). |
30 |
|
|
31 |
|
|
32 |
|
process(Filename) -> |
33 |
:-( |
{ok, PCAPNG} = file:read_file(Filename), |
34 |
:-( |
write_file(filename:rootname(Filename) ++ ".terms", |
35 |
|
parse(PCAPNG)). |
36 |
|
|
37 |
|
|
38 |
|
write_file(Filename, Terms) -> |
39 |
:-( |
{ok, Header} = file:read_file("HEADER.txt"), |
40 |
|
|
41 |
:-( |
file:write_file( |
42 |
|
Filename, |
43 |
|
[io_lib:fwrite("%% -*- mode: erlang -*-~n", []), |
44 |
|
Header, |
45 |
:-( |
[io_lib:fwrite("~n~p.~n", [Term]) || Term <- Terms]]). |
46 |
|
|
47 |
|
|
48 |
|
parse(<< |
49 |
|
?SECTION_HEADER:32, |
50 |
|
_:32, |
51 |
|
?BYTE_ORDER_MAGIC:32/little, |
52 |
|
_/binary>> = Data) -> |
53 |
14 |
parse(Data, conversion(little)); |
54 |
|
|
55 |
|
parse(<< |
56 |
|
?SECTION_HEADER:32, |
57 |
|
_:32, |
58 |
|
?BYTE_ORDER_MAGIC:32/big, |
59 |
|
_/binary>> = Data) -> |
60 |
:-( |
parse(Data, conversion(big)). |
61 |
|
|
62 |
|
parse(Data, I) -> |
63 |
1560 |
case block(Data, I) of |
64 |
|
#{block := Block, remainder := <<>>} -> |
65 |
14 |
[Block]; |
66 |
|
|
67 |
|
#{block := Block, remainder := Remainder} -> |
68 |
1546 |
[Block | parse(Remainder, I)] |
69 |
|
end. |
70 |
|
|
71 |
|
|
72 |
|
block(<<Type:32/bits, _/binary>> = Data, I) -> |
73 |
1560 |
block(I(Type), Data, I). |
74 |
|
|
75 |
|
block(Type, Data, I) -> |
76 |
1560 |
#{body := Body, remainder := Remainder} = body(Type, Data, I), |
77 |
1560 |
#{block => decode(Type, Body, I), remainder => Remainder}. |
78 |
|
|
79 |
|
body(3, <<_:32/bits, TotalLength:32/bits, _/binary>> = Data, I) -> |
80 |
:-( |
BodyLength = I(TotalLength) - 11, |
81 |
:-( |
<< |
82 |
|
_:32/bits, |
83 |
|
TotalLength:32/bits, |
84 |
|
Body:BodyLength/bytes, |
85 |
|
TotalLength:32/bits, |
86 |
|
Remainder/binary |
87 |
|
>> = Data, |
88 |
:-( |
#{body => Body, remainder => Remainder}; |
89 |
|
|
90 |
|
body(_, <<_:32/bits, TotalLength:32/bits, _/binary>> = Data, I) -> |
91 |
1560 |
BodyLength = I(TotalLength) - 12, |
92 |
1560 |
<< |
93 |
|
_:32/bits, |
94 |
|
TotalLength:32/bits, |
95 |
|
Body:BodyLength/bytes, |
96 |
|
TotalLength:32/bits, |
97 |
|
Remainder/binary |
98 |
|
>> = Data, |
99 |
1560 |
#{body => Body, remainder => Remainder}. |
100 |
|
|
101 |
|
|
102 |
|
blocks() -> |
103 |
1560 |
#{ |
104 |
|
?SECTION_HEADER => pcapng_section_header_block, |
105 |
|
?INTERFACE_DESCRIPTION => pcapng_interface_description_block, |
106 |
|
?PACKET => pcapng_packet_block, |
107 |
|
?SIMPLE_PACKET => pcapng_simple_packet_block, |
108 |
|
?NAME_RESOLUTION => pcapng_name_resolution_block, |
109 |
|
?INTERFACE_STATISTICS => pcapng_interface_statistics_block, |
110 |
|
?ENHANCED_PACKET => pcapng_enhanced_packet_block |
111 |
|
}. |
112 |
|
|
113 |
|
|
114 |
|
decode(BlockType, BlockBody, I) -> |
115 |
1560 |
(maps:get(BlockType, blocks())):parse(BlockBody, I). |
116 |
|
|
117 |
|
variable_length(Packet, Length) -> |
118 |
1651 |
variable_length(Packet, Length, 4). |
119 |
|
|
120 |
|
variable_length(Packet, Length, Alignment) when Length rem Alignment =:= 0 -> |
121 |
180 |
<<Aligned:Length/bytes, Remainder/binary>> = Packet, |
122 |
180 |
#{body => Aligned, remainder => Remainder}; |
123 |
|
|
124 |
|
variable_length(Packet, Length, Alignment) -> |
125 |
1471 |
Padding = (Alignment - (Length rem Alignment)) * 8, |
126 |
1471 |
<<Aligned:Length/bytes, _:Padding, Remainder/binary>> = Packet, |
127 |
1471 |
#{body => Aligned, remainder => Remainder}. |
128 |
|
|
129 |
|
conversion(little) -> |
130 |
14 |
fun |
131 |
|
(Binary) -> |
132 |
12681 |
Size = bit_size(Binary), |
133 |
12681 |
<<I:Size/little>> = Binary, |
134 |
12681 |
I |
135 |
|
end; |
136 |
|
conversion(big) -> |
137 |
:-( |
fun |
138 |
|
(Binary) -> |
139 |
:-( |
Size = bit_size(Binary), |
140 |
:-( |
<<I:Size/big>> = Binary, |
141 |
:-( |
I |
142 |
|
end. |
143 |
|
|
144 |
|
get_env(Par) -> |
145 |
:-( |
case application:get_env(?MODULE, Par) of |
146 |
|
{ok, Val} -> |
147 |
:-( |
Val; |
148 |
|
|
149 |
|
undefined -> |
150 |
:-( |
#{} |
151 |
|
end. |