Search code examples
clinuxarp

linux ARP recvfrom information


If I send an ARP package can I find out from recv what is the IP adress of the sender ?I ask this because i send multiple packages to different hosts with child processes and I receive the response to all the child processes so I'm asking if there is a way to know what child sent what package.Thank you.

struct ether_arp req;
struct sockaddr_ll addr={0};
struct ifreq inter;
int sock;//I check usinginter if the interface is correct
sock=socket(AF_PACKET,SOCK_DGRAM,htons(ETH_P_ARP));
 if (sock==-1) {
 printf("%s",strerror(errno));
}
if (ioctl(sock,SIOCGIFINDEX,&inter)==-1) {
printf("%s",strerror(errno));
return ;//for the interface index
addr.sll_family=AF_PACKET;
addr.sll_ifindex=index;
addr.sll_halen=ETHER_ADDR_LEN;
addr.sll_protocol=htons(ETH_P_ARP);
memcpy(addr.sll_addr,ether_broadcast_addr,ETHER_ADDR_LEN);
req.arp_hrd=htons(ARPHRD_ETHER);
req.arp_pro=htons(ETH_P_IP);
req.arp_hln=ETHER_ADDR_LEN;
req.arp_pln=sizeof(in_addr_t);
req.arp_op=htons(ARPOP_REQUEST);
......................  
 memcpy(&req.arp_spa,&target_ip_addr.s_addr,sizeof(req.arp_spa));//this way I save the   source IP
.......
if (sendto(sock,&req,sizeof(req),0,(struct sockaddr*)&addr,sizeof(addr))==-1) {
printf("%s",strerror(errno));
}THis is how I send it

There is a little more code but i don't think it is relevant


Solution

  • You can't use recvfrom to discover the ip address of the sender, because ARP packet got no network layer.

    If you want to know which host, with his relative mac address and ip address, replied to your requests you have to dissect the packet that's made like this:

    enter image description here

    Look here for further infos about single fields: ARP Message Format

    The 32 bits you're looking for are into Sender Protocol Address

    This is an hypotetic code snippet that shows ip numbers of hosts arp-replying to your ARP REQUESTS.

    DISCLAIMER: i didn't test it but it should give you an idea.

    /* buf is buffer containing the ethernet frame */
    char buf[65535];
    
    /* arp frame points to the arp data inside the ethernet frame */
    struct ether_arp *arp_frame;
    
    /* skipping the 14 bytes of ethernet frame header */
    arp_frame = (struct ether_arp *) (buf + 14);
    
    /* read until we got an arp packet or socket got a problem */
    while (recv(sock, buf, sizeof(buf), 0))
    {
        /* skip to the next frame if it's not an ARP packet */
        if ((((buf[12]) << 8) + buf[13]) != ETH_P_ARP) 
            continue;
    
        /* skip to the next frame if it's not an ARP REPLY */
        if (ntohs (arp_frame->arp_op) != ARPOP_REPLY)
            continue;
    
        /* got an arp reply! this is where i'm printing what you need             */
        /* ... and YES... spa of arp_spa field stands for Sender Protocol Address */
        printf("I got an arp reply from host with ip: %u.%u.%u.%u\n", arp_frame->arp_spa[0],
                                                                      arp_frame->arp_spa[1],
                                                                      arp_frame->arp_spa[2], 
                                                                      arp_frame->arp_spa[3]);
    
        /* break? */
        break;    
    }
    

    And this is a full WORKING example of a mini program listening for ARP-REPLIES.

    arp-reply-catcher.c source