diff --git a/apps/sdlan/src/network/arp_packet.erl b/apps/sdlan/src/net/arp_packet.erl similarity index 97% rename from apps/sdlan/src/network/arp_packet.erl rename to apps/sdlan/src/net/arp_packet.erl index 0a22300..0d5b639 100644 --- a/apps/sdlan/src/network/arp_packet.erl +++ b/apps/sdlan/src/net/arp_packet.erl @@ -4,13 +4,14 @@ -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). +-export([opcode/1]). -define(ETHERNET, 16#0001). -define(IPV4, 16#0800). +-define(ARP_REQUEST, 1). +-define(ARP_RESPONSE, 2). + -define(BROADCAST_MAC, <<255,255,255,255,255,255>>). -record(arp_packet, { @@ -65,6 +66,10 @@ parse(Bin) when is_binary(Bin) -> {error, invalid_length} end. +-spec opcode(Arp_packet :: #arp_packet{}) -> atom(). +opcode(#arp_packet{opcode = Opcode}) -> + Opcode. + %%-------------------------------------------------------------------- %% Marshal %%-------------------------------------------------------------------- diff --git a/apps/sdlan/src/network/layer_packet.erl b/apps/sdlan/src/net/layer_packet.erl similarity index 90% rename from apps/sdlan/src/network/layer_packet.erl rename to apps/sdlan/src/net/layer_packet.erl index c3e73bc..c71952c 100644 --- a/apps/sdlan/src/network/layer_packet.erl +++ b/apps/sdlan/src/net/layer_packet.erl @@ -2,8 +2,8 @@ %%% @doc Ethernet II layer packet parser %%%------------------------------------------------------------------- -module(layer_packet). - -export([parse/1, marshal/1, is_broadcast_mac/1, is_multicast_mac/1]). +-export([packet_type/1, payload/1]). -define(ETH_ARP, 16#0806). -define(ETH_IPV4, 16#0800). @@ -40,6 +40,14 @@ parse(Bin) when is_binary(Bin) -> {error, invalid_length} end. +-spec packet_type(Layer_packet :: #layer_packet{}) -> atom(). +packet_type(#layer_packet{type = T}) -> + T. + +-spec payload(Layer_packet :: #layer_packet{}) -> binary(). +payload(#layer_packet{payload = Payload}) -> + Payload. + %%-------------------------------------------------------------------- -spec marshal(#layer_packet{}) -> binary(). diff --git a/apps/sdlan/src/sdlan_network.erl b/apps/sdlan/src/sdlan_network.erl index 0f90c8e..01d199a 100644 --- a/apps/sdlan/src/sdlan_network.erl +++ b/apps/sdlan/src/sdlan_network.erl @@ -339,6 +339,31 @@ 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 arp_packet:opcode(ArpPacket) of + request -> + %% TODO + Mac = <<>>, + Ip = 12, + ArpResponse = arp_packet:marshal(arp_packet:arp_response(ArpPacket, Mac, Ip)), + + #endpoint{hole = #hole{peer = {NatIp, NatPort}}} = maps:get(SrcMac, UsedMap), + gen_udp:send(Sock, NatIp, NatPort, ArpResponse) + end; + + _ -> + ok + end + end + end, + PacketBytes = byte_size(Packet), %% 消息广播 maps:foreach(fun(Mac, #endpoint{hole = Hole}) ->