Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 214 lines (182 sloc) 6.827 kb
0406018 @msantos Add licensing and do cleanup. In other words, do stuff.
authored
1 %% Copyright (c) 2009, Michael Santos <michael.santos@gmail.com>
2 %% All rights reserved.
3 %%
4 %% Redistribution and use in source and binary forms, with or without
5 %% modification, are permitted provided that the following conditions
6 %% are met:
7 %%
8 %% Redistributions of source code must retain the above copyright
9 %% notice, this list of conditions and the following disclaimer.
10 %%
11 %% Redistributions in binary form must reproduce the above copyright
12 %% notice, this list of conditions and the following disclaimer in the
13 %% documentation and/or other materials provided with the distribution.
14 %%
15 %% Neither the name of the author nor the names of its contributors
16 %% may be used to endorse or promote products derived from this software
17 %% without specific prior written permission.
18 %%
19 %% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 %% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 %% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 %% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 %% COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 %% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 %% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 %% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 %% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 %% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 %% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 %% POSSIBILITY OF SUCH DAMAGE.
31 -module(epcap_net).
32
33 -include("epcap_net.hrl").
34
965b308 @msantos Decapsulate truncated packets. Convert sniff to a gen_server.
authored
35 -define(ETHERHDRLEN, 16).
36 -define(IPV4HDRLEN, 20).
37 -define(TCPHDRLEN, 20).
38 -define(UDPHDRLEN, 8).
39 -define(ICMPHDRLEN, 8).
40
0406018 @msantos Add licensing and do cleanup. In other words, do stuff.
authored
41 -export([
42 checksum/1,
43 checksum/3,
44 decapsulate/1,
45 makesum/1,
46 valid/1,
47 ether/1,
48 ether_addr/1,
49 icmp/1,
50 ipv4/1,
1fac0f7 @msantos Now compiler friendly, typo free!
authored
51 payload/1,
965b308 @msantos Decapsulate truncated packets. Convert sniff to a gen_server.
authored
52 proto/1,
0406018 @msantos Add licensing and do cleanup. In other words, do stuff.
authored
53 tcp/1,
54 tcp_flags/1,
55 udp/1
56 ]).
57
58 -define(is_print(C), C >= $ , C =< $~).
59
965b308 @msantos Decapsulate truncated packets. Convert sniff to a gen_server.
authored
60 decapsulate(P) when byte_size(P) < ?ETHERHDRLEN ->
61 invalid_packet;
62 decapsulate(P) when byte_size(P) < ?ETHERHDRLEN + ?IPV4HDRLEN ->
63 {EtherHdr, EtherData} = ether(P),
64 [EtherHdr, {truncated, EtherData}, <<>>, <<>>];
0406018 @msantos Add licensing and do cleanup. In other words, do stuff.
authored
65 decapsulate(P) ->
66 {EtherHdr, EtherData} = ether(P),
67 {IPHdr, IPData} = ipv4(EtherData),
965b308 @msantos Decapsulate truncated packets. Convert sniff to a gen_server.
authored
68 {Hdr, Payload} = decapsulate(proto(IPHdr#ipv4.p), (IPData)),
0406018 @msantos Add licensing and do cleanup. In other words, do stuff.
authored
69 [EtherHdr, IPHdr, Hdr, Payload].
70
965b308 @msantos Decapsulate truncated packets. Convert sniff to a gen_server.
authored
71 decapsulate(tcp, Packet) when byte_size(Packet) >= ?TCPHDRLEN ->
72 tcp(Packet);
73 decapsulate(udp, Packet) when byte_size(Packet) >= ?UDPHDRLEN ->
74 udp(Packet);
75 decapsulate(icmp, Packet) when byte_size(Packet) >= ?ICMPHDRLEN ->
76 icmp(Packet);
77 decapsulate(_, Packet) ->
78 {{truncated, Packet}, <<>>}.
79
80
0406018 @msantos Add licensing and do cleanup. In other words, do stuff.
authored
81 proto(?IPPROTO_ICMP) -> icmp;
82 proto(?IPPROTO_TCP) -> tcp;
83 proto(?IPPROTO_UDP) -> udp.
84
85 ether(<<Dhost:6/bytes, Shost:6/bytes, Type:2/bytes, Packet/binary>>) ->
86 Len = byte_size(Packet) - 4,
87 <<Payload:Len/bytes, CRC:4/bytes>> = Packet,
88 {#ether{
89 dhost = Dhost, shost = Shost,
90 type = Type, crc = CRC
91 }, Payload}.
92
93 ipv4(
94 <<V:4, HL:4, ToS:8, Len:16,
95 Id:16, _RF:1, DF:1, MF:1,
96 Off:13, TTL:8, P:8, Sum:16,
97 SA1:8, SA2:8, SA3:8, SA4:8,
98 DA1:8, DA2:8, DA3:8, DA4:8,
99 Payload/binary>> = Raw
100 ) ->
101 <<Hdr:160/bitstring, _/binary>> = Raw,
102 Valid = case makesum(Hdr) of
103 0 -> true;
104 _ -> false
105 end,
106
107 {#ipv4{
108 valid = Valid,
109 v = V, hl = HL, tos = ToS, len = Len,
110 id = Id, df = DF, mf = MF,
111 off = Off, ttl = TTL, p = P, sum = Sum,
112 saddr = {SA1,SA2,SA3,SA4},
113 daddr = {DA1,DA2,DA3,DA4}
114 }, Payload}.
115
116 tcp(
117 <<SPort:16, DPort:16,
118 SeqNo:32,
119 AckNo:32,
120 Off:4, 0:4, CWR:1, ECE:1, URG:1, ACK:1,
121 PSH:1, RST:1, SYN:1, FIN:1, Win:16,
122 Sum:16, Urp:16,
123 Payload/binary>>
124 ) ->
125 {Opt, Msg} = tcp_options(tcp_offset(Off), Payload),
126 {#tcp{
127 sport = SPort, dport = DPort,
128 seqno = SeqNo,
129 ackno = AckNo,
130 off = Off, cwr = CWR, ece = ECE, urg = URG, ack = ACK,
131 psh = PSH, rst = RST, syn = SYN, fin = FIN, win = Win,
132 sum = Sum, urp = Urp,
133 opt = Opt
134 }, Msg}.
135
136 tcp_offset(N) when N > 5 -> (N - 5) * 4;
137 tcp_offset(_) -> 0.
138
139 % Appears some optimization is stripping the padding off the options
140 tcp_options(Offset, Payload) when Offset > byte_size(Payload) ->
141 {Payload, <<>>};
142 tcp_options(Offset, Payload) when Offset > 0 ->
143 <<Opt:Offset/bytes, Msg/binary>> = Payload,
144 {Opt, Msg};
145 tcp_options(_, Payload) ->
146 {<<>>, Payload}.
147
148 udp(<<SPort:16, DPort:16, ULen:16, Sum:16, Payload/binary>>) ->
149 {#udp{sport = SPort, dport = DPort, ulen = ULen, sum = Sum}, Payload}.
150
151 icmp(<<?ICMP_ECHO:8, Code:8, Checksum:16, Id:16, Sequence:16, Payload/binary>>) ->
152 {#icmp{
153 type = ?ICMP_ECHO, code = Code, checksum = Checksum, id = Id,
154 sequence = Sequence
155 }, Payload};
156
157 % PLACEHOLDER: gateway
158 icmp(<<?ICMP_DEST_UNREACH:8, Code:8, Checksum:16, Gateway:32, Payload/binary>>) ->
159 {#icmp{
160 type = ?ICMP_DEST_UNREACH, code = Code, checksum = Checksum, gateway = Gateway
161 }, Payload};
162
163 % PLACEHOLDER: frag
164 icmp(<<?ICMP_DEST_UNREACH:8, Code:8, Checksum:16, _Unused:16, MTU:16, Payload/binary>>) ->
165 {#icmp{
166 type = ?ICMP_DEST_UNREACH, code = Code, checksum = Checksum, mtu = MTU
167 }, Payload};
168
169 % Catch unknown types
170 icmp(<<Type:8, Code:8, Checksum:16, Un:32, Payload/binary>>) ->
171 {#icmp{
172 type = Type, code = Code, checksum = Checksum, un = Un
173 }, Payload}.
174
175 payload(Payload) ->
176 [ to_ascii(C) || <<C:8>> <= Payload ].
177
178 checksum(Hdr) ->
179 lists:foldl(fun compl/2, 0, [ W || <<W:16>> <= Hdr ]).
180
181 checksum(tcp, #ipv4{saddr = {S1,S2,S3,S4}, daddr = {D1,D2,D3,D4}, p = P},
182 <<Head:16/bytes, _:2/bytes, Trailer/binary>> = Payload) ->
183 Len = byte_size(Payload),
184 PseudoHdr = case Len rem 2 of
185 0 -> <<S1,S2,S3,S4,D1,D2,D3,D4,0:8,P,Len:16,Head/bytes,0:16,Trailer/bytes>>;
186 1 -> <<S1,S2,S3,S4,D1,D2,D3,D4,0:8,P,Len:16,Head/bytes,0:16,Trailer/bytes,0>>
187 end,
188 checksum(PseudoHdr).
189
190 makesum(Hdr) -> 16#FFFF - checksum(Hdr).
191
192 compl(N) when N =< 16#FFFF -> N;
193 compl(N) -> (N band 16#FFFF) + (N bsr 16).
194 compl(N,S) -> compl(N+S).
195
196 valid(16#FFFF) -> true;
197 valid(_) -> false.
198
199 to_ascii(C) when ?is_print(C) -> C;
200 to_ascii(_) -> $..
201
202 ether_addr(B) when is_binary(B) ->
203 ether_addr(binary_to_list(B));
204 ether_addr(L) when is_list(L) ->
205 [ hd(io_lib:format("~.16B", [N])) || N <- L ].
206
207 tcp_flags(#tcp{cwr = CWR, ece = ECE, urg = URG, ack = ACK,
208 psh = PSH, rst = RST, syn = SYN, fin = FIN}) ->
209 [ atom_to_list(F) || {F,V} <-
210 [{cwr,CWR}, {ece,ECE}, {urg,URG}, {ack,ACK}, {psh,PSH}, {rst,RST}, {syn,SYN}, {fin,FIN}], V =:= 1 ].
211
212
213
Something went wrong with that request. Please try again.