I am trying to receive and send arp packets using c programming in Linux (Ubuntu)
My program works fine (i.e. runs without any error), but I cannot trac
A couple of things to get your packets on the wire/air.
There was an error in endianness when setting ah->arp_op. It is a network byteorder field of 2 octets, so use htons().
In general, the code is a little confused about network and host byteorder. It currently sends out the reply very mangled, but it is unclear to me whether that is the malicious intent of the code, or an accident. In the case that you want to send real, correct IP addresses, use htonl and htons, when building the reply.
To fix endianness:
In summary, the changes I did were 1) .sll_protocol = htons(ETH_P_ARP). (when sending data) 2) ah->arp_op = htons(ARPOP_REPLY) (in the reply arp) 3) Removed the nonsensical ntohs() on ah->arp_hd and ah->arp_pr. You dont want to convert data to host byteorder when populating the send buffer (unless you really really actually do) 4) Added ntohs() conversions and proper defines in some of the comparisons 5) some other small fixes 6) disabled the bit doing system("sudo...")!
Full code at pastebin. Here is a diff:
thuovila@glx:~/src/so/arp$ diff arp2.c arp_orig.c
13d12
< #include
20c19
< #define DEVICE "eth1"
---
> #define DEVICE "eth0"
25c24
< int s = -1; /*Socketdescriptor*/
---
> int s = 0; /*Socketdescriptor*/
92c91
< socket_address.sll_protocol = htons(ETH_P_ARP);
---
> socket_address.sll_protocol = htons(ETH_P_IP);
95c94
< socket_address.sll_pkttype = 0; //PACKET_OTHERHOST;
---
> socket_address.sll_pkttype = PACKET_OTHERHOST;
112c111
< if(ntohs(eh->h_proto) == ETH_P_ARP)
---
> if(htons(eh->h_proto) == 0x806)
119c118
< if(ntohs(ah->arp_op) != ARPOP_REQUEST)
---
> if(htons(ah->arp_op) != 0x0001)
139d137
< #if 0
145d142
< #endif
182c179
< eh->h_proto = htons(ETH_P_ARP);
---
> eh->h_proto = ETH_ARP;
200,201c197,198
< //ah->arp_hd = ntohs(ah->arp_hd);
< //ah->arp_pr = ntohs(ah->arp_pr);
---
> ah->arp_hd = ntohs(ah->arp_hd);
> ah->arp_pr = ntohs(ah->arp_pr);
203c200
< ah->arp_op = htons(ARPOP_REPLY);
---
> ah->arp_op = 0x0002;
EDIT Some wireshark advice. Capture ether proto 0x0806 (or arp for short). Use the pseudo device that captures any packets. Your packets should become visible.
On linux, if you want to stop the network stack from interfering, use: echo "8" > /proc/sys/net/ipv4/conf/all/arp_ignore
EDIT #2 I am not completely sure about the ETH_P_ARP. It might have been a snap judgement on my part. Using ETH_P_IP is correct in the ARP header field, but Im not sure which one to use for the packet socket sll_protocol. Also notice that socket_address.sll_pkttype = PACKET_OTHERHOST;
has no effect when sending (see man 7 packet). Also the mandatory SO observation, that you should always use at least -Wall (when using gcc or clang) as a compilation flag.
EDIT #3 I changed the program a little more. and updated the answer and diff accordingly. Surprisingly it does indeed seem, that .sll_protocol needs to be ETH_P_ARP. My copy of the man 7 packet doesnt even say it is used for anything, but the packet doesnt go out on the wire as ARP without it.