#! /usr/bin/env python # # Scapy extension for AWDS Routing Version 0.24 # AWDS Protocol version 7 # # (C) 2008-12-08 Georg Lukas AWDS_ETHERTYPE = 0x8334 try: import psyco except ImportError: pass from scapy.all import * ####################### ## AWDS packet types ## ####################### class AWDS(Packet): """ Packet generated by AdHoc WDS meshware """ name = "Ad Hoc WDS" # XXX TraceFlag fields_desc = [ BitField("trace", 0, 1), XBitField("options", 0, 5), BitEnumField("type", 0, 2, { 0: "Beacon", 1: "Flood", 2: "Unicast" }), MACField("src", ETHER_ANY), ShortField("seqno", 0) ] class AWDSBeacon(Packet): """ Beacon Packet generated by AdHoc WDS meshware """ name = "AWDS Beacon" fields_desc = [ ShortField("beacon_int", 1399), FieldLenField("nonmprcount", None, count_of="nonmprnodes", fmt="B"), FieldLenField("mprcount", None, count_of="mprnodes", fmt="B"), FieldListField("nonmprnodes",[],MACField("nonmpr", ETHER_ANY),count_from=lambda p: p.nonmprcount), FieldListField("mprnodes",[],MACField("mpr", ETHER_ANY),count_from=lambda p: p.mprcount) ] class AWDSFlood(Packet): """ Flood Packet generated by AdHoc WDS meshware """ name = "AWDS Flood" fields_desc = [ MACField("lasthop", ETHER_ANY), ByteField("ttl", 32), ByteEnumField("type", 0, { 0: "Topo", 98: "Data" }) ] class AWDSUnicast(Packet): """ Unicast Packet generated by AdHoc WDS meshware """ name = "AWDS Unicast" fields_desc = [ MACField("dest", ETHER_ANY), MACField("nexthop", ETHER_ANY), ByteField("ttl", 32), ByteEnumField("type", 0, { 18: "LinkQuality Probe", 42: "Ping", 98: "Data" }) ] class AWDSPing(Packet): """ AWDS Ping/Pong """ name = "AWDS Ping/Pong" fields_desc = [ ShortField("seq", 0), ByteEnumField("dir", 'i', { 'i': "ping", 'o': "pong"}), LongField("tstamp", 0) ] class AWDSTopoField(Field): def __init__(self, name, default): Field.__init__(self, name, default, "8s") class AWDSLink(Packet): """ Peer to peer link with link cost """ name = "AWDS Link" fields_desc = [ MACField("addr", ETHER_ANY), ShortField("cost", 10) ] def extract_padding(self, pkt): return "",pkt class AWDSTopo(Packet): """ Topology Flood generated by AdHoc WDS meshware """ name = "AWDS Topology" fields_desc = [ IntField("validity", 30000), FieldLenField("numlinks", None, count_of="links", fmt="B"), #FieldListField("links", [], AWDSTopoField("mpr", ETHER_ANY), count_from=lambda pkt: pkt.numlinks), PacketListField("links", [], AWDSLink, count_from=lambda pkt: pkt.numlinks), FieldLenField("namelen", None, length_of="name", fmt="B"), StrLenField("name", "awdsnode", length_from=lambda pkt: pkt.namelen) ] class AWDSCrypto(Packet): """ Encrypted packet from AdHoc WDS meshware """ name = "AWDS Crypted Data" fields_desc = [ LongField("iv", 0), LongField("nonce", 0) ] class AWDSPublish(Packet): """AWDS Publish Channel""" name = "AWDS Publish Channel" fields_desc = [ StrFixedLenField("subject", '', 8), StrField("data", '') ] class AWDSSubscribe(Packet): """AWDS Subscribe Channel""" name = "AWDS Subscribe Channels" fields_desc = [ XIntField("reserved", 20), FieldLenField("number", None, count_of="subjects", fmt="H"), #FieldListField("subjects", [], XLongField("subject", 0), count_from=lambda p: p.number) ] FieldListField("subjects", [], StrFixedLenField("subject", '', 8), count_from=lambda p: p.number) ] class AWDSSppFlood(Packet): """AWDS Simple Push/Poll protocol""" fields_desc = [ MACField("dest", ETHER_ANY) ] class AWDSSppPayload(Packet): """AWDS remote call packet""" name = "AWDS Remote Call" fields_desc = [ ByteEnumField("type", 0, { 0: "request", 1: "response", 2: "ack" }), IntField("id", 0), ByteField("seqno", 0) ] my_layer_bonds = [ ( Ether, AWDS, { "type" : AWDS_ETHERTYPE } ), ( AWDS, AWDSBeacon, { "type" : 0 } ), ( AWDS, AWDSFlood, { "type" : 1 } ), ( AWDS, AWDSUnicast, { "type" : 2 } ), ( AWDSFlood, AWDSTopo, { "type" : 0 } ), ( AWDSFlood, AWDSSppFlood, { "type" : 34 } ), ( AWDSFlood, AWDSPing, { "type" : 42 } ), ( AWDSFlood, Ether, { "type" : 98 } ), ( AWDSFlood, AWDSCrypto, { "type" : 99 } ), ( AWDSFlood, AWDSPublish, { "type" : 0x7c } ), ( AWDSFlood, AWDSSubscribe, { "type" : 0x7d } ), ( AWDSUnicast, AWDSPing, { "type" : 42 } ), ( AWDSUnicast, AWDSSppPayload,{ "type" : 34 } ), ( AWDSUnicast, Ether, { "type" : 98 } ), ( AWDSUnicast, AWDSCrypto, { "type" : 99 } ), ( AWDSUnicast, AWDSPublish, { "type" : 0x7c } ), ( AWDSUnicast, AWDSSubscribe, { "type" : 0x7d } ), ( AWDSSppFlood, AWDSSppPayload, {} ), ( AWDSTopo, Padding, {} ), ( SNAP, AWDS, { "code" : AWDS_ETHERTYPE } ) ] for l in my_layer_bonds: bind_layers(*l) del(l) def fakeup_topo(numlinks = 100, validity = 10000): macs=[] for i in range(0, numlinks): macs += [ "".join(RandMAC()) ] macs.sort() links=[] for i in range(0, numlinks): m = macs[i]; links += [map(lambda arg: AWDSLink(addr=arg), filter(lambda arg: m != arg, macs))] names=[] for i in range(0, numlinks): names += [ "node%03i" % i ] packets = [] for i in range(0, numlinks): packets += [Ether()/AWDS(src=macs[i])/AWDSFlood()/AWDSTopo(validity=validity, links=links[i], name=names[i])] return packets if __name__ == "__main__": interact(mydict=globals(), mybanner="AWDS Packet (%#x) support enabled." % AWDS_ETHERTYPE)