Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 193 lines (164 sloc) 6.163 kb
0406018 Michael Santos 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
35 -export([
36 checksum/1,
37 checksum/3,
38 decapsulate/1,
39 makesum/1,
40 valid/1,
41 ether/1,
42 ether_addr/1,
43 icmp/1,
44 ipv4/1,
1fac0f7 Michael Santos Now compiler friendly, typo free!
authored
45 payload/1,
0406018 Michael Santos Add licensing and do cleanup. In other words, do stuff.
authored
46 tcp/1,
47 tcp_flags/1,
48 udp/1
49 ]).
50
51 -define(is_print(C), C >= $ , C =< $~).
52
53 decapsulate(P) ->
54 {EtherHdr, EtherData} = ether(P),
55 {IPHdr, IPData} = ipv4(EtherData),
56 Proto = proto(IPHdr#ipv4.p),
57 {Hdr, Payload} = ?MODULE:Proto(IPData),
58 [EtherHdr, IPHdr, Hdr, Payload].
59
60 proto(?IPPROTO_ICMP) -> icmp;
61 proto(?IPPROTO_TCP) -> tcp;
62 proto(?IPPROTO_UDP) -> udp.
63
64 ether(<<Dhost:6/bytes, Shost:6/bytes, Type:2/bytes, Packet/binary>>) ->
65 Len = byte_size(Packet) - 4,
66 <<Payload:Len/bytes, CRC:4/bytes>> = Packet,
67 {#ether{
68 dhost = Dhost, shost = Shost,
69 type = Type, crc = CRC
70 }, Payload}.
71
72 ipv4(
73 <<V:4, HL:4, ToS:8, Len:16,
74 Id:16, _RF:1, DF:1, MF:1,
75 Off:13, TTL:8, P:8, Sum:16,
76 SA1:8, SA2:8, SA3:8, SA4:8,
77 DA1:8, DA2:8, DA3:8, DA4:8,
78 Payload/binary>> = Raw
79 ) ->
80 <<Hdr:160/bitstring, _/binary>> = Raw,
81 Valid = case makesum(Hdr) of
82 0 -> true;
83 _ -> false
84 end,
85
86 {#ipv4{
87 valid = Valid,
88 v = V, hl = HL, tos = ToS, len = Len,
89 id = Id, df = DF, mf = MF,
90 off = Off, ttl = TTL, p = P, sum = Sum,
91 saddr = {SA1,SA2,SA3,SA4},
92 daddr = {DA1,DA2,DA3,DA4}
93 }, Payload}.
94
95 tcp(
96 <<SPort:16, DPort:16,
97 SeqNo:32,
98 AckNo:32,
99 Off:4, 0:4, CWR:1, ECE:1, URG:1, ACK:1,
100 PSH:1, RST:1, SYN:1, FIN:1, Win:16,
101 Sum:16, Urp:16,
102 Payload/binary>>
103 ) ->
104 {Opt, Msg} = tcp_options(tcp_offset(Off), Payload),
105 {#tcp{
106 sport = SPort, dport = DPort,
107 seqno = SeqNo,
108 ackno = AckNo,
109 off = Off, cwr = CWR, ece = ECE, urg = URG, ack = ACK,
110 psh = PSH, rst = RST, syn = SYN, fin = FIN, win = Win,
111 sum = Sum, urp = Urp,
112 opt = Opt
113 }, Msg}.
114
115 tcp_offset(N) when N > 5 -> (N - 5) * 4;
116 tcp_offset(_) -> 0.
117
118 % Appears some optimization is stripping the padding off the options
119 tcp_options(Offset, Payload) when Offset > byte_size(Payload) ->
120 {Payload, <<>>};
121 tcp_options(Offset, Payload) when Offset > 0 ->
122 <<Opt:Offset/bytes, Msg/binary>> = Payload,
123 {Opt, Msg};
124 tcp_options(_, Payload) ->
125 {<<>>, Payload}.
126
127 udp(<<SPort:16, DPort:16, ULen:16, Sum:16, Payload/binary>>) ->
128 {#udp{sport = SPort, dport = DPort, ulen = ULen, sum = Sum}, Payload}.
129
130 icmp(<<?ICMP_ECHO:8, Code:8, Checksum:16, Id:16, Sequence:16, Payload/binary>>) ->
131 {#icmp{
132 type = ?ICMP_ECHO, code = Code, checksum = Checksum, id = Id,
133 sequence = Sequence
134 }, Payload};
135
136 % PLACEHOLDER: gateway
137 icmp(<<?ICMP_DEST_UNREACH:8, Code:8, Checksum:16, Gateway:32, Payload/binary>>) ->
138 {#icmp{
139 type = ?ICMP_DEST_UNREACH, code = Code, checksum = Checksum, gateway = Gateway
140 }, Payload};
141
142 % PLACEHOLDER: frag
143 icmp(<<?ICMP_DEST_UNREACH:8, Code:8, Checksum:16, _Unused:16, MTU:16, Payload/binary>>) ->
144 {#icmp{
145 type = ?ICMP_DEST_UNREACH, code = Code, checksum = Checksum, mtu = MTU
146 }, Payload};
147
148 % Catch unknown types
149 icmp(<<Type:8, Code:8, Checksum:16, Un:32, Payload/binary>>) ->
150 {#icmp{
151 type = Type, code = Code, checksum = Checksum, un = Un
152 }, Payload}.
153
154 payload(Payload) ->
155 [ to_ascii(C) || <<C:8>> <= Payload ].
156
157 checksum(Hdr) ->
158 lists:foldl(fun compl/2, 0, [ W || <<W:16>> <= Hdr ]).
159
160 checksum(tcp, #ipv4{saddr = {S1,S2,S3,S4}, daddr = {D1,D2,D3,D4}, p = P},
161 <<Head:16/bytes, _:2/bytes, Trailer/binary>> = Payload) ->
162 Len = byte_size(Payload),
163 PseudoHdr = case Len rem 2 of
164 0 -> <<S1,S2,S3,S4,D1,D2,D3,D4,0:8,P,Len:16,Head/bytes,0:16,Trailer/bytes>>;
165 1 -> <<S1,S2,S3,S4,D1,D2,D3,D4,0:8,P,Len:16,Head/bytes,0:16,Trailer/bytes,0>>
166 end,
167 checksum(PseudoHdr).
168
169 makesum(Hdr) -> 16#FFFF - checksum(Hdr).
170
171 compl(N) when N =< 16#FFFF -> N;
172 compl(N) -> (N band 16#FFFF) + (N bsr 16).
173 compl(N,S) -> compl(N+S).
174
175 valid(16#FFFF) -> true;
176 valid(_) -> false.
177
178 to_ascii(C) when ?is_print(C) -> C;
179 to_ascii(_) -> $..
180
181 ether_addr(B) when is_binary(B) ->
182 ether_addr(binary_to_list(B));
183 ether_addr(L) when is_list(L) ->
184 [ hd(io_lib:format("~.16B", [N])) || N <- L ].
185
186 tcp_flags(#tcp{cwr = CWR, ece = ECE, urg = URG, ack = ACK,
187 psh = PSH, rst = RST, syn = SYN, fin = FIN}) ->
188 [ atom_to_list(F) || {F,V} <-
189 [{cwr,CWR}, {ece,ECE}, {urg,URG}, {ack,ACK}, {psh,PSH}, {rst,RST}, {syn,SYN}, {fin,FIN}], V =:= 1 ].
190
191
192
Something went wrong with that request. Please try again.