class Eddystone_URL(Packet): """ An Eddystone type for transmitting a URL (to a web page). https://github.com/google/eddystone/tree/master/eddystone-url """ name = "Eddystone URL" fields_desc = [ SignedByteField("tx_power", 0), ByteEnumField("url_scheme", 0, EDDYSTONE_URL_SCHEMES), EddystoneURLField("url", None), ] def to_url(self): return EDDYSTONE_URL_SCHEMES[self.url_scheme] + self.url @staticmethod def from_url(url): """Creates an Eddystone_Frame with a Eddystone_URL for a given URL.""" url = url.encode('ascii') scheme = None for k, v in EDDYSTONE_URL_SCHEMES.items(): if url.startswith(v): scheme = k url = url[len(v):] break else: raise Exception("URLs must start with EDDYSTONE_URL_SCHEMES") return Eddystone_Frame() / Eddystone_URL(url_scheme=scheme, url=url)
class Eddystone_EID(Packet): # https://github.com/google/eddystone/tree/master/eddystone-eid name = "Eddystone EID" fields_desc = [ SignedByteField("tx_power", 0), StrFixedLenField("eid", None, 8), ]
class BTLE_RF(Packet): """Cooked BTLE link-layer pseudoheader. https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR.html """ name = "BTLE RF info header" _TYPES = { 0: "ADV_OR_DATA_UNKNOWN_DIR", 1: "AUX_ADV", 2: "DATA_M_TO_S", 3: "DATA_S_TO_M", 4: "CONN_ISO_M_TO_S", 5: "CONN_ISO_S_TO_M", 6: "BROADCAST_ISO", 7: "RFU", } _PHY = { 0: "1M", 1: "2M", 2: "Coded", 3: "RFU", } fields_desc = [ ByteField("rf_channel", 0), SignedByteField("signal", -128), SignedByteField("noise", -128), ByteField("access_address_offenses", 0), XLEIntField("reference_access_address", 0), LEBitField("dewhitened", 0, 1), LEBitField("sig_power_valid", 0, 1), LEBitField("noise_power_valid", 0, 1), LEBitField("decrypted", 0, 1), LEBitField("reference_access_address_valid", 0, 1), LEBitField("access_address_offenses_valid", 0, 1), LEBitField("channel_aliased", 0, 1), LEBitEnumField("type", 0, 3, _TYPES), LEBitField("crc_checked", 0, 1), LEBitField("crc_valid", 0, 1), LEBitField("mic_checked", 0, 1), LEBitField("mic_valid", 0, 1), LEBitEnumField("phy", 0, 2, _PHY), ]
class Eddystone_UID(Packet): # https://github.com/google/eddystone/tree/master/eddystone-uid name = "Eddystone UID" fields_desc = [ SignedByteField("tx_power", 0), StrFixedLenField("namespace", None, 10), StrFixedLenField("instance", None, 6), StrFixedLenField("reserved", None, 2), ]
class BTLE_RF(Packet): """Cooked BTLE link-layer pseudoheader. http://www.whiterocker.com/bt/LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR.html """ name = "BTLE RF info header" fields_desc = [ ByteField("rf_channel", 0), SignedByteField("signal", -128), SignedByteField("noise", -128), ByteField("access_address_offenses", 0), XLEIntField("reference_access_address", 0), FlagsField("flags", 0, -16, [ "dewhitened", "sig_power_valid", "noise_power_valid", "decrypted", "reference_access_address_valid", "access_address_offenses_valid", "channel_aliased", "res1", "res2", "res3", "crc_checked", "crc_valid", "mic_checked", "mic_valid", "res4", "res5" ]) ]
class BTLE_PPI(PPI_Element): """Cooked BTLE PPI header See ``ppi_btle_t`` in https://github.com/greatscottgadgets/libbtbb/blob/master/lib/src/pcap.c """ name = "BTLE PPI header" fields_desc = [ ByteField("btle_version", 0), # btle_channel is a frequency in MHz. Named for consistency with # other users. LEShortField("btle_channel", None), ByteField("btle_clkn_high", None), LEIntField("btle_clk_100ns", None), SignedByteField("rssi_max", None), SignedByteField("rssi_min", None), SignedByteField("rssi_avg", None), ByteField("rssi_count", None) ]
class PPI_Geotag_Sensor(HCSIPacket): name = "PPI Sensor" hcsi_fields = [ LEShortEnumField('SensorType', None, sensor_types), SignedByteField('ScaleFactor', None), Fixed6_4Field('Val_X', None), Fixed6_4Field('Val_Y', None), Fixed6_4Field('Val_Z', None), Fixed6_4Field('Val_T', None), Fixed6_4Field('Val_E', None), ] + _hcsi_null_range(7, 28)
class IBeacon_Data(Packet): """ iBeacon broadcast data frame. Composed on top of an Apple_BLE_Submessage. """ name = "iBeacon data" fields_desc = [ UUIDField("uuid", None, uuid_fmt=UUIDField.FORMAT_BE), ShortField("major", None), ShortField("minor", None), SignedByteField("tx_power", None), ]
class Eddystone_EID(Packet): """ An Eddystone type for transmitting encrypted, ephemeral identifiers. This implementation does not support decrypting this data. https://github.com/google/eddystone/tree/master/eddystone-eid """ name = "Eddystone EID" fields_desc = [ SignedByteField("tx_power", 0), StrFixedLenField("eid", None, 8), ]
class Eddystone_UID(Packet): """ An Eddystone type for transmitting a unique identifier. https://github.com/google/eddystone/tree/master/eddystone-uid """ name = "Eddystone UID" fields_desc = [ SignedByteField("tx_power", 0), StrFixedLenField("namespace", None, 10), StrFixedLenField("instance", None, 6), StrFixedLenField("reserved", None, 2), ]
class APRadioBasicCaps_OpClass(Packet): name = "Operating Class" fields_desc = [ XByteField("op_class", None), SignedByteField("eirp", None), FieldLenField("nop_chnl_cnt", None, fmt='B', count_of="nop_chnl_list"), FieldListField("nop_chnl_list", None, XByteField("nop_chnl", None), count_from=lambda p: p.nop_chnl_cnt) ] def extract_padding(self, s): return "", s
class HCI_LE_Meta_Advertising_Report(Packet): name = "Advertising Report" fields_desc = [ ByteField("number", 0), ByteEnumField("type", 0, { 0: "conn_und", 4: "scan_rsp" }), ByteEnumField("atype", 0, { 0: "public", 1: "random" }), LEMACField("addr", None), FieldLenField("len", None, length_of="data", fmt="B"), PacketListField("data", [], EIR_Hdr, length_from=lambda pkt: pkt.len), SignedByteField("rssi", 0) ]
class AltBeacon(Packet, LowEnergyBeaconHelper): """ AltBeacon broadcast frame type. https://github.com/AltBeacon/spec """ name = "AltBeacon" magic = b"\xBE\xAC" fields_desc = [ StrFixedLenField("header", magic, len(magic)), # The spec says this is 20 bytes, with >=16 bytes being an # organisational unit-specific identifier. However, the Android library # treats this as UUID + uint16 + uint16. UUIDField("id1", None), # Local identifier ShortField("id2", None), ShortField("id3", None), SignedByteField("tx_power", None), ByteField("mfg_reserved", None), ] @classmethod def magic_check(cls, payload): """ Checks if the given payload is for us (starts with our magic string). """ return payload.startswith(cls.magic) def build_eir(self): """Builds a list of EIR messages to wrap this frame.""" # Note: Company ID is not required by spec, but most tools only look # for manufacturer-specific data with Radius Networks' manufacturer ID. return LowEnergyBeaconHelper.base_eir + [ EIR_Hdr() / EIR_Manufacturer_Specific_Data( company_id=RADIUS_NETWORKS_MFG) / self ]
# http://www.iana.org/assignments/icmp-parameters sensor_types = { 1: "Velocity", 2: "Acceleration", 3: "Jerk", 100: "Rotation", 101: "Magnetic", 1000: "Temperature", 1001: "Barometer", 1002: "Humidity", 2000: "TDOA_Clock", 2001: "Phase" } SENS_Fields = [ LEShortEnumField('SensorType', None, sensor_types), SignedByteField('ScaleFactor', None), Fixed6_4Field('Val_X', None), Fixed6_4Field('Val_Y', None), Fixed6_4Field('Val_Z', None), Fixed6_4Field('Val_T', None), Fixed6_4Field('Val_E', None), HCSINullField("Reserved07", None), HCSINullField("Reserved08", None), # noqa: E501 HCSINullField("Reserved09", None), HCSINullField("Reserved10", None), # noqa: E501 HCSINullField("Reserved11", None), HCSINullField("Reserved12", None), # noqa: E501 HCSINullField("Reserved13", None), HCSINullField("Reserved14", None), # noqa: E501 HCSINullField("Reserved15", None), HCSINullField("Reserved16", None), # noqa: E501
class EIR_TX_Power_Level(EIR_Element): name = "TX Power Level" fields_desc = [SignedByteField("level", 0)]