86890704fd
todo: add documentation & wireshark dissector
670 lines
27 KiB
Text
Executable file
670 lines
27 KiB
Text
Executable file
% PNIO RPC layer test campaign
|
|
|
|
+ Syntax check
|
|
= Import the PNIO RPC layer
|
|
from scapy.contrib.dce_rpc import *
|
|
from scapy.contrib.pnio_rpc import *
|
|
from scapy.modules.six import itervalues
|
|
|
|
= Check that we have UUIDs
|
|
|
|
for v in itervalues(RPC_INTERFACE_UUID):
|
|
assert(isinstance(v, UUID))
|
|
|
|
+ Check Block
|
|
|
|
= Block default values
|
|
bytes(Block()) == bytearray.fromhex('000000020100')
|
|
|
|
= Block basic example
|
|
bytes(Block(load=b'\x01\x02\x03')) == bytearray.fromhex('000000050100010203')
|
|
|
|
= Block has no payload (only padding)
|
|
p = Block(bytearray.fromhex('000000050100010203040506'))
|
|
p == Block(block_length=5, load=b'\x01\x02\x03') / conf.padding_layer(b'\x04\x05\x06')
|
|
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check IODControlReq
|
|
|
|
= IODControlReq default values
|
|
bytes(IODControlReq()) == bytearray.fromhex('0000001c01000000000000000000000000000000000000000000000000000000')
|
|
|
|
= IODControlReq basic example (IODControlReq PrmEnd control)
|
|
bytes(IODControlReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=2, ControlCommand_PrmEnd=1)) == bytearray.fromhex('0110001c010000000123456789abcdef0123456789abcdef0002000000010000')
|
|
|
|
= IODControlReq dissection
|
|
p = IODControlReq(bytearray.fromhex('0118001c010000000123456789abcdef0123456789abcdef0005000000400000ef'))
|
|
p == IODControlReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=5, ControlCommand_PrmBegin=1, block_type='IODBlockReq_connect_begin', block_length=28, padding=b'\0\0') / conf.padding_layer(b'\xef')
|
|
|
|
= IODControlReq response
|
|
p = p.get_response()
|
|
p == IODControlRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=5, block_type='IODBlockRes_connect_begin')
|
|
|
|
####################################################################
|
|
|
|
+ Check IODControlRes
|
|
|
|
= IODControlRes default values
|
|
bytes(IODControlRes()) == bytearray.fromhex('8110001c01000000000000000000000000000000000000000000000000080000')
|
|
|
|
= IODControlRes basic example (IODControlRes PrmEnd control)
|
|
bytes(IODControlRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=2, block_type='IODBlockRes_connect_end')) == bytearray.fromhex('8110001c010000000123456789abcdef0123456789abcdef0002000000080000')
|
|
|
|
= IODControlRes dissection
|
|
p = IODControlRes(bytearray.fromhex('8118001c010000000123456789abcdef0123456789abcdef0005000000080000ef'))
|
|
p == IODControlRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=5, block_type='IODBlockRes_connect_begin', block_length=28, padding=b'\0\0') / conf.padding_layer(b'\xef')
|
|
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check IODWriteReq
|
|
|
|
= IODWriteReq default values
|
|
bytes(IODWriteReq()) == bytearray.fromhex('0008003c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
|
|
|
|
= IODWriteReq basic example
|
|
bytes(IODWriteReq(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321
|
|
) / b'\xab\xcd'
|
|
) == bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcd')
|
|
|
|
= IODWriteReq dissection
|
|
p = IODWriteReq(bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcdef'))
|
|
p == IODWriteReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321, block_length=60, recordDataLength=2, padding='\0\0', RWPadding=b'\0'*24
|
|
) / b'\xab\xcd' / conf.padding_layer(b'\xef')
|
|
|
|
= IODWriteReq response
|
|
p = p.get_response()
|
|
p == IODWriteRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321)
|
|
|
|
####################################################################
|
|
|
|
+ Check IODWriteRes
|
|
|
|
= IODWriteRes default values
|
|
bytes(IODWriteRes()) == bytearray.fromhex('8008003c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')
|
|
|
|
= IODWriteRes basic example
|
|
bytes(IODWriteRes(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321
|
|
)) == bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000')
|
|
|
|
= IODWriteRes dissection
|
|
p = IODWriteRes(bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000ef'))
|
|
p == IODWriteRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321, recordDataLength=0, block_length=60, padding=b'\0\0', RWPadding=b'\0'*16
|
|
) / conf.padding_layer(b'\xef')
|
|
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check IODWriteMultipleReq
|
|
|
|
#########
|
|
= IODWriteMultipleReq default values
|
|
bytes(IODWriteMultipleReq()) == bytearray.fromhex('0008003c0100000000000000000000000000000000000000ffffffffffffffff0000e04000000000000000000000000000000000000000000000000000000000')
|
|
|
|
#########
|
|
= IODWriteMultipleReq basic example
|
|
bytes(IODWriteMultipleReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', blocks=[
|
|
IODWriteReq(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321
|
|
) / b'\xab\xcd',
|
|
IODWriteReq(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,
|
|
index=0x1234
|
|
) / b'\x01\x02',
|
|
])
|
|
) == bytearray.fromhex('0008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000086000000000000000000000000000000000000000000000000') + \
|
|
bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcd') + b'\0\0' + \
|
|
bytearray.fromhex('0008003c010000020123456789abcdef0123456789abcdef000000020003000400001234000000020000000000000000000000000000000000000000000000000102')
|
|
|
|
#########
|
|
= IODWriteMultipleReq dissection
|
|
p = IODWriteMultipleReq(
|
|
bytearray.fromhex('0008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000086000000000000000000000000000000000000000000000000') + \
|
|
bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcd') + b'\0\0' + \
|
|
bytearray.fromhex('0008003c010000020123456789abcdef0123456789abcdef000000020003000400001234000000020000000000000000000000000000000000000000000000000102') + b'\xef'
|
|
)
|
|
p == IODWriteMultipleReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', recordDataLength=0x86,
|
|
padding=b'\0'*2, RWPadding=b'\0'*24, block_length=60, blocks=[
|
|
IODWriteReq(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321, recordDataLength=2, padding=b'\0'*2, RWPadding=b'\0'*24, block_length=60
|
|
) / b'\xab\xcd',
|
|
IODWriteReq(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,
|
|
index=0x1234, recordDataLength=2, padding=b'\0'*2, RWPadding=b'\0'*24, block_length=60
|
|
) / b'\x01\x02',
|
|
]) / conf.padding_layer(b'\xef')
|
|
|
|
#########
|
|
= IODWriteMultipleReq response
|
|
p = p.get_response()
|
|
p == IODWriteMultipleRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', blocks=[
|
|
IODWriteRes(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321
|
|
),
|
|
IODWriteRes(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,
|
|
index=0x1234
|
|
),
|
|
])
|
|
|
|
|
|
####################################################################
|
|
|
|
+ Check IODWriteMultipleRes
|
|
|
|
= IODWriteMultipleRes default values
|
|
bytes(IODWriteMultipleRes()) == bytearray.fromhex('8008003c0100000000000000000000000000000000000000ffffffffffffffff0000e04000000000000000000000000000000000000000000000000000000000')
|
|
|
|
= IODWriteMultipleRes basic example
|
|
bytes(IODWriteMultipleRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', blocks=[
|
|
IODWriteRes(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321
|
|
),
|
|
IODWriteRes(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,
|
|
index=0x1234
|
|
),
|
|
])
|
|
) == bytearray.fromhex('8008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000080000000000000000000000000000000000000000000000000') + \
|
|
bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000') + \
|
|
bytearray.fromhex('8008003c010000020123456789abcdef0123456789abcdef00000002000300040000123400000000000000000000000000000000000000000000000000000000')
|
|
|
|
= IODWriteMultipleRes dissection
|
|
p = IODWriteMultipleRes(
|
|
bytearray.fromhex('8008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000080000000000000000000000000000000000000000000000000') + \
|
|
bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000') + \
|
|
bytearray.fromhex('8008003c010000020123456789abcdef0123456789abcdef00000002000300040000123400000000000000000000000000000000000000000000000000000000') + b'\xef'
|
|
)
|
|
p == IODWriteMultipleRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', recordDataLength=0x80,
|
|
padding=b'\0'*2, RWPadding=b'\0'*16, block_length=60, blocks=[
|
|
IODWriteRes(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,
|
|
index=0x4321, recordDataLength=0, padding=b'\0'*2, RWPadding=b'\0'*16, block_length=60
|
|
),
|
|
IODWriteRes(
|
|
ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,
|
|
index=0x1234, recordDataLength=0, padding=b'\0'*2, RWPadding=b'\0'*16, block_length=60
|
|
),
|
|
]) / conf.padding_layer(b'\xef')
|
|
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check ARBlockReq
|
|
|
|
= ARBlockReq default values
|
|
bytes(ARBlockReq()) == bytearray.fromhex('0101003601000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103e888920000')
|
|
|
|
= ARBlockReq basic example
|
|
bytes(ARBlockReq(
|
|
ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1,
|
|
CMInitiatorObjectUUID='dea00000-6c97-11d1-8271-010203040506', ARProperties_ParametrizationServer='CM_Initator',
|
|
CMInitiatorStationName='plc1')
|
|
) == bytearray.fromhex('0101003a010000010123456789abcdef0123456789abcdef0001000000000000dea000006c9711d182710102030405060000001103e888920004') + b'plc1'
|
|
|
|
= ARBlockReq dissection
|
|
p = ARBlockReq(bytearray.fromhex('0101003a010000010123456789abcdef0123456789abcdef0001010203040506dea000006c9711d182710102030405060000001103e888920004') + b'plc1' + b'\xef')
|
|
p == ARBlockReq(
|
|
ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1,
|
|
CMInitiatorObjectUUID='dea00000-6c97-11d1-8271-010203040506', ARProperties_ParametrizationServer='CM_Initator',
|
|
CMInitiatorMacAdd='01:02:03:04:05:06', StationNameLength=4, CMInitiatorStationName='plc1', block_length=58
|
|
) / conf.padding_layer(b'\xef')
|
|
|
|
= ARBlockReq response
|
|
p = p.get_response()
|
|
p == ARBlockRes(ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1)
|
|
|
|
####################################################################
|
|
|
|
+ Check ARBlockRes
|
|
|
|
= ARBlockRes default values
|
|
bytes(ARBlockRes()) == bytearray.fromhex('8101001e010000010000000000000000000000000000000000000000000000008892')
|
|
|
|
= ARBlockRes basic example
|
|
bytes(
|
|
ARBlockRes(ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1)
|
|
) == bytearray.fromhex('8101001e010000010123456789abcdef0123456789abcdef00010000000000008892')
|
|
|
|
= ARBlockRes dissection
|
|
p = ARBlockRes(bytearray.fromhex('8101001e010000010123456789abcdef0123456789abcdef00010102030405068892ef'))
|
|
p == ARBlockRes(
|
|
ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1,
|
|
CMResponderMacAdd='01:02:03:04:05:06', block_length=30) / conf.padding_layer(b'\xef')
|
|
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check IOCRBlockReq
|
|
|
|
= IOCRBlockReq default values
|
|
bytes(IOCRBlockReq()) == bytearray.fromhex('0102002a010000010001889200000000002880000020002000010000ffffffff000a000ac0000000000000000000')
|
|
|
|
= IOCRAPI default values
|
|
bytes(IOCRAPI()) == bytearray.fromhex('0000000000000000')
|
|
|
|
= IOCRAPIObject default values
|
|
bytes(IOCRAPIObject()) == bytearray.fromhex('000000000000')
|
|
|
|
= IOCRBlockReq basic example
|
|
p = IOCRBlockReq(
|
|
IOCRType='OutputCR', IOCRReference=1, SendClockFactor=2,
|
|
ReductionRatio=32, DataLength=47, FrameID=0x8014,
|
|
APIs=[
|
|
IOCRAPI(
|
|
API=4,
|
|
IODataObjects=[
|
|
IOCRAPIObject(SlotNumber=2, SubslotNumber=1, FrameOffset=0),
|
|
IOCRAPIObject(SlotNumber=1, SubslotNumber=1, FrameOffset=9),
|
|
]
|
|
),
|
|
IOCRAPI(
|
|
API=0,
|
|
IODataObjects=[
|
|
IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=15),
|
|
],
|
|
IOCSs=[
|
|
IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=4),
|
|
],
|
|
),
|
|
]
|
|
)
|
|
bytes(p) == \
|
|
bytearray.fromhex('01020052010000020001889200000000002f80140002002000010000ffffffff000a000ac0000000000000000002' + \
|
|
'0000000400020002000100000001000100090000' + \
|
|
'00000000000100030001000f0001000300010004')
|
|
|
|
= IOCRBlockReq dissection
|
|
p = IOCRBlockReq(
|
|
bytearray.fromhex('01020052010000020001889200000000002f80140002002000010000ffffffff000a000ac0000102030405060002' + \
|
|
'0000000400020002000100000001000100090000' + \
|
|
'00000000000100030001000f0001000300010004') + b'\xef')
|
|
p == IOCRBlockReq(
|
|
IOCRType='OutputCR', IOCRReference=1, SendClockFactor=2, IOCRMulticastMACAdd='01:02:03:04:05:06',
|
|
ReductionRatio=32, DataLength=47, FrameID=0x8014, block_length=82,
|
|
NumberOfAPIs=2, APIs=[
|
|
IOCRAPI(
|
|
API=4,
|
|
NumberOfIODataObjects=2, IODataObjects=[
|
|
IOCRAPIObject(SlotNumber=2, SubslotNumber=1, FrameOffset=0),
|
|
IOCRAPIObject(SlotNumber=1, SubslotNumber=1, FrameOffset=9),
|
|
],
|
|
NumberOfIOCS=0
|
|
),
|
|
IOCRAPI(
|
|
API=0,
|
|
NumberOfIODataObjects=1, IODataObjects=[
|
|
IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=15),
|
|
],
|
|
NumberOfIOCS=1, IOCSs=[
|
|
IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=4),
|
|
],
|
|
),
|
|
]
|
|
) / conf.padding_layer(b'\xef')
|
|
|
|
= IOCRBlockReq response
|
|
p = p.get_response()
|
|
p == IOCRBlockRes(IOCRType='OutputCR', IOCRReference=1, FrameID=0x8014)
|
|
|
|
####################################################################
|
|
|
|
+ Check IOCRBlockRes
|
|
|
|
= IOCRBlockRes default values
|
|
bytes(IOCRBlockRes()) == bytearray.fromhex('810200080100000100018000')
|
|
|
|
= IOCRBlockRes basic example
|
|
bytes(
|
|
IOCRBlockRes(IOCRType='InputCR', IOCRReference=2, FrameID=0x8014)
|
|
) == bytearray.fromhex('810200080100000100028014')
|
|
|
|
= IOCRBlockRes dissection
|
|
p = IOCRBlockRes(bytearray.fromhex('810200080100000100028014ef'))
|
|
p == IOCRBlockRes(IOCRType='InputCR', IOCRReference=2, FrameID=0x8014,
|
|
block_length=8) / conf.padding_layer(b'\xef')
|
|
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check ExpectedSubmoduleBlockReq
|
|
|
|
= ExpectedSubmoduleBlockReq default values
|
|
bytes(ExpectedSubmoduleBlockReq()) == bytearray.fromhex('0104000401000000')
|
|
|
|
= ExpectedSubmoduleAPI default values
|
|
bytes(ExpectedSubmoduleAPI()) == bytearray.fromhex('0000000000000000000000000000')
|
|
|
|
= ExpectedSubmodule default values
|
|
bytes(ExpectedSubmodule()) == bytearray.fromhex('0000000000000000')
|
|
|
|
= ExpectedSubmoduleDataDescription default values
|
|
bytes(ExpectedSubmoduleDataDescription()) == bytearray.fromhex('000000000000')
|
|
|
|
= ExpectedSubmoduleBlockReq basic example
|
|
p = ExpectedSubmoduleBlockReq(
|
|
APIs=[
|
|
ExpectedSubmoduleAPI(
|
|
API=4, SlotNumber=2, ModuleIdentNumber=0x08c4,
|
|
Submodules=[
|
|
ExpectedSubmodule(
|
|
SubslotNumber=1, SubmoduleIdentNumber=0x0123,
|
|
SubmoduleProperties_Type='INPUT_OUTPUT',
|
|
DataDescription=[
|
|
ExpectedSubmoduleDataDescription(
|
|
DataDescription='Output',
|
|
SubmoduleDataLength=5,
|
|
LengthIOPS=2, LengthIOCS=0
|
|
),
|
|
ExpectedSubmoduleDataDescription(
|
|
DataDescription='Input',
|
|
SubmoduleDataLength=3,
|
|
LengthIOPS=1, LengthIOCS=2
|
|
)
|
|
]
|
|
),
|
|
]
|
|
),
|
|
]
|
|
)
|
|
bytes(p) == \
|
|
bytearray.fromhex('0104002601000001') + \
|
|
bytearray.fromhex('000000040002000008c400000001') + \
|
|
bytearray.fromhex('0001000001230003') + \
|
|
bytearray.fromhex('000200050002') + \
|
|
bytearray.fromhex('000100030201')
|
|
|
|
= ExpectedSubmoduleBlockReq dissection
|
|
p = ExpectedSubmoduleBlockReq(
|
|
bytearray.fromhex('0104002601000001') + \
|
|
bytearray.fromhex('000000040002000008c400000001') + \
|
|
bytearray.fromhex('0001000001230003') + \
|
|
bytearray.fromhex('000200050002') + \
|
|
bytearray.fromhex('000100030201') + b'\xef'
|
|
)
|
|
p == ExpectedSubmoduleBlockReq(block_length=38,
|
|
NumberOfAPIs=1, APIs=[
|
|
ExpectedSubmoduleAPI(
|
|
API=4, SlotNumber=2, ModuleIdentNumber=0x08c4,
|
|
NumberOfSubmodules=1 ,Submodules=[
|
|
ExpectedSubmodule(
|
|
SubslotNumber=1, SubmoduleIdentNumber=0x0123,
|
|
SubmoduleProperties_Type='INPUT_OUTPUT',
|
|
DataDescription=[
|
|
ExpectedSubmoduleDataDescription(
|
|
DataDescription='Output',
|
|
SubmoduleDataLength=5,
|
|
LengthIOPS=2, LengthIOCS=0
|
|
),
|
|
ExpectedSubmoduleDataDescription(
|
|
DataDescription='Input',
|
|
SubmoduleDataLength=3,
|
|
LengthIOPS=1, LengthIOCS=2
|
|
)
|
|
]
|
|
),
|
|
]
|
|
),
|
|
]
|
|
) / conf.padding_layer(b'\xef')
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check PNIOServiceReqPDU
|
|
|
|
= PNIOServiceReqPDU basic example
|
|
* PNIOServiceReqPDU must always be placed above a DCE/RPC layer as it requires the endianness field
|
|
p = DceRpc() / PNIOServiceReqPDU(blocks=[
|
|
Block(load=b'\x01\x02')
|
|
])
|
|
s = bytes(p)
|
|
# Remove the random UUID part before comparison
|
|
s[:18] + s[24:] == \
|
|
bytearray.fromhex('0400000000000000dea000006c9711d18271' + 'dea000016c9711d1827100a02442df7d000000000000000000000000000000000000000000000001000000000000ffffffff001c00000000' + \
|
|
'0000000800000008000000080000000000000008' +
|
|
'0000000401000102')
|
|
|
|
= PNIOServiceReqPDU dissection
|
|
p = DceRpc(
|
|
bytes(bytearray.fromhex('0400000000000000dea000006c9711d18271010203040506dea000016c9711d1827100a02442df7d000000000000000000000000000000000000000000000001000000000000ffffffff001c00000000' + \
|
|
'0000000f000000080000000f0000000000000008' + \
|
|
'0000000401000102ef')
|
|
))
|
|
bytes(p.payload) == bytes(PNIOServiceReqPDU(args_length=8, args_max=15, max_count=15, actual_count=8,
|
|
blocks=[
|
|
Block(block_length=4, load=b'\x01\x02')
|
|
]
|
|
) / b'\xef')
|
|
|
|
|
|
####################################################################
|
|
####################################################################
|
|
|
|
+ Check PNIOServiceResPDU
|
|
|
|
= PNIOServiceResPDU basic example
|
|
* PNIOServiceResPDU must always be placed above a DCE/RPC layer as it requires the endianness field
|
|
p = DceRpc() / PNIOServiceResPDU(blocks=[
|
|
Block(load=b'\x01\x02')
|
|
])
|
|
s = bytes(p)
|
|
# Remove the random UUID part before comparison
|
|
s[:18] + s[24:] == \
|
|
bytearray.fromhex('0402000000000000dea000006c9711d18271' + 'dea000026c9711d1827100a02442df7d000000000000000000000000000000000000000000000001000000000000ffffffff001c00000000' + \
|
|
'0000000000000008000000080000000000000008' + \
|
|
'0000000401000102')
|
|
|
|
= PNIOServiceResPDU dissection
|
|
p = DceRpc(
|
|
bytes(bytearray.fromhex('0402000000000000dea000006c9711d18271010203040506dea000026c9711d1827100a02442df7d000000000000000000000000000000000000000000000001000000000000ffffffff001c00000000' + \
|
|
'00001234000000080000000f0000000000000008' + \
|
|
'0000000401000102ef')
|
|
))
|
|
bytes(p.payload) == bytes(PNIOServiceResPDU(status=0x1234, args_length=8, max_count=15, actual_count=8,
|
|
blocks=[
|
|
Block(block_length=4, load=b'\x01\x02')
|
|
]
|
|
) / b'\xef')
|
|
|
|
####################################################################
|
|
## Some usual examples ##
|
|
####################################################################
|
|
|
|
+ Check some basic examples
|
|
|
|
#### Connect Request
|
|
= A PNIO RPC Connect Request
|
|
p = DceRpc(
|
|
endianness='little', opnum=0, sequence_num=0,
|
|
object_uuid='dea00000-6c97-11d1-8271-010203040506',
|
|
activity='01234567-89ab-cdef-0123-456789abcdef'
|
|
) / PNIOServiceReqPDU(
|
|
blocks=[
|
|
# AR block
|
|
ARBlockReq(
|
|
ARType='IOCARSingle', ARUUID='fedcba98-7654-3210-fedc-ba9876543210', SessionKey=0,
|
|
CMInitiatorMacAdd='01:02:03:04:05:06', CMInitiatorStationName='plc-1',
|
|
CMInitiatorObjectUUID='dea00000-6c97-11d1-8271-010203040506', ARProperties_ParametrizationServer='CM_Initator'
|
|
),
|
|
# IO CR input block
|
|
IOCRBlockReq(
|
|
IOCRType='InputCR', IOCRReference=1, SendClockFactor=2,
|
|
ReductionRatio=32, DataLength=40,
|
|
APIs=[
|
|
IOCRAPI(
|
|
API=0,
|
|
IODataObjects=[
|
|
IOCRAPIObject(SlotNumber=3, SubslotNumber=1,FrameOffset=15),
|
|
],
|
|
IOCSs=[
|
|
IOCRAPIObject(SlotNumber=3, SubslotNumber=1,FrameOffset=4),
|
|
],
|
|
),
|
|
]
|
|
),
|
|
# IO CR output block
|
|
IOCRBlockReq(
|
|
IOCRType='OutputCR', IOCRReference=2, SendClockFactor=8, ReductionRatio=32,
|
|
DataLength=52, FrameID=0xffff,
|
|
APIs=[
|
|
IOCRAPI(
|
|
API=0,
|
|
IODataObjects=[
|
|
IOCRAPIObject(SlotNumber=3, SubslotNumber=1,FrameOffset=0),
|
|
IOCRAPIObject(SlotNumber=1, SubslotNumber=2,FrameOffset=9),
|
|
],
|
|
),
|
|
]
|
|
),
|
|
# List of expected submodules
|
|
ExpectedSubmoduleBlockReq(
|
|
APIs=[
|
|
ExpectedSubmoduleAPI(
|
|
API=0, SlotNumber=3, ModuleIdentNumber=0x08c4,
|
|
Submodules=[
|
|
ExpectedSubmodule(
|
|
SubslotNumber=1, SubmoduleIdentNumber=0x0124,
|
|
SubmoduleProperties_Type='INPUT_OUTPUT',
|
|
DataDescription=[
|
|
ExpectedSubmoduleDataDescription(
|
|
DataDescription='Output',
|
|
SubmoduleDataLength=3,
|
|
LengthIOPS=1, LengthIOCS=1
|
|
),
|
|
ExpectedSubmoduleDataDescription(
|
|
DataDescription='Input',
|
|
SubmoduleDataLength=5,
|
|
LengthIOPS=2, LengthIOCS=0
|
|
)
|
|
]
|
|
),
|
|
]
|
|
),
|
|
]
|
|
),
|
|
ExpectedSubmoduleBlockReq(
|
|
APIs=[
|
|
ExpectedSubmoduleAPI(
|
|
API=0, SlotNumber=1, ModuleIdentNumber=0x08c3,
|
|
Submodules=[
|
|
ExpectedSubmodule(
|
|
SubslotNumber=2, SubmoduleIdentNumber=0x0424,
|
|
SubmoduleProperties_Type='OUTPUT',
|
|
DataDescription=[
|
|
ExpectedSubmoduleDataDescription(
|
|
DataDescription='Output',
|
|
SubmoduleDataLength=5,
|
|
LengthIOPS=1, LengthIOCS=0
|
|
)
|
|
]
|
|
),
|
|
]
|
|
),
|
|
]
|
|
),
|
|
]
|
|
)
|
|
bytes(p) == bytearray.fromhex(
|
|
'04000000100000000000a0de976cd11182710102030405060100a0de976cd111827100a02442df7d67452301ab89efcd0123456789abcdef0000000001000000000000000000ffffffff250100000000' + \
|
|
'1101000011010000110100000000000011010000' + \
|
|
'0101003b01000001fedcba9876543210fedcba98765432100000010203040506dea000006c9711d182710102030405060000001103e888920005') + b'plc-1' + \
|
|
bytearray.fromhex('0102003e010000010001889200000000002880000002002000010000ffffffff000a000ac0000000000000000001' + \
|
|
'00000000000100030001000f0001000300010004' + \
|
|
'0102003e0100000200028892000000000034ffff0008002000010000ffffffff000a000ac0000000000000000001' + \
|
|
'0000000000020003000100000001000200090000' + \
|
|
'0104002601000001000000000003000008c400000001' + \
|
|
'0001000001240003' + \
|
|
'000200030101' + \
|
|
'000100050002' + \
|
|
'0104002001000001000000000001000008c300000001' + \
|
|
'0002000004240002' + \
|
|
'000200050001')
|
|
|
|
|
|
#### Write Request
|
|
= A PNIO RPC Write Request
|
|
p = DceRpc(
|
|
endianness='little', opnum=2, sequence_num=1,
|
|
object_uuid='dea00000-6c97-11d1-8271-010203040506',
|
|
activity='01234567-89ab-cdef-0123-456789abcdef'
|
|
) / PNIOServiceReqPDU(
|
|
blocks=[
|
|
IODWriteMultipleReq(
|
|
seqNum=0, ARUUID='fedcba98-7654-3210-fedc-ba9876543210', blocks=[
|
|
IODWriteReq(
|
|
seqNum=1, API=0, slotNumber=1, subslotNumber=1, index=0x123,
|
|
ARUUID='fedcba98-7654-3210-fedc-ba9876543210'
|
|
) / b'\x01\x02',
|
|
IODWriteReq(
|
|
seqNum=2, API=0, slotNumber=3, subslotNumber=1,
|
|
ARUUID='fedcba98-7654-3210-fedc-ba9876543210'
|
|
) / FParametersBlock(
|
|
F_CRC_Seed=1, F_CRC_Length='CRC-24', F_Source_Add=0xc1, F_Dest_Add=0xc2,
|
|
F_WD_Time=500, F_Par_CRC=0x1234
|
|
),
|
|
]
|
|
)
|
|
]
|
|
)
|
|
bytes(p) == bytearray.fromhex(
|
|
'04000000100000000000a0de976cd11182710102030405060100a0de976cd111827100a02442df7d67452301ab89efcd0123456789abcdef0000000001000000010000000200ffffffffe20000000000' + \
|
|
'ce000000ce000000ce00000000000000ce000000' + \
|
|
'0008003c01000000fedcba9876543210fedcba9876543210ffffffffffffffff0000e0400000008e' + '00' * 24 + \
|
|
'0008003c01000001fedcba9876543210fedcba987654321000000000000100010000012300000002' + '00' * 24 + \
|
|
'01020000' + \
|
|
'0008003c01000002fedcba9876543210fedcba98765432100000000000030001000001000000000a' + '00' * 24 + \
|
|
'484000c100c201f41234')
|
|
|
|
|
|
#### PrmEnd control Request
|
|
= A PNIO RPC PrmEnd Control Request
|
|
p = DceRpc(
|
|
endianness='little', opnum=0, sequence_num=2,
|
|
object_uuid='dea00000-6c97-11d1-8271-010203040506',
|
|
activity='01234567-89ab-cdef-0123-456789abcdef'
|
|
) / PNIOServiceReqPDU(
|
|
blocks=[
|
|
IODControlReq(ARUUID='fedcba98-7654-3210-fedc-ba9876543210', SessionKey=0, ControlCommand_PrmEnd=1)
|
|
]
|
|
)
|
|
bytes(p) == bytearray.fromhex(
|
|
'04000000100000000000a0de976cd11182710102030405060100a0de976cd111827100a02442df7d67452301ab89efcd0123456789abcdef0000000001000000020000000000ffffffff340000000000' + \
|
|
'2000000020000000200000000000000020000000' + \
|
|
'0110001c01000000fedcba9876543210fedcba98765432100000000000010000')
|
|
|
|
#### ApplicationReady control Request
|
|
= A PNIO RPC PrmEnd Control Request
|
|
p = DceRpc(
|
|
endianness='little', opnum=0, sequence_num=0,
|
|
object_uuid='dea00000-6c97-11d1-8271-060504030201',
|
|
activity='01020304-0506-0708-090a-0b0c0d0e0f00',
|
|
interface_uuid=RPC_INTERFACE_UUID['UUID_IO_ControllerInterface'],
|
|
) / PNIOServiceReqPDU(
|
|
blocks=[
|
|
IODControlReq(ARUUID='fedcba98-7654-3210-fedc-ba9876543210', SessionKey=0, ControlCommand_ApplicationReady=1)
|
|
]
|
|
)
|
|
bytes(p) == bytearray.fromhex(
|
|
'04000000100000000000a0de976cd11182710605040302010200a0de976cd111827100a02442df7d0403020106050807090a0b0c0d0e0f000000000001000000000000000000ffffffff340000000000' + \
|
|
'2000000020000000200000000000000020000000' + \
|
|
'0112001c01000000fedcba9876543210fedcba98765432100000000000020000')
|