Source code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 ''' This tool reports all newly connected devices to our network therefore it has to remember all IP to MAC resolutions. Additionally it can detect if a device suddenly changes its MAC address. ''' from scapy.all import sniff, ARPfrom signal import signal, SIGINTimport sysarp_watcher_db_file = "/var/cache/arp-watcher.db" ip_mac = {} def sig_int_handler (signum, frame) : print "Got SIGINT. Saving ARP database..." try : f = open(arp_watcher_db_file, "w" ) for (ip, mac) in ip_mac.items(): f.write(ip + " " + mac + "\n" ) f.close() print "Done." except IOError: print "Cannot write file " + arp_watcher_db_file sys.exit(1 ) def watch_arp (pkt) : if pkt[ARP].op == 2 : print pkt[ARP].hwsrc + " " + pkt[ARP].psrc if ip_mac.get(pkt[ARP].psrc) == None : print "Found new device " + pkt[ARP].hwsrc + " " + pkt[ARP].psrc ip_mac[pkt[ARP].psrc] = pkt[ARP].hwsrc elif ip_mac.get(pkt[ARP].psrc) and ip_mac[pkt[ARP].psrc] != pkt[ARP].hws rc: print pkt[ARP].hwsrc + " has got new ip " + pkt[ARP].psrc + "(old " + ip_mac[pkt[ARP].psrc] + ")" signal(SIGINT, sig_int_handler) if len(sys.argv) < 2 : print sys.argv[0 ] + " <iface>" sys.exit(0 ) try : fh = open(arp_watcher_db_file, "r" ) except IOError: print "Cannot read file " + arp_watcher_db_file sys.exit(1 ) for line in fh: line.chomp() (ip, mac) = line.split(" " ) ip_mac[IP] = mac sniff(prn=watch_arp,filter="arp" , iface=sys.argv[1 ], store=0 )