Skip to content

Instantly share code, notes, and snippets.

@jwheare
Last active December 28, 2015 05:29
Show Gist options
  • Save jwheare/7449798 to your computer and use it in GitHub Desktop.
Save jwheare/7449798 to your computer and use it in GitHub Desktop.
Sniff airport traffic and map MAC addresses to a last.fm username
#!/usr/bin/env python
import subprocess
import sys
import re
import urllib
# Mapping of local MAC addresses to last.fm usernames
MAC_ADDRESSES = {
'00:00:00:00:00:00': 'lastfm_username',
}
# only really works when you have a dedicated base station for speakers that
# isn't also serving internets
AIRPORT_MAC = ['00:00:00:00:00:00', '00:00:00:00:00:01'] # add as many receivers as you have
INTERFACE = 'en1' # might need changing, check your ifconfig for the wifi interface
PACKET_PATTERN = re.compile('.*SA:([^\s]+).*')
def map_line_to_mac_address(line):
m = PACKET_PATTERN.match(line)
if m:
mac_address = m.group(1)
return mac_address
return None
def sniff_network():
tcpdump = [
'tcpdump',
'-n', # Don't resolve hosts/ports to names
'-i', INTERFACE, # Listen on wifi interface
'-y', 'IEEE802_11', # Use the 802.11 data link layer
'-I', # Monitor mode, listen in on all network traffic
'-e', # Include packet headers, so we can parse out mac addresses
# '-vvv', # verbose
'wlan', 'dst', 'host', ' or '.join(AIRPORT_MAC) # BPF filter where destination host is one of the Airport MACs
]
print ' '.join(tcpdump)
proc = subprocess.Popen(' '.join(tcpdump), shell=True, stdout=subprocess.PIPE)
process_lines(proc)
def process_lines(proc):
now_playing = None
now_playing_dj = None
try:
while True:
line = proc.stdout.readline()
mac_address = map_line_to_mac_address(line)
if mac_address and mac_address != now_playing:
try:
if mac_address in MAC_ADDRESSES:
dj = MAC_ADDRESSES[mac_address]
if dj != now_playing_dj:
# print '\n', line,
print 'New DJ: %s' % dj
# post to a web server somewhere or whatever
now_playing_dj = dj
else:
# print '\n', line,
print 'Unknown MAC address: %s' % mac_address
sys.stdout.flush()
now_playing = mac_address
except IOError as exc:
# update call failed, try again
print 'Error!', exc
except KeyboardInterrupt:
pass
if __name__ == '__main__':
sniff_network()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment