blob: 27af1e9fdf136674fc9ab7f0c6be96ceb638a5be [file] [log] [blame]
Brian O'Connore9b4dd72016-03-05 01:07:18 -08001#!/usr/bin/env python
2import sys
3import os
4import fcntl
5import socket
6from struct import pack
7
8def getIPAddress(intf):
9 #Borrowed from:
10 #http://stackoverflow.com/questions/24196932/how-can-i-get-the-ip-address-of-eth0-in-python
11 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
12 return socket.inet_ntoa(fcntl.ioctl(
13 s.fileno(),
14 0x8915, # SIOCGIFADDR
15 pack('256s', intf[:15])
16 )[20:24])
17
18def gratuitousArp(intf, ip=None, mac=None):
19 #Adapted from:
20 #https://github.com/krig/send_arp.py/blob/master/send_arp.py
21 sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
22 try:
23 sock.bind((intf, socket.SOCK_RAW))
24 except:
25 print 'Device does not exist: %s' % intf
26 return
27
28 if not ip:
29 try:
30 ip = getIPAddress(intf)
31 except IOError:
32 print 'No IP for %s' % intf
33 return
34 packed_ip = pack('!4B', *[int(x) for x in ip.split('.')])
35
36 if mac:
37 packed_mac = pack('!6B', *[int(x,16) for x in mac.split(':')])
38 else:
39 packed_mac = sock.getsockname()[4]
40
41 bcast_mac = pack('!6B', *(0xFF,)*6)
42 zero_mac = pack('!6B', *(0x00,)*6)
43 eth_arp = pack('!H', 0x0806)
44 arp_proto = pack('!HHBBH', 0x0001, 0x0800, 0x0006, 0x0004, 0x0001)
45 arpframe = [
46 ## ETHERNET
47 # destination MAC addr
48 bcast_mac,
49 # source MAC addr
50 packed_mac,
51 # eth proto
52 eth_arp,
53
54 ## ARP
55 arp_proto,
56 # sender MAC addr
57 packed_mac,
58 # sender IP addr
59 packed_ip,
60 # target hardware addr
61 bcast_mac,
62 # target IP addr
63 packed_ip
64 ]
65
66 # send the ARP packet
67 sock.send(''.join(arpframe))
68
69if __name__ == "__main__":
70 if len(sys.argv) > 1:
71 intfs = sys.argv[1:]
72 else:
73 intfs = os.listdir('/sys/class/net/')
74
75 for intf in intfs:
76 gratuitousArp(intf)