增加网络基础包的解析
This commit is contained in:
parent
8d94244689
commit
d7db914e88
153
apps/sdlan/src/network/arp_packet.erl
Normal file
153
apps/sdlan/src/network/arp_packet.erl
Normal file
@ -0,0 +1,153 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @doc ARP packet parser / builder (Ethernet + IPv4)
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(arp_packet).
|
||||
|
||||
-export([parse/1, marshal/1, is_broadcast_mac/1, arp_request/3, arp_response/3]).
|
||||
|
||||
-define(ARP_REQUEST, 1).
|
||||
-define(ARP_RESPONSE, 2).
|
||||
|
||||
-define(ETHERNET, 16#0001).
|
||||
-define(IPV4, 16#0800).
|
||||
|
||||
-define(BROADCAST_MAC, <<255,255,255,255,255,255>>).
|
||||
|
||||
-record(arp_packet, {
|
||||
hardware_type,
|
||||
protocol_type,
|
||||
hardware_size,
|
||||
protocol_size,
|
||||
opcode,
|
||||
sender_mac,
|
||||
sender_ip,
|
||||
target_mac,
|
||||
target_ip
|
||||
}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Parsing
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec parse(binary()) ->
|
||||
{ok, #arp_packet{}} | {error, invalid_length | invalid_opcode}.
|
||||
parse(Bin) when is_binary(Bin) ->
|
||||
case Bin of
|
||||
<<
|
||||
HType:16/big,
|
||||
PType:16/big,
|
||||
HLen:8,
|
||||
PLen:8,
|
||||
Op:16/big,
|
||||
SMac:6/binary,
|
||||
SIP:32/big,
|
||||
TMac:6/binary,
|
||||
TIP:32/big,
|
||||
_/binary
|
||||
>> ->
|
||||
case decode_opcode(Op) of
|
||||
{ok, Opcode} ->
|
||||
{ok, #arp_packet{
|
||||
hardware_type = HType,
|
||||
protocol_type = PType,
|
||||
hardware_size = HLen,
|
||||
protocol_size = PLen,
|
||||
opcode = Opcode,
|
||||
sender_mac = SMac,
|
||||
sender_ip = SIP,
|
||||
target_mac = TMac,
|
||||
target_ip = TIP
|
||||
}};
|
||||
error ->
|
||||
{error, invalid_opcode}
|
||||
end;
|
||||
_ ->
|
||||
{error, invalid_length}
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Marshal
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec marshal(#arp_packet{}) -> binary().
|
||||
marshal(#arp_packet{
|
||||
hardware_type = HType,
|
||||
protocol_type = PType,
|
||||
hardware_size = HLen,
|
||||
protocol_size = PLen,
|
||||
opcode = Opcode,
|
||||
sender_mac = SMac,
|
||||
sender_ip = SIP,
|
||||
target_mac = TMac,
|
||||
target_ip = TIP
|
||||
}) ->
|
||||
Op = encode_opcode(Opcode),
|
||||
<<
|
||||
HType:16/big,
|
||||
PType:16/big,
|
||||
HLen:8,
|
||||
PLen:8,
|
||||
Op:16/big,
|
||||
SMac/binary,
|
||||
SIP:32/big,
|
||||
TMac/binary,
|
||||
TIP:32/big
|
||||
>>.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Opcode helpers
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
decode_opcode(?ARP_REQUEST) -> {ok, request};
|
||||
decode_opcode(?ARP_RESPONSE) -> {ok, response};
|
||||
decode_opcode(_) -> error.
|
||||
|
||||
encode_opcode(request) -> ?ARP_REQUEST;
|
||||
encode_opcode(response) -> ?ARP_RESPONSE.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Utils
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec is_broadcast_mac(binary()) -> boolean().
|
||||
is_broadcast_mac(?BROADCAST_MAC) -> true;
|
||||
is_broadcast_mac(_) -> false.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Builders (对齐 Swift 扩展)
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec arp_request(integer(), binary(), integer()) -> #arp_packet{}.
|
||||
arp_request(SenderIP, SenderMAC, TargetIP) ->
|
||||
#arp_packet{
|
||||
hardware_type = ?ETHERNET,
|
||||
protocol_type = ?IPV4,
|
||||
hardware_size = 6,
|
||||
protocol_size = 4,
|
||||
opcode = request,
|
||||
sender_mac = SenderMAC,
|
||||
sender_ip = SenderIP,
|
||||
target_mac = <<0,0,0,0,0,0>>,
|
||||
target_ip = TargetIP
|
||||
}.
|
||||
|
||||
-spec arp_response(#arp_packet{}, binary(), integer()) -> #arp_packet{}.
|
||||
arp_response(#arp_packet{
|
||||
hardware_type = HType,
|
||||
protocol_type = PType,
|
||||
hardware_size = HLen,
|
||||
protocol_size = PLen,
|
||||
sender_mac = ReqMac,
|
||||
sender_ip = ReqIP
|
||||
}, Mac, IP) ->
|
||||
#arp_packet{
|
||||
hardware_type = HType,
|
||||
protocol_type = PType,
|
||||
hardware_size = HLen,
|
||||
protocol_size = PLen,
|
||||
opcode = response,
|
||||
sender_mac = Mac,
|
||||
sender_ip = IP,
|
||||
target_mac = ReqMac,
|
||||
target_ip = ReqIP
|
||||
}.
|
||||
88
apps/sdlan/src/network/layer_packet.erl
Normal file
88
apps/sdlan/src/network/layer_packet.erl
Normal file
@ -0,0 +1,88 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @doc Ethernet II layer packet parser
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(layer_packet).
|
||||
|
||||
-export([parse/1, marshal/1, is_broadcast_mac/1, is_multicast_mac/1]).
|
||||
|
||||
-define(ETH_ARP, 16#0806).
|
||||
-define(ETH_IPV4, 16#0800).
|
||||
-define(ETH_IPV6, 16#86DD).
|
||||
-define(ETH_VLAN, 16#8100).
|
||||
|
||||
-record(layer_packet, {
|
||||
dst_mac,
|
||||
src_mac,
|
||||
type,
|
||||
payload
|
||||
}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% API
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec parse(binary()) -> {ok, #layer_packet{}} | {error, invalid_length | invalid_type}.
|
||||
parse(Bin) when is_binary(Bin) ->
|
||||
case Bin of
|
||||
<<Dst:6/binary, Src:6/binary, Type:16, Payload/binary>> ->
|
||||
case decode_type(Type) of
|
||||
{ok, T} ->
|
||||
{ok, #layer_packet{
|
||||
dst_mac = Dst,
|
||||
src_mac = Src,
|
||||
type = T,
|
||||
payload = Payload
|
||||
}};
|
||||
error ->
|
||||
{error, invalid_type}
|
||||
end;
|
||||
_ ->
|
||||
{error, invalid_length}
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec marshal(#layer_packet{}) -> binary().
|
||||
marshal(#layer_packet{dst_mac = Dst, src_mac = Src, type = Type, payload = Payload}) ->
|
||||
TypeBin = encode_type(Type),
|
||||
<<Dst/binary, Src/binary, TypeBin:16, Payload/binary>>.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% EtherType mapping
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
decode_type(?ETH_ARP) ->
|
||||
{ok, arp};
|
||||
decode_type(?ETH_IPV4) ->
|
||||
{ok, ipv4};
|
||||
decode_type(?ETH_IPV6) ->
|
||||
{ok, ipv6};
|
||||
decode_type(?ETH_VLAN) ->
|
||||
{ok, tagged_frame};
|
||||
decode_type(_) ->
|
||||
error.
|
||||
|
||||
encode_type(arp) ->
|
||||
?ETH_ARP;
|
||||
encode_type(ipv4) ->
|
||||
?ETH_IPV4;
|
||||
encode_type(ipv6) ->
|
||||
?ETH_IPV6;
|
||||
encode_type(tagged_frame) ->
|
||||
?ETH_VLAN.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MAC helpers (对齐 Swift MacAddress)
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec is_broadcast_mac(binary()) -> boolean().
|
||||
is_broadcast_mac(<<255,255,255,255,255,255>>) ->
|
||||
true;
|
||||
is_broadcast_mac(_) ->
|
||||
false.
|
||||
|
||||
-spec is_multicast_mac(binary()) -> boolean().
|
||||
is_multicast_mac(<<1,0,94,_/binary>>) ->
|
||||
true;
|
||||
is_multicast_mac(_) ->
|
||||
false.
|
||||
Loading…
x
Reference in New Issue
Block a user