nimbuscontrols / EIPScanner

Free implementation of EtherNet/IP in C++
https://eipscanner.readthedocs.io/en/latest/
MIT License
224 stars 90 forks source link

Implicite Messaging - missing data #64

Open chruetli opened 2 years ago

chruetli commented 2 years ago

I have a question about using Implicite Messaging. After some time I found out how to apply my EDS file to the ImplicitMessagingExample.cpp. When I run the example the following output is produced:

[DEBUG] Opened TCP socket fd=3
[DEBUG] Connecting to 192.168.0.2:44818
[INFO] Registered session 748366592
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Open IO connection O2T_ID=2b9d32 T2O_ID=63cf0001 SerialNumber 1
[DEBUG] Opened UDP socket fd=4
[INFO] Open UDP socket to send data to 192.168.0.2:2222
[DEBUG] Opened UDP socket fd=5
[WARNING] Connection SeriaNumber=1 is closed by timeout
[INFO] Closed
[DEBUG] Close UDP socket fd=4
[WARNING] Attempt to close an already closed connection
[DEBUG] Close UDP socket fd=5
[INFO] Unregistered session 748366592
[DEBUG] Close TCP socket fd=3

The corresponding wireshark dump can be found in the attached file. implicitMessagingExample.zip

In the Wireshark dump one can see the following:

No. Time        Source      Source Port Destination Protocol    Dest Port   Length  Info
27  2.455733    192.168.0.2 2222        192.168.0.5 CIP I/O     2222        70  Connection: ID=0x63CF0001, SEQ=0000000084, T->O
31  3.314139    192.168.0.5 64662       192.168.0.2 CIP I/O     2222        74  Connection: ID=0x002B9D32, SEQ=0000000001, O->T
36  3.455587    192.168.0.2 2222        192.168.0.5 CIP I/O     64662       70  Connection: ID=0x63CF0001, SEQ=0000000085
38  4.338032    192.168.0.5 64662       192.168.0.2 CIP I/O     2222        74  Connection: ID=0x002B9D32, SEQ=0000000002, O->T
39  4.455630    192.168.0.2 2222        192.168.0.5 CIP I/O     64662       70  Connection: ID=0x63CF0001, SEQ=0000000086
47  5.372058    192.168.0.5 64662       192.168.0.2 CIP I/O     2222        74  Connection: ID=0x002B9D32, SEQ=0000000003, O->T
48  5.455641    192.168.0.2 2222        192.168.0.5 CIP I/O     64662       70  Connection: ID=0x63CF0001, SEQ=0000000087

There is traffic from target to originator and vice versa. But none of these packages is printed in the example program. What looks strange to me is the fact that the connection ID=0x63CF0001 changes the port between package 27 and 36. Is there something I did wrong?

Best regards Mario

jadamroth commented 2 years ago

Hi,

I apologize - I can help with bugs or specific questions about the library, but I'm not able to assist right away for connectivity questions, particularly with implicit messaging.

Most of the issues that people open are related to connecting their device via implicit messaging, and it takes too much time to remotely assist with a device I don't have in my possession.

I will leave this issue open in case anyone else is able to help. In the meantime, please refer to these other issues with implicit messaging connectivity questions:

Side note - We are considering creating a service that helps people configure and connect to industrial devices. If this is something that is of interest, please let me know.

chruetli commented 2 years ago

Thank you for the answer Adam, I can understand your reservation.

I will further investigate the problem with my device and keep the thread updated. Maybe there is a low hanging fruit I don't/can't see or some strange bahaviour catching your eyes...

BaseSocket::select(std::vector<BaseSocket::SPtr> sockets, ...) is the place where data from sockets are read. The sockets are collected by the ConnectionManager which loops over the _socketMap. My problem is that the initial connection

ioConnection->_socket = std::make_unique<UDPSocket>(si->getRemoteEndPoint().getHost(), EIP_DEFAULT_IMPLICIT_PORT);

is not registred in the _socketMap - so the data sent to it will not be received.

