diff --git a/apps/sdlan/src/net/arp_packet.erl b/apps/sdlan/src/net/arp_packet.erl index 0d5b639..7eb0f18 100644 --- a/apps/sdlan/src/net/arp_packet.erl +++ b/apps/sdlan/src/net/arp_packet.erl @@ -4,7 +4,7 @@ -module(arp_packet). -export([parse/1, marshal/1, is_broadcast_mac/1, arp_request/3, arp_response/3]). --export([opcode/1]). +-export([opcode/1, target_ip/1]). -define(ETHERNET, 16#0001). -define(IPV4, 16#0800). @@ -26,6 +26,20 @@ target_ip }). +-type arp_packet() :: #arp_packet{ + hardware_type :: integer(), + protocol_type :: integer(), + hardware_size :: integer(), + protocol_size :: integer(), + opcode :: atom() | integer(), + sender_mac :: binary(), + sender_ip :: integer(), + target_mac :: binary(), + target_ip :: integer() +}. + +-export_type([arp_packet/0]). + %%-------------------------------------------------------------------- %% Parsing %%-------------------------------------------------------------------- @@ -70,6 +84,10 @@ parse(Bin) when is_binary(Bin) -> opcode(#arp_packet{opcode = Opcode}) -> Opcode. +-spec target_ip(Arp_packet :: #arp_packet{}) -> TargetIp :: integer(). +target_ip(#arp_packet{target_ip = TargetIp}) -> + TargetIp. + %%-------------------------------------------------------------------- %% Marshal %%-------------------------------------------------------------------- diff --git a/apps/sdlan/src/sdlan_network.erl b/apps/sdlan/src/sdlan_network.erl index 01d199a..a0b8e6e 100644 --- a/apps/sdlan/src/sdlan_network.erl +++ b/apps/sdlan/src/sdlan_network.erl @@ -7,6 +7,8 @@ %%% Created : 27. 3月 2024 15:13 %%%------------------------------------------------------------------- -module(sdlan_network). +-feature(maybe_expr, enable). + -author("anlicheng"). -include("sdlan.hrl"). -include("sdlan_pb.hrl"). @@ -340,46 +342,34 @@ handle_cast({forward, Sock, SrcMac, DstMac, Packet}, State = #state{network_id = case sdlan_util:is_broadcast_mac(DstMac) orelse sdlan_util:is_multicast_mac(DstMac) of true -> %% 解析Packet是不是arp请求 - case layer_packet:parse(Packet) of - {ok, LayerPacket} -> - case layer_packet:packet_type(LayerPacket) of - arp -> - case arp_packet:parse(layer_packet:payload(LayerPacket)) of - {ok, ArpPacket} -> + case maybe_arp_request(Packet) of + {ok, ArpRequestPkt} -> + TargetIp = arp_packet:target_ip(ArpRequestPkt), + %% 通过ip查找到对应的Endpoint - case arp_packet:opcode(ArpPacket) of - request -> - %% TODO - Mac = <<>>, - Ip = 12, - ArpResponse = arp_packet:marshal(arp_packet:arp_response(ArpPacket, Mac, Ip)), + TargetMac = <<>>, + ArpResponse = arp_packet:marshal(arp_packet:arp_response(ArpRequestPkt, TargetMac, TargetIp)), + #endpoint{hole = #hole{peer = {NatIp, NatPort}}} = maps:get(SrcMac, UsedMap), + gen_udp:send(Sock, NatIp, NatPort, ArpResponse); - #endpoint{hole = #hole{peer = {NatIp, NatPort}}} = maps:get(SrcMac, UsedMap), - gen_udp:send(Sock, NatIp, NatPort, ArpResponse) - end; + error -> + PacketBytes = byte_size(Packet), + %% 消息广播 + maps:foreach(fun(Mac, #endpoint{hole = Hole}) -> + case {Mac =/= SrcMac, Hole} of + {true, #hole{peer = {NatIp, NatPort}}} -> + gen_udp:send(Sock, NatIp, NatPort, Packet); + _ -> + ok + end + end, UsedMap), - _ -> - ok - end - end - end, + %% client和stun之间必须有心跳机制保持nat映射可用,并且通过服务转发的udp包肯定可以到达对端的nat + lager:debug("[sdlan_network] broadcast data networkd_id: ~p, src_mac: ~p, dst_mac: ~p", + [NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac)]), - PacketBytes = byte_size(Packet), - %% 消息广播 - maps:foreach(fun(Mac, #endpoint{hole = Hole}) -> - case {Mac =/= SrcMac, Hole} of - {true, #hole{peer = {NatIp, NatPort}}} -> - gen_udp:send(Sock, NatIp, NatPort, Packet); - _ -> - ok - end - end, UsedMap), - - %% client和stun之间必须有心跳机制保持nat映射可用,并且通过服务转发的udp包肯定可以到达对端的nat - lager:debug("[sdlan_network] broadcast data networkd_id: ~p, src_mac: ~p, dst_mac: ~p", - [NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac)]), - - {noreply, State#state{forward_bytes = ForwardBytes + PacketBytes}}; + {noreply, State#state{forward_bytes = ForwardBytes + PacketBytes}} + end; false -> lager:debug("[sdlan_network] networkd_id: ~p, src_mac: ~p, dst_mac: ~p, forward discard 1", [NetworkId, sdlan_util:format_mac(SrcMac), sdlan_util:format_mac(DstMac)]), @@ -474,6 +464,19 @@ code_change(_OldVsn, State = #state{}, _Extra) -> %%% Internal functions %%%=================================================================== +-spec maybe_arp_request(Packet :: binary()) -> error | {ok, ArpPkt :: arp_packet:arp_packet()}. +maybe_arp_request(Packet) when is_binary(Packet) -> + maybe + {ok, LayerPacket} ?= layer_packet:parse(Packet), + arp ?= layer_packet:packet_type(LayerPacket), + {ok, ArpPacket} ?= arp_packet:parse(layer_packet:payload(LayerPacket)), + request ?= arp_packet:opcode(ArpPacket), + {ok, ArpPacket} + else + _ -> + error + end. + -spec limiting_check(ThrottleKey :: any()) -> pass | denied. limiting_check(ThrottleKey) -> case throttle:check(sdlan_network, ThrottleKey) of