pjkundert / cpppo

Communications Protocol Python Parser and Originator -- EtherNet/IP CIP
https://hardconsulting.com/products/6-cpppo-enip-api
Other
332 stars 109 forks source link

Identity response from PowerFlex makes client session invalid #45

Open corbers opened 6 years ago

corbers commented 6 years ago

I'm using the cpppo library to discover devices on a network. I'm using the client API to send out a list identity request over UDP. Unfortunately, one of the devices discovered is a PowerFlex 700 which returns a CIP packet with a 0 length field. Looking at the comments in your code it appears that you're aware of this bug in PowerFlex devices and have attempted to code against this in your parser. Unfortunately, this doesn't appear to work for my scenario and so the client object is left in an invalid state, presumably because it's got unparsed data that it's not sure what to do with. The problem I've got then is that the situation is not recoverable; there's no way I can continue the process. The only thing I can do is start again which leads to the same issue. Alternatively, I could use TCP and step through the network addresses for the subnet but this is really inefficient.

If you have any suggestions on how I might recover from this issue that would be great. To help, here's the packet of data that's returned by the Power Flex in Hex.

63000000000000000000000000000000000000000000000001000c00270001000002af129b7d7a91000000000000000001007b0068006e03610020e6242020506f776572466c65782037303020564320343830562032343841202020202020ff

And here's the relevant part from the cpppo logger...

11-16 19:52:16.079 MainThread enip.cli INFO     __next__   EtherNet/IP--> 155.125.122.145:44818 rcvd    96: "c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x0c\x00'\x00\x01\x00\x00\x02\xaf\x12\x9b}z\x91\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00{\x00h\x00\n\x03a\x00 \xe6$  PowerFlex 700 VC 480V 248A      \xff"
11-16 19:52:16.084 MainThread cpppo    INFO     terminate                                  ( header.((empty)) :             =>         enip.command     = 99 (format '<H' over array('c', 'c\x00'))
11-16 19:52:16.086 MainThread cpppo    INFO     terminate                                  ( header.((empty)) :             =>          enip.length     = 0 (format '<H' over array('c', '\x00\x00'))
11-16 19:52:16.091 MainThread cpppo    INFO     terminate                                  ( header.((empty)) :             =>  enip.session_handle     = 0 (format '<I' over array('c', '\x00\x00\x00\x00'))
11-16 19:52:16.095 MainThread cpppo    INFO     terminate                                  ( header.((empty)) :             =>          enip.status     = 0 (format '<I' over array('c', '\x00\x00\x00\x00'))
11-16 19:52:16.106 MainThread cpppo    INFO     terminate                                  ( header.((empty)) :             =>         enip.options     = 0 (format '<I' over array('c', '\x00\x00\x00\x00'))
11-16 19:52:16.108 MainThread enip.cli INFO     __next__   EtherNet/IP    155.125.122.255:44818 done:                         ((enip.((payload.((byte))) -> ((payload.; next byte 1120: '\x01'    : {'peer': ('155.125.122.145', 44818), 'enip': {'status': 0, 'sender_context': {'input': array('c', '\x00\x00\x00\x00\x00\x00\x00\x00')}, 'session_handle': 0, 'length': 0, 'command': 99, 'options': 0}}
11-16 19:52:16.109 MainThread enip.cli INFO     __next__   Returning result: {'peer': ('155.125.122.145', 44818), 'enip': {'status': 0, 'sender_context': {'input': array('c', '\x00\x00\x00\x00\x00\x00\x00\x00')}, 'session_handle': 0, 'length': 0, 'command': 99, 'options': 0}}

Thanks for a great library.