#!/usr/bin/python import struct from socket import * PKT_VER="1.0" INACTIVE=0 # Encapsulates a heartbeat message PKT_FMT = '!BBHL6BLB' # pkt_vermaj, pkt_vermin, pkt_size, uptime, MAC_ADDR, IP_ADDR, num_stations STA_FMT = '!H6BLLLLLLLhBf' # size, mac, ip_addr, metric, inactive, rx_bytes, rx_packets, tx_bytes, tx_packets, signal, tx_rate,throughput class heartbeat: # unpack data to simple string representation # TODO: perhaps use simplejson: http://simplejson.googlecode.com/svn/tags/simplejson-2.1.0/docs/index.html # or python-json, or python-cjson # or python-json, or python-cjson @staticmethod def str(data, arp = None, mac = None): s = '' i = struct.calcsize(PKT_FMT) (pkt_vermaj, pkt_vermin, pkt_size, uptime, m0, m1, m2, m3, m4, m5, ip_addr, num_stations) = struct.unpack(PKT_FMT, data[0:i]) s += " uptime:%d\n" % uptime s += " ip_addr:%s\n" % inet_ntoa(struct.pack('I' , ip_addr)) s += " mac:%02x:%02x:%02x:%02x:%02x:%02x\n" % (m0, m1, m2, m3, m4, m5) s += " stations:%d\n" % num_stations for j in range(num_stations): (size, m0, m1, m2, m3, m4, m5, station_ip_addr, metric, inactive, rx_bytes, rx_packets, tx_bytes, tx_packets, signal, tx_rate, throughput) = struct.unpack_from(STA_FMT, data, i) mac = "%02x:%02x:%02x:%02x:%02x:%02x" % (m0, m1, m2, m3, m4, m5) i += struct.calcsize(STA_FMT) sta = " station%d:\n" % (j+1) if arp: sta += " ip:%s\n" % arp.getip(mac) sta += " mac:%s\n" % mac sta += " ip_addr:%s\n" % inet_ntoa(struct.pack('I' , station_ip_addr)) sta += " metric:%s\n" % metric sta += " inactive:%d\n" % inactive sta += " rx_bytes:%d\n" % rx_bytes sta += " rx_packets:%d\n" % rx_packets sta += " tx_bytes:%d\n" % tx_bytes sta += " tx_packets:%d\n" % tx_packets sta += " signal:%d\n" % signal sta += " tx_rate:%d\n" % tx_rate sta += " throughput:%f\n" % throughput #print sta s += sta return s # generate and return a heartbeat packet # - uses /sys/kernel/debug/ieee80211//stations as this is # probably a more stable API than output of 'iw dev station dump' @staticmethod def create(src , neighbors): data = '' phy = 'mesh0' #"phy%s" % open("/sys/class/net/%s/phy80211/index" % iface).read().strip() uptime, idletime = (0, 0) #[float(f) for f in open("/proc/uptime").read().split()] # station data stations = [] tx_rate = 0 for (ip, mac) in neighbors: neighbormac = mac.split(':') newneighbormac = [] for i in neighbormac: newneighbormac.append(int(i)) sta_data = heartbeat.create_station_packet(newneighbormac, ip, tx_rate=2, rx_packets = 50, tx_packets = 21, inactive_ms = 320, throughput = 3.3, last_signal = 4) data += sta_data # heartbeat packet (srcip , srcmac) = src srcmacarray = srcmac.split(':') newsrcmacarray = [] for i in srcmacarray: newsrcmacarray.append(int(i)) data = struct.pack(PKT_FMT, int(PKT_VER.split('.')[0]), int(PKT_VER.split('.')[1]), struct.calcsize(PKT_FMT) + len(neighbors)*struct.calcsize(STA_FMT), int(uptime), newsrcmacarray[0], newsrcmacarray[1], newsrcmacarray[2], newsrcmacarray[3], newsrcmacarray[4], newsrcmacarray[5], struct.unpack('I' ,inet_aton(srcip) )[0], len(neighbors)) + data return data @staticmethod def create_station_packet(mac , ip_addr, tx_rate=0, inactive_ms=0, rx_bytes = 0, rx_packets =0, tx_bytes = 0, tx_packets = 0, last_signal = 0, metric = 0, throughput=0): sta_data = struct.pack(STA_FMT, struct.calcsize(STA_FMT), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], struct.unpack('I' ,inet_aton(ip_addr) )[0], metric, inactive_ms, rx_bytes, rx_packets, tx_bytes, tx_packets, last_signal, tx_rate, throughput ) return sta_data def create_fake_packet(filename, src, neighbors): data = heartbeat.create(src , neighbors) f = open(filename, 'w') f.write(data) f.close() f = open(filename, 'r') data = f.read() print filename , " created with following data:" print heartbeat.str(data) create_fake_packet("packet0", ("100.100.100.100" , "00:00:00:00:00:00"), [("100.100.100.101" , "00:00:00:00:00:01")]) create_fake_packet("packet1", ("100.100.100.101" , "00:00:00:00:00:01"), [("100.100.100.100" , "00:00:00:00:00:00")] ) create_fake_packet("packet2", ("100.100.100.102" , "00:00:00:00:00:02"), [("100.100.100.100" , "00:00:00:00:00:00"), ("100.100.100.101" , "00:00:00:00:00:01"), ("100.100.100.103" , "00:00:00:00:00:03")]) create_fake_packet("packet3", ("100.100.100.103" , "00:00:00:00:00:03"), [("100.100.100.104" , "00:00:00:00:00:04"), ("100.100.100.102" , "00:00:00:00:00:02")])