diff --git a/scapy/layers/zigbee.py b/scapy/layers/zigbee.py index 8531ca6f79d..4487319b024 100644 --- a/scapy/layers/zigbee.py +++ b/scapy/layers/zigbee.py @@ -1318,12 +1318,24 @@ class ZCLPriceGetScheduledPrices(Packet): ] +class _RateLabelStrField(StrLenField): + """Rate Label is a UTF-8 encoded octet string whose first octet indicates + the length of the label; the value includes the length octet.""" + + def getfield(self, pkt, s): + if not s: + return s, "" + length = s[0] if isinstance(s[0], int) else ord(s[0]) + self.length_from = lambda x: length + 1 + return StrLenField.getfield(self, pkt, s) + + class ZCLPricePublishPrice(Packet): name = "Price Cluster: Publish Price Command (Server: Generated)" fields_desc = [ XLEIntField("provider_id", 0x00000000), # Unsigned 32-bit Integer (4 octets) # noqa: E501 # Rate Label is a UTF-8 encoded Octet String (0-12 octets). The first Octet indicates the length. # noqa: E501 - StrLenField("rate_label", "", length_from=lambda pkt:int(pkt.rate_label[0])), # TODO verify # noqa: E501 + _RateLabelStrField("rate_label", ""), XLEIntField("issuer_event_id", 0x00000000), # Unsigned 32-bit Integer (4 octets) # noqa: E501 XLEIntField("current_time", 0x00000000), # UTCTime (4 octets) ByteField("unit_of_measure", 0), # 8 bits enumeration (1 octet) diff --git a/test/scapy/layers/dot15d4.uts b/test/scapy/layers/dot15d4.uts index 15ad74de801..4017c9460dd 100644 --- a/test/scapy/layers/dot15d4.uts +++ b/test/scapy/layers/dot15d4.uts @@ -948,3 +948,17 @@ assert ZCLIASZoneZoneEnrollResponse in pkt.layers() assert pkt[ZCLIASZoneZoneEnrollResponse].rsp_code == 0x00 assert pkt[ZCLIASZoneZoneEnrollResponse].zone_id == 0x3a assert raw(pkt[ZCLIASZoneZoneEnrollResponse].payload) == b'' + += ZCLPricePublishPrice rate label dissection + +p = ZCLPricePublishPrice(bytes.fromhex("1122334404616263645566778899aabbcc01ccdd0203445566778899aabbccdd112233445566778899aabbccddee")) +assert p.provider_id == 0x44332211 +assert p.rate_label == b"\x04abcd" +assert p.issuer_event_id == 0x88776655 +assert p.current_time == 0xCCBBAA99 +assert p.price == 0xDDCCBBAA +assert p.price_ratio == 0x11 +assert p.generation_price == 0x55443322 +assert p.number_of_block_thresholds == 0xDD +assert p.price_control == 0xEE +assert raw(p) == bytes.fromhex("1122334404616263645566778899aabbcc01ccdd0203445566778899aabbccdd112233445566778899aabbccddee")