formatted
This commit is contained in:
parent
0e4cd32027
commit
97b957742f
3 changed files with 140 additions and 107 deletions
|
|
@ -10,7 +10,7 @@ defmodule PacketInfo do
|
||||||
@eth_p_rarp 0x8035
|
@eth_p_rarp 0x8035
|
||||||
@eth_p_ipv6 0x86DD
|
@eth_p_ipv6 0x86DD
|
||||||
@eth_p_802_1q 0x8100
|
@eth_p_802_1q 0x8100
|
||||||
@eth_p_802_1qinq 0x88a8
|
@eth_p_802_1qinq 0x88A8
|
||||||
@eth_p_mpls_uni 0x8847
|
@eth_p_mpls_uni 0x8847
|
||||||
@eth_p_mpls_multi 0x8848
|
@eth_p_mpls_multi 0x8848
|
||||||
|
|
||||||
|
|
@ -28,41 +28,75 @@ defmodule PacketInfo do
|
||||||
|
|
||||||
defstruct [
|
defstruct [
|
||||||
# L2
|
# L2
|
||||||
:eth_dst, :eth_src, :eth_type,
|
:eth_dst,
|
||||||
|
:eth_src,
|
||||||
|
:eth_type,
|
||||||
# VLAN
|
# VLAN
|
||||||
:vlan_tci,
|
:vlan_tci,
|
||||||
# L2.5(MPLS)
|
# L2.5(MPLS)
|
||||||
:mpls_label, :mpls_tc, :mpls_bos, :mpls_ttl,
|
:mpls_label,
|
||||||
|
:mpls_tc,
|
||||||
|
:mpls_bos,
|
||||||
|
:mpls_ttl,
|
||||||
# L2.5(PBB)
|
# L2.5(PBB)
|
||||||
:pbb_isid,
|
:pbb_isid,
|
||||||
# L3(IP)
|
# L3(IP)
|
||||||
:ip_tos, :ip_ttl, :ip_proto, :ipv4_src, :ipv4_dst,
|
:ip_tos,
|
||||||
:ipv6_src, :ipv6_dst, :ipv6_flabel, :ipv6_exthdr,
|
:ip_ttl,
|
||||||
|
:ip_proto,
|
||||||
|
:ipv4_src,
|
||||||
|
:ipv4_dst,
|
||||||
|
:ipv6_src,
|
||||||
|
:ipv6_dst,
|
||||||
|
:ipv6_flabel,
|
||||||
|
:ipv6_exthdr,
|
||||||
# L3(ARP)
|
# L3(ARP)
|
||||||
:arp_op, :arp_sha, :arp_spa, :arp_tha, :arp_tpa,
|
:arp_op,
|
||||||
|
:arp_sha,
|
||||||
|
:arp_spa,
|
||||||
|
:arp_tha,
|
||||||
|
:arp_tpa,
|
||||||
# L3(ipv6 ND)
|
# L3(ipv6 ND)
|
||||||
:ipv6_nd_target, :ipv6_nd_sll, :ipv6_nd_tll,
|
:ipv6_nd_target,
|
||||||
|
:ipv6_nd_sll,
|
||||||
|
:ipv6_nd_tll,
|
||||||
# L4(TCP)
|
# L4(TCP)
|
||||||
:tcp_src, :tcp_dst, :tcp_flags,
|
:tcp_src,
|
||||||
|
:tcp_dst,
|
||||||
|
:tcp_flags,
|
||||||
# L4(UDP)
|
# L4(UDP)
|
||||||
:udp_src, :udp_dst,
|
:udp_src,
|
||||||
|
:udp_dst,
|
||||||
# L4(SCTP)
|
# L4(SCTP)
|
||||||
:sctp_src, :sctp_dst,
|
:sctp_src,
|
||||||
|
:sctp_dst,
|
||||||
# L4(ICMPv4)
|
# L4(ICMPv4)
|
||||||
:icmpv4_type, :icmpv4_code,
|
:icmpv4_type,
|
||||||
|
:icmpv4_code,
|
||||||
# L4(ICMPv6)
|
# L4(ICMPv6)
|
||||||
:icmpv6_type, :icmpv6_code
|
:icmpv6_type,
|
||||||
|
:icmpv6_code
|
||||||
]
|
]
|
||||||
|
|
||||||
@type t :: %PacketInfo{
|
@type t :: %PacketInfo{
|
||||||
eth_dst: String.t() | nil,
|
eth_dst: String.t() | nil,
|
||||||
eth_src: String.t() | nil,
|
eth_src: String.t() | nil,
|
||||||
eth_type: :ipv4 | :ipv6 | :arp | :rarp | :"802.1q" | :"802.1qinq" | :lldp | :mpls | 0..65535 | nil,
|
eth_type:
|
||||||
mpls_label: 0..0xfffff | nil,
|
:ipv4
|
||||||
|
| :ipv6
|
||||||
|
| :arp
|
||||||
|
| :rarp
|
||||||
|
| :"802.1q"
|
||||||
|
| :"802.1qinq"
|
||||||
|
| :lldp
|
||||||
|
| :mpls
|
||||||
|
| 0..65535
|
||||||
|
| nil,
|
||||||
|
mpls_label: 0..0xFFFFF | nil,
|
||||||
mpls_tc: 0..7,
|
mpls_tc: 0..7,
|
||||||
mpls_bos: boolean() | nil,
|
mpls_bos: boolean() | nil,
|
||||||
mpls_ttl: 0..255 | nil,
|
mpls_ttl: 0..255 | nil,
|
||||||
pbb_isid: 0..0xffffff | nil,
|
pbb_isid: 0..0xFFFFFF | nil,
|
||||||
ip_tos: 0..255 | nil,
|
ip_tos: 0..255 | nil,
|
||||||
ip_ttl: 0..255 | nil,
|
ip_ttl: 0..255 | nil,
|
||||||
ip_proto: 0..255 | :tcp | :udp | :icmp | :sctp | nil,
|
ip_proto: 0..255 | :tcp | :udp | :icmp | :sctp | nil,
|
||||||
|
|
@ -70,8 +104,9 @@ defmodule PacketInfo do
|
||||||
ipv4_dst: :inet.ip4_address() | nil,
|
ipv4_dst: :inet.ip4_address() | nil,
|
||||||
ipv6_src: :inet.ip6_address() | nil,
|
ipv6_src: :inet.ip6_address() | nil,
|
||||||
ipv6_dst: :inet.ip6_address() | nil,
|
ipv6_dst: :inet.ip6_address() | nil,
|
||||||
ipv6_flabel: 0..0xfffff,
|
ipv6_flabel: 0..0xFFFFF,
|
||||||
ipv6_exthdr: [:nonext | :esp | :auth | :dest | :frag | :router | :hop | :unrep | :unseq] | nil,
|
ipv6_exthdr:
|
||||||
|
[:nonext | :esp | :auth | :dest | :frag | :router | :hop | :unrep | :unseq] | nil,
|
||||||
arp_op: :request | :reply | :inrequest | :inreply | nil,
|
arp_op: :request | :reply | :inrequest | :inreply | nil,
|
||||||
arp_sha: String.t() | nil,
|
arp_sha: String.t() | nil,
|
||||||
arp_spa: :inet.ip4_address() | nil,
|
arp_spa: :inet.ip4_address() | nil,
|
||||||
|
|
@ -80,23 +115,22 @@ defmodule PacketInfo do
|
||||||
ipv6_nd_target: :inet.ip6_address() | nil,
|
ipv6_nd_target: :inet.ip6_address() | nil,
|
||||||
ipv6_nd_sll: String.t() | nil,
|
ipv6_nd_sll: String.t() | nil,
|
||||||
ipv6_nd_tll: String.t() | nil,
|
ipv6_nd_tll: String.t() | nil,
|
||||||
tcp_src: 0..0xffff | nil,
|
tcp_src: 0..0xFFFF | nil,
|
||||||
tcp_dst: 0..0xffff | nil,
|
tcp_dst: 0..0xFFFF | nil,
|
||||||
tcp_flags: [:fin | :syn | :rst | :psh | :ack | :urg | :ece | :cwr | :ns] | nil,
|
tcp_flags: [:fin | :syn | :rst | :psh | :ack | :urg | :ece | :cwr | :ns] | nil,
|
||||||
udp_src: 0..0xffff | nil,
|
udp_src: 0..0xFFFF | nil,
|
||||||
udp_dst: 0..0xffff | nil,
|
udp_dst: 0..0xFFFF | nil,
|
||||||
sctp_src: 0..0xffff | nil,
|
sctp_src: 0..0xFFFF | nil,
|
||||||
sctp_dst: 0..0xffff | nil,
|
sctp_dst: 0..0xFFFF | nil,
|
||||||
icmpv4_type: 0..0xff | nil,
|
icmpv4_type: 0..0xFF | nil,
|
||||||
icmpv4_code: 0..0xff | nil,
|
icmpv4_code: 0..0xFF | nil,
|
||||||
icmpv6_type: 0..0xff | nil,
|
icmpv6_type: 0..0xFF | nil,
|
||||||
icmpv6_code: 0..0xff | nil
|
icmpv6_code: 0..0xFF | nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@spec decapsulate(packet :: binary()) :: PacketInfo.t()
|
@spec decapsulate(packet :: binary()) :: PacketInfo.t()
|
||||||
def decapsulate(<<daddr::6-bytes, saddr::6-bytes, eth_type::16, rest::bytes>>) do
|
def decapsulate(<<daddr::6-bytes, saddr::6-bytes, eth_type::16, rest::bytes>>) do
|
||||||
packet_info =
|
packet_info = %PacketInfo{
|
||||||
%PacketInfo{
|
|
||||||
eth_dst: MacAddress.bin_to_str(daddr),
|
eth_dst: MacAddress.bin_to_str(daddr),
|
||||||
eth_src: MacAddress.bin_to_str(saddr),
|
eth_src: MacAddress.bin_to_str(saddr),
|
||||||
eth_type: eth_type(eth_type)
|
eth_type: eth_type(eth_type)
|
||||||
|
|
@ -110,16 +144,14 @@ defmodule PacketInfo do
|
||||||
defp decapsulate_next({:ipv4, <<_::4, hl::4, _::bytes>> = packet}, pi)
|
defp decapsulate_next({:ipv4, <<_::4, hl::4, _::bytes>> = packet}, pi)
|
||||||
when byte_size(packet) >= 20 do
|
when byte_size(packet) >= 20 do
|
||||||
opt_len = (hl - 5) * 4
|
opt_len = (hl - 5) * 4
|
||||||
<<4::4, _hl::4, tos::8, _len::16, _id::16, _frag::3,
|
|
||||||
_offset::13, ttl::8, proto::8, _sum::16,
|
<<4::4, _hl::4, tos::8, _len::16, _id::16, _frag::3, _offset::13, ttl::8, proto::8, _sum::16,
|
||||||
sa1, sa2, sa3, sa4,
|
sa1, sa2, sa3, sa4, da1, da2, da3, da4, _opt::size(opt_len)-bytes, rest::bytes>> = packet
|
||||||
da1, da2, da3, da4,
|
|
||||||
_opt::size(opt_len)-bytes,
|
|
||||||
rest::bytes>> = packet
|
|
||||||
|
|
||||||
decapsulate_next(
|
decapsulate_next(
|
||||||
{ip_proto(proto), rest},
|
{ip_proto(proto), rest},
|
||||||
%{pi
|
%{
|
||||||
|
pi
|
||||||
| ip_tos: tos,
|
| ip_tos: tos,
|
||||||
ip_proto: ip_proto(proto),
|
ip_proto: ip_proto(proto),
|
||||||
ip_ttl: ttl,
|
ip_ttl: ttl,
|
||||||
|
|
@ -131,12 +163,11 @@ defmodule PacketInfo do
|
||||||
|
|
||||||
defp decapsulate_next({arp, packet}, pi)
|
defp decapsulate_next({arp, packet}, pi)
|
||||||
when (arp == :arp or arp == :rarp) and byte_size(packet) >= 28 do
|
when (arp == :arp or arp == :rarp) and byte_size(packet) >= 28 do
|
||||||
<<_::6-bytes, op::16,
|
<<_::6-bytes, op::16, sha::6-bytes, sa1, sa2, sa3, sa4, tha::6-bytes, da1, da2, da3, da4,
|
||||||
sha::6-bytes, sa1, sa2, sa3, sa4,
|
|
||||||
tha::6-bytes, da1, da2, da3, da4,
|
|
||||||
_::bytes>> = packet
|
_::bytes>> = packet
|
||||||
|
|
||||||
%{pi
|
%{
|
||||||
|
pi
|
||||||
| arp_op: arp_op(op),
|
| arp_op: arp_op(op),
|
||||||
arp_sha: MacAddress.bin_to_str(sha),
|
arp_sha: MacAddress.bin_to_str(sha),
|
||||||
arp_spa: {sa1, sa2, sa3, sa4},
|
arp_spa: {sa1, sa2, sa3, sa4},
|
||||||
|
|
@ -146,27 +177,28 @@ defmodule PacketInfo do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp decapsulate_next({:ipv6, packet}, pi) when byte_size(packet) >= 40 do
|
defp decapsulate_next({:ipv6, packet}, pi) when byte_size(packet) >= 40 do
|
||||||
<<6::4, class::8, flow::20,
|
<<6::4, class::8, flow::20, _len::16, next::8, hop::8, sa1::16, sa2::16, sa3::16, sa4::16,
|
||||||
_len::16, next::8, hop::8,
|
sa5::16, sa6::16, sa7::16, sa8::16, da1::16, da2::16, da3::16, da4::16, da5::16, da6::16,
|
||||||
sa1::16, sa2::16, sa3::16, sa4::16, sa5::16, sa6::16, sa7::16, sa8::16,
|
da7::16, da8::16, rest::binary>> = packet
|
||||||
da1::16, da2::16, da3::16, da4::16, da5::16, da6::16, da7::16, da8::16,
|
|
||||||
rest::binary>> = packet
|
|
||||||
|
|
||||||
decapsulate_next(
|
decapsulate_next(
|
||||||
{ip_proto(next), rest},
|
{ip_proto(next), rest},
|
||||||
%{pi
|
%{
|
||||||
|
pi
|
||||||
| ipv6_src: {sa1, sa2, sa3, sa4, sa5, sa6, sa7, sa8},
|
| ipv6_src: {sa1, sa2, sa3, sa4, sa5, sa6, sa7, sa8},
|
||||||
ipv6_dst: {da1, da2, da3, da4, da5, da6, da7, da8},
|
ipv6_dst: {da1, da2, da3, da4, da5, da6, da7, da8},
|
||||||
ipv6_flabel: flow,
|
ipv6_flabel: flow,
|
||||||
ip_tos: class,
|
ip_tos: class,
|
||||||
ip_proto: ip_proto(next),
|
ip_proto: ip_proto(next),
|
||||||
ip_ttl: hop,
|
ip_ttl: hop
|
||||||
})
|
}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp decapsulate_next({vlan, <<tci::12, type::16, rest::bytes>>}, pi)
|
defp decapsulate_next({vlan, <<tci::12, type::16, rest::bytes>>}, pi)
|
||||||
when vlan == :"802.1q" or vlan == :"802.1qinq",
|
when vlan == :"802.1q" or vlan == :"802.1qinq",
|
||||||
do: decapsulate_next(
|
do:
|
||||||
|
decapsulate_next(
|
||||||
{eth_type(type), rest},
|
{eth_type(type), rest},
|
||||||
%{pi | vlan_tci: tci, eth_type: eth_type(type)}
|
%{pi | vlan_tci: tci, eth_type: eth_type(type)}
|
||||||
)
|
)
|
||||||
|
|
@ -192,8 +224,7 @@ defmodule PacketInfo do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp decapsulate_next({:tcp, packet}, pi) do
|
defp decapsulate_next({:tcp, packet}, pi) do
|
||||||
<<sport::16, dport::16, _seq::32,
|
<<sport::16, dport::16, _seq::32, _ack::32, _off::4, 0::3, flags_int::9, _::bytes>> = packet
|
||||||
_ack::32, _off::4, 0::3, flags_int::9, _::bytes>> = packet
|
|
||||||
|
|
||||||
tcp_flags = Openflow.Enums.tcp_flags_to_atom(flags_int)
|
tcp_flags = Openflow.Enums.tcp_flags_to_atom(flags_int)
|
||||||
%{pi | tcp_src: sport, tcp_dst: dport, tcp_flags: tcp_flags}
|
%{pi | tcp_src: sport, tcp_dst: dport, tcp_flags: tcp_flags}
|
||||||
|
|
@ -207,7 +238,7 @@ defmodule PacketInfo do
|
||||||
%{pi | sctp_src: sport, sctp_dst: dport}
|
%{pi | sctp_src: sport, sctp_dst: dport}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec eth_type(non_neg_integer()) :: atom() | 0..0xffff
|
@spec eth_type(non_neg_integer()) :: atom() | 0..0xFFFF
|
||||||
defp eth_type(@eth_p_ip), do: :ipv4
|
defp eth_type(@eth_p_ip), do: :ipv4
|
||||||
|
|
||||||
defp eth_type(@eth_p_arp), do: :arp
|
defp eth_type(@eth_p_arp), do: :arp
|
||||||
|
|
@ -224,7 +255,7 @@ defmodule PacketInfo do
|
||||||
|
|
||||||
defp eth_type(type), do: type
|
defp eth_type(type), do: type
|
||||||
|
|
||||||
@spec arp_op(non_neg_integer()) :: atom() | 0..0xffff
|
@spec arp_op(non_neg_integer()) :: atom() | 0..0xFFFF
|
||||||
defp arp_op(@arpop_request), do: :request
|
defp arp_op(@arpop_request), do: :request
|
||||||
|
|
||||||
defp arp_op(@arpop_reply), do: :reply
|
defp arp_op(@arpop_reply), do: :reply
|
||||||
|
|
@ -235,7 +266,7 @@ defmodule PacketInfo do
|
||||||
|
|
||||||
defp arp_op(@arpop_nak), do: :nak
|
defp arp_op(@arpop_nak), do: :nak
|
||||||
|
|
||||||
@spec ip_proto(non_neg_integer()) :: atom() :: 0..0xff
|
@spec ip_proto(non_neg_integer()) :: atom() :: 0..0xFF
|
||||||
defp ip_proto(@ipproto_icmp), do: :icmpv4
|
defp ip_proto(@ipproto_icmp), do: :icmpv4
|
||||||
|
|
||||||
defp ip_proto(@ipproto_tcp), do: :tcp
|
defp ip_proto(@ipproto_tcp), do: :tcp
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,10 @@ defmodule Tres.IPv4Address do
|
||||||
[^addr] ->
|
[^addr] ->
|
||||||
{:ok, ipaddr} = addr |> to_charlist |> :inet.parse_address()
|
{:ok, ipaddr} = addr |> to_charlist |> :inet.parse_address()
|
||||||
{ipaddr, {255, 255, 255, 255}}
|
{ipaddr, {255, 255, 255, 255}}
|
||||||
|
|
||||||
[netaddr, cidr_str] ->
|
[netaddr, cidr_str] ->
|
||||||
cidr = String.to_integer(cidr_str)
|
cidr = String.to_integer(cidr_str)
|
||||||
mask = (0xFFFFFFFF >>> (32 - cidr)) <<< (32 - cidr)
|
mask = 0xFFFFFFFF >>> (32 - cidr) <<< (32 - cidr)
|
||||||
<<m1, m2, m3, m4>> = <<mask::32>>
|
<<m1, m2, m3, m4>> = <<mask::32>>
|
||||||
{:ok, ipaddr} = netaddr |> to_charlist |> :inet.parse_address()
|
{:ok, ipaddr} = netaddr |> to_charlist |> :inet.parse_address()
|
||||||
{ipaddr, {m1, m2, m3, m4}}
|
{ipaddr, {m1, m2, m3, m4}}
|
||||||
|
|
@ -38,7 +39,7 @@ defmodule Tres.IPv4Address do
|
||||||
def to_network({{a1, a2, a3, a4}, {m1, m2, m3, m4}}) do
|
def to_network({{a1, a2, a3, a4}, {m1, m2, m3, m4}}) do
|
||||||
addr_int = :binary.decode_unsigned(<<a1, a2, a3, a4>>, :big)
|
addr_int = :binary.decode_unsigned(<<a1, a2, a3, a4>>, :big)
|
||||||
mask_int = :binary.decode_unsigned(<<m1, m2, m3, m4>>, :big)
|
mask_int = :binary.decode_unsigned(<<m1, m2, m3, m4>>, :big)
|
||||||
<<n1, n2, n3, n4>> = <<(addr_int &&& mask_int)::32>>
|
<<n1, n2, n3, n4>> = <<addr_int &&& mask_int::32>>
|
||||||
{n1, n2, n3, n4}
|
{n1, n2, n3, n4}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ defmodule Tres.MacAddress do
|
||||||
|> check_format()
|
|> check_format()
|
||||||
|> to_a()
|
|> to_a()
|
||||||
|> Enum.at(0)
|
|> Enum.at(0)
|
||||||
|> Kernel.==(0xff)
|
|> Kernel.==(0xFF)
|
||||||
rescue
|
rescue
|
||||||
_e in ArgumentError ->
|
_e in ArgumentError ->
|
||||||
{:error, :invalid_format}
|
{:error, :invalid_format}
|
||||||
|
|
@ -63,6 +63,7 @@ defmodule Tres.MacAddress do
|
||||||
# private functions
|
# private functions
|
||||||
|
|
||||||
defp to_a(<<>>, acc), do: Enum.reverse(acc)
|
defp to_a(<<>>, acc), do: Enum.reverse(acc)
|
||||||
|
|
||||||
defp to_a(<<octet::2-bytes, rest::bytes>>, acc) do
|
defp to_a(<<octet::2-bytes, rest::bytes>>, acc) do
|
||||||
to_a(rest, [String.to_integer(octet, 16) | acc])
|
to_a(rest, [String.to_integer(octet, 16) | acc])
|
||||||
end
|
end
|
||||||
|
|
@ -81,6 +82,6 @@ defmodule Tres.MacAddress do
|
||||||
defp check_format(mac) when is_binary(mac) do
|
defp check_format(mac) when is_binary(mac) do
|
||||||
if String.match?(mac, @mac_addr_pattern),
|
if String.match?(mac, @mac_addr_pattern),
|
||||||
do: mac,
|
do: mac,
|
||||||
else: raise ArgumentError, message: "MAC address should be 12 letters hex string format"
|
else: raise(ArgumentError, message: "MAC address should be 12 letters hex string format")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue