diff --git a/lib/packet_info.ex b/lib/packet_info.ex deleted file mode 100644 index 2d27333..0000000 --- a/lib/packet_info.ex +++ /dev/null @@ -1,281 +0,0 @@ -defmodule PacketInfo do - @moduledoc """ - Packet parser based on supported match fields in OXM and NXM - """ - - alias Tres.MacAddress - - @eth_p_ip 0x0800 - @eth_p_arp 0x0806 - @eth_p_rarp 0x8035 - @eth_p_ipv6 0x86DD - @eth_p_802_1q 0x8100 - @eth_p_802_1qinq 0x88A8 - @eth_p_mpls_uni 0x8847 - @eth_p_mpls_multi 0x8848 - - @ipproto_icmp 1 - @ipproto_tcp 6 - @ipproto_udp 17 - @ipproto_icmpv6 58 - @ipproto_sctp 132 - - @arpop_request 1 - @arpop_reply 2 - @arpop_inrequest 8 - @arpop_inreply 9 - @arpop_nak 10 - - defstruct [ - # L2 - :eth_dst, - :eth_src, - :eth_type, - # VLAN - :vlan_tci, - # L2.5(MPLS) - :mpls_label, - :mpls_tc, - :mpls_bos, - :mpls_ttl, - # L2.5(PBB) - :pbb_isid, - # L3(IP) - :ip_tos, - :ip_ttl, - :ip_proto, - :ipv4_src, - :ipv4_dst, - :ipv6_src, - :ipv6_dst, - :ipv6_flabel, - :ipv6_exthdr, - # L3(ARP) - :arp_op, - :arp_sha, - :arp_spa, - :arp_tha, - :arp_tpa, - # L3(ipv6 ND) - :ipv6_nd_target, - :ipv6_nd_sll, - :ipv6_nd_tll, - # L4(TCP) - :tcp_src, - :tcp_dst, - :tcp_flags, - # L4(UDP) - :udp_src, - :udp_dst, - # L4(SCTP) - :sctp_src, - :sctp_dst, - # L4(ICMPv4) - :icmpv4_type, - :icmpv4_code, - # L4(ICMPv6) - :icmpv6_type, - :icmpv6_code - ] - - @type t :: %PacketInfo{ - eth_dst: String.t() | nil, - eth_src: String.t() | nil, - eth_type: - :ipv4 - | :ipv6 - | :arp - | :rarp - | :"802.1q" - | :"802.1qinq" - | :lldp - | :mpls - | 0..65535 - | nil, - mpls_label: 0..0xFFFFF | nil, - mpls_tc: 0..7, - mpls_bos: boolean() | nil, - mpls_ttl: 0..255 | nil, - pbb_isid: 0..0xFFFFFF | nil, - ip_tos: 0..255 | nil, - ip_ttl: 0..255 | nil, - ip_proto: 0..255 | :tcp | :udp | :icmp | :sctp | nil, - ipv4_src: :inet.ip4_address() | nil, - ipv4_dst: :inet.ip4_address() | nil, - ipv6_src: :inet.ip6_address() | nil, - ipv6_dst: :inet.ip6_address() | nil, - ipv6_flabel: 0..0xFFFFF, - ipv6_exthdr: - [:nonext | :esp | :auth | :dest | :frag | :router | :hop | :unrep | :unseq] | nil, - arp_op: :request | :reply | :inrequest | :inreply | nil, - arp_sha: String.t() | nil, - arp_spa: :inet.ip4_address() | nil, - arp_tha: String.t() | nil, - arp_tpa: :inet.ip4_address() | nil, - ipv6_nd_target: :inet.ip6_address() | nil, - ipv6_nd_sll: String.t() | nil, - ipv6_nd_tll: String.t() | nil, - tcp_src: 0..0xFFFF | nil, - tcp_dst: 0..0xFFFF | nil, - tcp_flags: [:fin | :syn | :rst | :psh | :ack | :urg | :ece | :cwr | :ns] | nil, - udp_src: 0..0xFFFF | nil, - udp_dst: 0..0xFFFF | nil, - sctp_src: 0..0xFFFF | nil, - sctp_dst: 0..0xFFFF | nil, - icmpv4_type: 0..0xFF | nil, - icmpv4_code: 0..0xFF | nil, - icmpv6_type: 0..0xFF | nil, - icmpv6_code: 0..0xFF | nil - } - - @spec decapsulate(packet :: binary()) :: PacketInfo.t() - def decapsulate(<>) do - packet_info = %PacketInfo{ - eth_dst: MacAddress.bin_to_str(daddr), - eth_src: MacAddress.bin_to_str(saddr), - eth_type: eth_type(eth_type) - } - - decapsulate_next({eth_type(eth_type), rest}, packet_info) - end - - # private functions - - defp decapsulate_next({:ipv4, <<_::4, hl::4, _::bytes>> = packet}, pi) - when byte_size(packet) >= 20 do - 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, - sa1, sa2, sa3, sa4, da1, da2, da3, da4, _opt::size(opt_len)-bytes, rest::bytes>> = packet - - decapsulate_next( - {ip_proto(proto), rest}, - %{ - pi - | ip_tos: tos, - ip_proto: ip_proto(proto), - ip_ttl: ttl, - ipv4_src: {sa1, sa2, sa3, sa4}, - ipv4_dst: {da1, da2, da3, da4} - } - ) - end - - defp decapsulate_next({arp, packet}, pi) - when (arp == :arp or arp == :rarp) and byte_size(packet) >= 28 do - <<_::6-bytes, op::16, sha::6-bytes, sa1, sa2, sa3, sa4, tha::6-bytes, da1, da2, da3, da4, - _::bytes>> = packet - - %{ - pi - | arp_op: arp_op(op), - arp_sha: MacAddress.bin_to_str(sha), - arp_spa: {sa1, sa2, sa3, sa4}, - arp_tha: MacAddress.bin_to_str(tha), - arp_tpa: {da1, da2, da3, da4} - } - end - - defp decapsulate_next({:ipv6, packet}, pi) when byte_size(packet) >= 40 do - <<6::4, class::8, flow::20, _len::16, next::8, hop::8, sa1::16, sa2::16, sa3::16, sa4::16, - sa5::16, sa6::16, sa7::16, sa8::16, da1::16, da2::16, da3::16, da4::16, da5::16, da6::16, - da7::16, da8::16, rest::binary>> = packet - - decapsulate_next( - {ip_proto(next), rest}, - %{ - pi - | ipv6_src: {sa1, sa2, sa3, sa4, sa5, sa6, sa7, sa8}, - ipv6_dst: {da1, da2, da3, da4, da5, da6, da7, da8}, - ipv6_flabel: flow, - ip_tos: class, - ip_proto: ip_proto(next), - ip_ttl: hop - } - ) - end - - defp decapsulate_next({vlan, <>}, pi) - when vlan == :"802.1q" or vlan == :"802.1qinq", - do: - decapsulate_next( - {eth_type(type), rest}, - %{pi | vlan_tci: tci, eth_type: eth_type(type)} - ) - - defp decapsulate_next({:mpls, packet}, pi) do - <> = packet - <> = rest - - next = - case next_int do - 4 -> :ipv4 - 6 -> :ipv6 - end - - decapsulate_next( - {next, rest}, - %{pi | mpls_label: label, mpls_tc: tc, mpls_ttl: ttl, mpls_bos: bos} - ) - end - - defp decapsulate_next({:icmpv4, <>}, pi) do - %{pi | icmpv4_type: type, icmpv4_code: code} - end - - defp decapsulate_next({:tcp, packet}, pi) do - <> = packet - - tcp_flags = Openflow.Enums.tcp_flags_to_atom(flags_int) - %{pi | tcp_src: sport, tcp_dst: dport, tcp_flags: tcp_flags} - end - - defp decapsulate_next({:udp, <>}, pi) do - %{pi | udp_src: sport, udp_dst: dport} - end - - defp decapsulate_next({:sctp, <>}, pi) do - %{pi | sctp_src: sport, sctp_dst: dport} - end - - @spec eth_type(non_neg_integer()) :: atom() | 0..0xFFFF - defp eth_type(@eth_p_ip), do: :ipv4 - - defp eth_type(@eth_p_arp), do: :arp - - defp eth_type(@eth_p_rarp), do: :rarp - - defp eth_type(@eth_p_ipv6), do: :ipv6 - - defp eth_type(@eth_p_802_1q), do: :"802.1q" - - defp eth_type(@eth_p_802_1qinq), do: :"802.1qinq" - - defp eth_type(type) when type == @eth_p_mpls_uni or type == @eth_p_mpls_multi, do: :mpls - - defp eth_type(type), do: type - - @spec arp_op(non_neg_integer()) :: atom() | 0..0xFFFF - defp arp_op(@arpop_request), do: :request - - defp arp_op(@arpop_reply), do: :reply - - defp arp_op(@arpop_inrequest), do: :inrequest - - defp arp_op(@arpop_inreply), do: :inreply - - defp arp_op(@arpop_nak), do: :nak - - @spec ip_proto(non_neg_integer()) :: atom() :: 0..0xFF - defp ip_proto(@ipproto_icmp), do: :icmpv4 - - defp ip_proto(@ipproto_tcp), do: :tcp - - defp ip_proto(@ipproto_udp), do: :udp - - defp ip_proto(@ipproto_icmpv6), do: :icmpv6 - - defp ip_proto(@ipproto_sctp), do: :sctp - - defp ip_proto(ipproto), do: ipproto -end