esp32_bluetooth_classic_sni.../libs/scapy/contrib/pnio.uts
Matheus Eduardo Garbelini 86890704fd initial commit
todo: add documentation & wireshark dissector
2021-08-31 19:51:03 +08:00

228 lines
7.6 KiB
Text
Executable file

# 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