Brian O'Connor | e9b4dd7 | 2016-03-05 01:07:18 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | import sys |
| 3 | import os |
| 4 | import fcntl |
| 5 | import socket |
| 6 | from struct import pack |
| 7 | |
| 8 | def 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 | |
| 18 | def 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 | |
| 69 | if __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) |