I'am writing an network library in C from scratch. I already implemented the Ethernet protocol and now I want to get ARP working. Sending Requests/Replies works fine but receiving isn't working well. When I send an send an Request and wait for the Reply after it, recvfrom() just takes the first incoming ARP packet. But I want to get the Reply from the host replying to my Request.
I can't just receive packets until the correct one arrives because the library should support socket timeouts. (set with setsockopt())
The socket is created like this:
int sfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP))
Output of my test program:
Sending ARP-Request ...
0o0o0o0 ARP-FRAME DUMP 0o0o0o0
HwType: 256 (0x7ab74e358670)
PrType: 8 (0x7ab74e358672)
HwALen: 6 (0x7ab74e358674)
PrALen: 4 (0x7ab74e358675)
ArpOP : 256 (0x7ab74e358676)
Sha : 84:4b:10:14:a0:04 (0x7ab74e358678)
Spa : 192.168.12.1 (0x7ab74e35867e)
Tha : 00:00:00:00:00:00 (0x7ab74e358682)
Tpa : 192.168.0.3 (0x7ab74e358688)
Receiving ARP-Reply ...
0o0o0o0 ARP-FRAME DUMP 0o0o0o0
HwType: 256 (0x7ab74e358670)
PrType: 8 (0x7ab74e358672)
HwALen: 6 (0x7ab74e358674)
PrALen: 4 (0x7ab74e358675)
ArpOP : 512 (0x7ab74e358676)
Sha : 10:00:00:00:00:01 (0x7ab74e358678)
Spa : 192.168.12.78 (0x7ab74e35867e)
Tha : 84:4b:10:14:a0:04 (0x7ab74e358682)
Tpa : 192.168.12.1 (0x7ab74e358688)
Is it possible to filter incoming ARP packets/how to do it?
Thanks in advance.
--- EDIT ---
I played around with the BPF and it worked fine for filtering out ARP packets. It wrote this filter
ld [28]
jne #0x4e0ca8c0, drop
ret #-1
drop: ret #0
to filter the incoming ARP replies. It should load the source IP from the packet and compare it with the one defined in the code. 0x4e0ca8c0 is the valid IP addr. of the host whose reply I want. tcpdump shows the incoming reply but my program freezes (Waits forever). I used the BPF like this:
struct sock_fprog prog;
struct sock_filter filter[4] =\
{{ 0x20, 0, 0, 0x0000001c },
{ 0x15, 0, 1, 0x4e0ca8c0 },
{ 0x06, 0, 0, 0xffffffff },
{ 0x06, 0, 0, 0000000000 }};
prog.len = 4;
prog.filter = filter;
if(setsockopt(sfd, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) ==\
-1) {
fprintf(stderr, "ERROR enabling bpf: setsockopt(): %s\n",\
strerror(errno));
goto ... (error handler);
}
/* Receive incoming ARP reply */
I hope I haven't made any stupid/obvious mistakes.
Thanks in advance!
-- LAST EDIT --
The IP addr. must be in NBO. So with the correct BPF:
struct sock_filter filter[4] =\
{{ 0x20, 0, 0, 0x0000001c },
{ 0x15, 0, 1, 0xc0a80c4e },
{ 0x06, 0, 0, 0xffffffff },
{ 0x06, 0, 0, 0000000000 }};
... only replies from 192.168.12.78 (0xc0a80c4e) are accepted/received.
Huge thanks to Ctx!