# coding: utf8 % ProfinetIO layer test campaign + Syntax check = Import the ProfinetIO layer from scapy.contrib.pnio import * from scapy.config import conf import re old_conf_dissector = conf.debug_dissector conf.debug_dissector=True + Check DCE/RPC layer = ProfinetIO default values raw(ProfinetIO()) == b'\x00\x00' = ProfinetIO overloads Ethertype p = Ether() / ProfinetIO() p.type == 0x8892 = ProfinetIO overloads UDP dport p = UDP() / ProfinetIO() p.dport == 0x8892 = Ether guesses ProfinetIO as payload class p = Ether(hex_bytes('ffffffffffff00000000000088920102')) isinstance(p.payload, ProfinetIO) and p.frameID == 0x0102 = UDP guesses ProfinetIO as payload class p = UDP(hex_bytes('12348892000a00000102')) isinstance(p.payload, ProfinetIO) and p.frameID == 0x0102 + PNIO RTC PDU tests = ProfinetIO PNIORealTime_IOxS parsing of a single status p = PNIORealTime_IOxS(b'\x80') assert(p.dataState == 1) assert(p.instance == 0) assert(p.reserved == 0) assert(p.extension == 0) p = PNIORealTime_IOxS(b'\xe1') assert(p.dataState == 1) assert(p.instance == 3) assert(p.reserved == 0) assert(p.extension == 1) True = ProfinetIO PNIORealTime_IOxS building of a single status p = PNIORealTime_IOxS(dataState = 'good', instance='subslot', extension=0) assert(raw(p) == b'\x80') p = PNIORealTime_IOxS(dataState = 'bad', instance='device', extension=1) assert(raw(p) == b'\x41') True = ProfinetIO PNIORealTime_IOxS parsing with multiple statuses TestPacket = type( 'TestPacket', (Packet,), { 'name': 'TestPacket', 'fields_desc': [ PacketListField('data', [], next_cls_cb= PNIORealTime_IOxS.is_extension_set) ], } ) p = TestPacket(b'\x81\xe1\x01\x80') assert(len(p.data) == 4) assert(p.data[0].dataState == 1) assert(p.data[0].instance == 0) assert(p.data[0].reserved == 0) assert(p.data[0].extension == 1) assert(p.data[1].dataState == 1) assert(p.data[1].instance == 3) assert(p.data[1].reserved == 0) assert(p.data[1].extension == 1) assert(p.data[2].dataState == 0) assert(p.data[2].instance == 0) assert(p.data[2].reserved == 0) assert(p.data[2].extension == 1) assert(p.data[3].dataState == 1) assert(p.data[3].instance == 0) assert(p.data[3].reserved == 0) assert(p.data[3].extension == 0) = ProfinetIO RTC PDU parsing without configuration p = Ether(b'\x00\x02\x04\x06\x08\x0a\x01\x03\x05\x07\x09\x0B\x88\x92\x80\x00\x01\x02\x03\x04\xf0\x00\x35\x00') assert(p[Ether].dst == '00:02:04:06:08:0a') assert(p[Ether].src == '01:03:05:07:09:0b') assert(p[Ether].type == 0x8892) assert(p[ProfinetIO].frameID == 0x8000) assert(isinstance(p[ProfinetIO].payload, PNIORealTimeCyclicPDU)) assert(len(p[PNIORealTimeCyclicPDU].data) == 1) assert(isinstance(p[PNIORealTimeCyclicPDU].data[0], PNIORealTimeCyclicDefaultRawData)) assert(p[PNIORealTimeCyclicDefaultRawData].data == b'\x01\x02\x03\x04') assert(p[PNIORealTimeCyclicPDU].padding == b'') assert(p[PNIORealTimeCyclicPDU].cycleCounter == 0xf000) assert(p[PNIORealTimeCyclicPDU].dataStatus == 0x35) assert(p[PNIORealTimeCyclicPDU].transferStatus == 0) True = ProfinetIO RTC PDU building p = Ether(src='01:03:05:07:09:0b', dst='00:02:04:06:08:0a')/ProfinetIO(frameID = 'PTCP-RTSyncPDU')/PNIORealTimeCyclicPDU( data=[ PNIORealTimeCyclicPDU.build_fixed_len_raw_type(10)(data = b'\x80'*10) ], padding = b'\x00'*8, cycleCounter = 900, dataStatus = 0x35, transferStatus = 0 ) assert( raw(p) == \ b'\x00\x02\x04\x06\x08\x0a' \ b'\x01\x03\x05\x07\x09\x0b' \ b'\x88\x92' \ b'\x00\x80' \ b'\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80' \ b'\x00\x00\x00\x00\x00\x00\x00\x00' \ b'\x03\x84' \ b'\x35' \ b'\x00' ) = ProfinetIO RTC PDU parsing with config scapy.config.conf.contribs['PNIO_RTC'][('01:03:05:07:09:0b', '00:02:04:06:08:0a', 0x8010)] = [ PNIORealTimeCyclicPDU.build_fixed_len_raw_type(5), PNIORealTimeCyclicPDU.build_fixed_len_raw_type(3), PNIORealTimeCyclicPDU.build_fixed_len_raw_type(2) ] p = Ether( b'\x00\x02\x04\x06\x08\x0a' \ b'\x01\x03\x05\x07\x09\x0B' \ b'\x88\x92' \ b'\x80\x10' \ b'\x01\x02\x03\x04\x05' \ b'\x01\x02\x03' \ b'\x01\x02' \ b'\x00\x00' \ b'\xf0\x00' \ b'\x35' \ b'\x00' ) assert(p[Ether].dst == '00:02:04:06:08:0a') assert(p[Ether].src == '01:03:05:07:09:0b') assert(p[Ether].type == 0x8892) assert(p[ProfinetIO].frameID == 0x8010) assert(isinstance(p[ProfinetIO].payload, PNIORealTimeCyclicPDU)) assert(len(p[PNIORealTimeCyclicPDU].data) == 3) assert(isinstance(p[PNIORealTimeCyclicPDU].data[0], scapy.config.conf.raw_layer)) assert(p[PNIORealTimeCyclicPDU].data[0].data == b'\x01\x02\x03\x04\x05') assert(isinstance(p[PNIORealTimeCyclicPDU].data[1], scapy.config.conf.raw_layer)) assert(p[PNIORealTimeCyclicPDU].data[1].data == b'\x01\x02\x03') assert(isinstance(p[PNIORealTimeCyclicPDU].data[2], scapy.config.conf.raw_layer)) assert(p[PNIORealTimeCyclicPDU].data[2].data == b'\x01\x02') assert(p[PNIORealTimeCyclicPDU].padding == b'\x00' * 2) assert(p[PNIORealTimeCyclicPDU].cycleCounter == 0xf000) assert(p[PNIORealTimeCyclicPDU].dataStatus == 0x35) assert(p[PNIORealTimeCyclicPDU].transferStatus == 0) p = Ether(b'\x00\x02\x04\x06\x08\x0a\x01\x03\x05\x07\x09\x0B\x88\x92\x80\x00\x01\x02\x03\x04\xf0\x00\x35\x00') assert(p[Ether].dst == '00:02:04:06:08:0a') assert(p[Ether].src == '01:03:05:07:09:0b') assert(p[Ether].type == 0x8892) assert(p[ProfinetIO].frameID == 0x8000) assert(isinstance(p[ProfinetIO].payload, PNIORealTimeCyclicPDU)) assert(len(p[PNIORealTimeCyclicPDU].data) == 1) assert(isinstance(p[PNIORealTimeCyclicPDU].data[0], PNIORealTimeCyclicDefaultRawData)) assert(p[PNIORealTimeCyclicDefaultRawData].data == b'\x01\x02\x03\x04') assert(p[PNIORealTimeCyclicPDU].padding == b'') assert(p[PNIORealTimeCyclicPDU].cycleCounter == 0xf000) assert(p[PNIORealTimeCyclicPDU].dataStatus == 0x35) assert(p[PNIORealTimeCyclicPDU].transferStatus == 0) True = PROFIsafe parsing (query with F_CRC_SEED=0) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeControl, 2)(b'\x80\x80\x40\x01\x02\x03') assert(p.data == b'\x80\x80') assert(p.control == 0x40) assert(p.crc == 0x010203) True = PROFIsafe parsing (query with F_CRC_SEED=1) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeControlCRCSeed, 2)(b'\x80\x80\x40\x01\x02\x03\x04') assert(p.data == b'\x80\x80') assert(p.control == 0x40) assert(p.crc == 0x01020304) True = PROFIsafe parsing (response with F_CRC_SEED=0) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatus, 1)(b'\x80\x40\x01\x02\x03') assert(p.data == b'\x80') assert(p.status == 0x40) assert(p.crc == 0x010203) True = PROFIsafe parsing (response with F_CRC_SEED=1) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatusCRCSeed, 1)(b'\x80\x40\x01\x02\x03\x04') assert(p.data == b'\x80') assert(p.status == 0x40) assert(p.crc == 0x01020304) True = PROFIsafe building (query with F_CRC_SEED=0) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeControl, 2)(data = b'\x81\x80', control=0x40, crc=0x040506) assert(raw(p) == b'\x81\x80\x40\x04\x05\x06') = PROFIsafe building (query with F_CRC_SEED=1) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeControlCRCSeed, 2)(data = b'\x81\x80', control=0x02, crc=0x04050607) assert(raw(p) == b'\x81\x80\x02\x04\x05\x06\x07') = PROFIsafe building (response with F_CRC_SEED=0) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatus, 3)(data = b'\x01\x81\x00', status=0x01, crc=0x040506) assert(raw(p) == b'\x01\x81\x00\x01\x04\x05\x06') = PROFIsafe building (response with F_CRC_SEED=1) p = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatusCRCSeed, 3)(data = b'\x01\x81\x80', status=0x01, crc=0x04050607) assert(raw(p) == b'\x01\x81\x80\x01\x04\x05\x06\x07') conf.debug_dissector = old_conf_dissector