Closed amuessig closed 8 years ago
Can you provide an example of a frame with an ARP that is failing? Feel free to change the mac address to dummy values.
Note pkt:decapsulate/1 returns the headers in order so you can use pattern matching:
[#ether{}, #arp{} = ARP, _Payload] = pkt:decapsulate(Data)
That might simplify the code a bit:
case Frame of
[#ether{}, #arp{op = ?ARPOP_REPLY, sip = Key, sha = DestMAC}, _Payload] ->
....
_ ->
ok
end
I did not use pattern matching because I am not only receiving ARP frames but any frames and did not try out what happens if it is not an ARP
.
After further investigating, it came out that I don't even receive the ARP frames.. I actually don't know why.
I am using a raw socket with procket and receive any other Data which can be parsed and processed. ARPs are not there. Should I open an issue there? I have no clue what is happening, since even a wireshark/tcpdump on this interface shows the ARP
.
On Mar 17, 2016 8:40 AM, "amuessig" notifications@github.com wrote:
I did not use pattern matching because I am not only receiving ARP frames but any frames and did not try out what happens if it is not an ARP.
Code should have the same behavior, any unmatched packets return OK.
After further investigating, it came out that I don't even receive the ARP frames.. I actually don't know why. I am using a raw socket with procket and receive any other Data which can be parsed and processed. ARPs are not there. Should I open an issue there? I have no clue what is happening, since even a wireshark/tcpdump on this interface shows the ARP.
A raw socket or a PF_PACKET socket? If you can include self-contained, runnable code, it will be easier to see what is going on.
— You are receiving this because you commented.
Reply to this email directly or view it on GitHub
As you are asking, I think it is a PF_PACKET socket. But PF_PACKET should also allow capturing at OSI Layer 2? Actually, I need to capture ANY traffic going through this socket.
setup_socket() ->
{ok, ListenSock} = procket:open(0, [{protocol, 16#0008}, {type, raw}, {family, packet}]),
Dev ="eth1",
% Binding to an interface
IfIndex = packet:ifindex(ListenSock, Dev),
ok = packet:bind(ListenSock, IfIndex),
Port = erlang:open_port({fd, ListenSock, ListenSock}, [binary, stream]),
%Get HW address and IP address
{ok, PL} = inet:ifget(Dev, [addr, hwaddr]),
IP = proplists:get_value(addr, PL),
MAC = list_to_binary(proplists:get_value(hwaddr, PL)),
% For Queuing packets when local MAC lookup fails
Queue = #{},
test_receive(ListenSock, IfIndex, Port, IP, MAC, Queue).
test_receive(ListenSock, IfIndex, Port, IP, MAC, Queue) ->
receive
{Port, {data, Data}} ->
Frame = pkt:decapsulate(Data),
ARP = lists:keyfind(arp,1,Frame),
io:format("Is it ARP? Frame: ~p~n", [Frame]),
io:format("Is it ARP? Data: ~p~n", [Data]),
case ARP of
false ->
ok;
_ ->
Type = ARP#arp.op,
case Type of
?ARPOP_REPLY ->
% Get the ARP sender ip which is the key
Key = ARP#arp.sip,
(#{Key := ListData} = Queue),
DestMAC = ARP#arp.sha,
io:format("It's a ARP Reply, doing different stuff here~p~n", [DestMAC]);
_ ->
ok
end
end
end,
test_receive(ListenSock, IfIndex, Port, IP, MAC, Queue).
Update: Am I right with the assumption, that I need to change the protocol to 16#0300?
{ok, ListenSock} = procket:open(0, [{protocol, 16#0300}, {type, raw}, {family, packet}])
I will check this tomorrow.
@amuessig that is correct. The socket is listening for IP packets only (ETH_P_IP). Switching to ETH_P_ALL (0x0003 in big endian format, needs to be converted to the native endian format on Linux) should receive everything including ARPs.
This solved the problem. Thanks for the explanation!
I want to receive packets and check if they are ARP replies. Thus, I look for 'arp' in the Frame, but it never matches. I couldn't find a single ARP packet which was decoded.
Am I wrong or is there a bug on decoding? Thanks!