pythonpython-3.xscapyarp

How to correctly receive responses from the ARP protocol


I want to make a small script for monitoring the local network for the presence of devices in it. I am using ARP protocol request and response, here is my code:

import time
import scapy.all as scapy
import argparse
import pandas as pd


def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument('--target', '-t', dest='target', help='Target IP / IP range.')
    option = parser.parse_args()
    return option


def scan(ip):
    arp_request = scapy.ARP(pdst=ip)
    broadcast = scapy.Ether(dst='ff:ff:ff:ff:ff:ff')
    arp_request_broadcast = broadcast / arp_request
    answered_list = scapy.srp(arp_request_broadcast, timeout=3, verbose=False)[0]

    clients_list = []
    for element in answered_list:
        clients_dict = {'ip': element[1].psrc, 'mac': element[1].hwsrc}
        clients_list.append(clients_dict)
    return clients_list


opt = get_arguments()
while True:
    time.sleep(3)
    scan_result = pd.DataFrame(scan(opt.target))
    print(scan_result)

In principle, everything works, but there is one big problem in my opinion. Somehow, the answer is returned to me that there are fewer connected devices on the network than in reality. see picture.

enter image description here

As you can see, the first two answers show me the real picture of what is happening, i.e. I see all six devices (highlighted in red), but then an absolutely unknown situation happens to me, for some reason there are more or less devices, some kind of random answer.

Could you tell me please, Is this problem caused by the peculiarities of the ARP protocol? Or is there some error in the code?

Would you mind telling me how can improve this code or do something differentl?

Thank you very much!


Solution

  • Having studied the scapy documentation better, I found that can use the retry parameter in scapy.srp, and now my line in the code looks like this:

    answered_list = scapy.srp(arp_request_broadcast, timeout=2, retry=-2 verbose=False)[0]
    

    Thus, now all devices located on the local network respond to me and are correctly displayed.