Maybe one should change this part of code in ConnectionManager.cpp:

            } else {
                ioConnection->_socket = std::make_unique<UDPSocket>(si->getRemoteEndPoint().getHost(), EIP_DEFAULT_IMPLICIT_PORT);
            }

            Logger(LogLevel::INFO) << "Open UDP socket to send data to "
                    << ioConnection->_socket->getRemoteEndPoint().toString();

            findOrCreateSocket(sockets::EndPoint(si->getRemoteEndPoint().getHost(), EIP_DEFAULT_IMPLICIT_PORT));

Instead of creating a UDPSocket socket directly the socket may be created in findOrCreateSocket and assigned accordingly... But I don't know if this is a valid (sens of Ethernet/IP spec) solution. Any thoughts?

chruetli commented 2 years ago

I went by the idea above and changed the code acordingly to:

- ioConnection->_socket = std::make_unique<UDPSocket>(si->getRemoteEndPoint().getHost(), EIP_DEFAULT_IMPLICIT_PORT);
+ auto socket = findOrCreateSocket(sockets::EndPoint(si->getRemoteEndPoint().getHost(), EIP_DEFAULT_IMPLICIT_PORT));
+ ioConnection->_socket = std::make_unique<UDPSocket>(*socket.get());

As described in the message above (https://github.com/nimbuscontrols/EIPScanner/issues/64#issuecomment-902473687) there is a new socket created for the ioConnection. And later the method findOrCreateSocket is called with the same end point. But the socket for the ioConnection is not added to the _socketMap so no one listen to it. The fix works and I get the messages from my device. But the implementation is not ok. findOrCreateSocket registers the socket as a shared pointer and for ioConnection it is again used but as a unique pointer... (and it's now closed twice as it is used twice...) Any ideas?

My connection dump:

[DEBUG] Opened TCP socket fd=3
[DEBUG] Connecting to 192.168.0.2:44818
[INFO] Registered session 748366592
[INFO] Send request: service=0x54 epath=[classId=6 objectId=1]
[INFO] Open IO connection O2T_ID=2b9d32 T2O_ID=a7e70001 SerialNumber 1
[DEBUG] Opened UDP socket fd=4
[INFO] Open UDP socket to send data to 192.168.0.2:2222
[DEBUG] Received data from connection T2O_ID=a7e70001
[INFO] Received: secNum=29 data=[0][0][10][c][0][0][c0][de]
[DEBUG] Received data from connection T2O_ID=a7e70001
[INFO] Received: secNum=30 data=[0][0][10][c][0][0][c0][de]
[DEBUG] Received data from connection T2O_ID=a7e70001
...
[INFO] Received: secNum=46 data=[0][0][10][c][0][0][c0][de]
[DEBUG] Received data from connection T2O_ID=a7e70001
[INFO] Received: secNum=47 data=[0][0][10][c][0][0][c0][de]
[INFO] Close connection connection T2O_ID=a7e70001
[INFO] Send request: service=0x4e epath=[classId=6 objectId=1]
[DEBUG] Close UDP socket fd=4
[DEBUG] Close UDP socket fd=4
[INFO] Unregistered session 748366592
[DEBUG] Close TCP socket fd=3
LiamMZ commented 2 years ago

@chruetli Did you ever find a good solution to this problem?

chruetli commented 2 years ago

@LiamMZ The changes I posted on 20/24 Aug work good for me. I use them since. But I would be happy to have another set of eyes looking on the problem.

LiamMZ commented 2 years ago

@LiamMZ The changes I posted on 20/24 Aug work good for me. I use them since. But I would be happy to have another set of eyes looking on the problem.

I had two issues on my end:

  1. my network configuration for the VM I was running my scanner on was set to NAT and I needed it to be set to bridged adapter
  2. There was a bug in the adapter library I was using
nicktramp commented 9 months ago

I had a similar (if not the same) issue. Changing the UDP socket being created in the ForwardOpen() call to UDPBoundSocket type (to ensure it is actually bound) solved the issue for me, without creating multiple sockets (it was found in the _socketMap as well as the _connectionMap used to handle the connections).

@chruetli @LiamMZ (and anyone else) If you're willing and able, would you mind trying the library with these changes? You can find my fork at https://github.com/FikeCorp/EIPScanner/tree/brooks.

chruetli commented 9 months ago

@nicktramp Nick, this sounds good an promising! I will give it a try as soon as I have some time!