is there any way to get ether/ip headers via gen_tcp? - tcp

is there any way to get not only body of incoming message. but also ether/IP headers of it? Now i'm using gen_tcp and receive messages by active controlling process.
for now socket is opened via 'of_driver' in such way:
gen_tcp:connect(IpAddr, Port, [binary, {packet, raw}, {active, false}],CONNECT_TIMEOUT)

As far as I know, you can't get Ethernet or IP headers through gen_tcp. You could use the procket library to open a raw socket. (The {packet, raw} option passed to gen_tcp doesn't refer to a "raw" socket; it just means that gen_tcp doesn't try to interpret the TCP byte stream to split it into packets.)

Related

TCP three way handshake

In the TCP three way handshake connection procedure does the client (the one who initiated the connection) send to the server any data payload joined with the ACK packet in the third step ?
The last ACK in the TCP handshake can already contain a payload. But, this is usually not done since the application first calls connect and then will either wait for the server to reply or send its first data. Since the kernel does not know what the application will do next it will already send out the ACK within the connect so that the server knows as fast as possible that the connection is established.
Depending on your OS it might be possible to change this behavior and send the ACK together with the first data. In Linux this can be achieved by explicitly disabling quick ack before connecting:
int off = 0;
setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &off, sizeof(off));
connect(fd,...)

How to get device information from a remote modbus service?

We need to send a message to a remote modbus service listening on por 502 and get as a response the device information, the same way shodan (https://www.shodan.io) does when you search from an IP address running a modbus service. We have read modbus specifications and tried to build a message but we send it to the server over TCP and it never responds.
For example, the following message should do the trick but does not work for us:
002B0E0104
00: address, not used.
2B: function code for get information
0E: additional function code for get device information
01: read device ID code
04: object ID.
How should we do to build a correct message and get the device information as a response?
There's no requirement that a Modbus device actually supports function code 0x2B.
In my experience it's very uncommon.
I have found that modbus protocol has 2 modes of building messages:
ASCII and RTU. I was using ASCII but it was bad because I have found
that a modbus service over TCP uses RTU mode.
Also, when it is over
TCP, the modbus messages must not have address byte neither error
check byte and I was building the messages with that bytes on it.
The
third thing I was doing bad was that when modbus is over TCP, its
messages must include a 7-byte header at the beginning that I was not
inserting.
All of this is described on:
https://scadahacker.com/library/Documents/ICS_Protocols/Acromag%20-%20Introduction%20to%20Modbus-TCP.pdf
For example, a well formed message (represented in hexadecimal) could be:
000000000005002B0E0106
At least, server is giving me a readable response. The message must be converted from hexadecimal to binary and then inserted into the data section of a TCP packet which will be sent to the server to the 502 port and over an IP packet which will contain the IP to the server.
Linux nc command lets you to send messages inside of TCP packets so you don't have to deal with the OSI layers.
My problem was that the messages I was sending to the server were not meeting the modbus/TCP protocol rules.

C# TcpClient send data in other TCP frame

I use TCPClient and NetworkStream to send short messages (Modbus frames) by socket. I use Write() method from NetworkStream to send data.
The problem is that I use twice or more write(), but the messages are send in one TCP Frame (check by Wireshark), for me is necessary that all writed messages will be sending in other TCP frame.
Any idea to resolve this problem?
Sounds as if TCP is buffering your data to optimize performance. You might want to put a delay between your two Sends or disable Nagel's algorithm (use SetSocketOption NoDelay true).
This can affect your TCP performance so you'll want to be careful when/where it's used.
Mike

Sending packets via UDP in erlang

so i'm trying to send udp packet to a listening port on a computer which is not connected to the same LAN but has internet access via gen_udp in erlang.
I start my first node by opening the port
({ok, Socket} = gen_udp:open(8887).) and the open the port on the other node the same way, When i send a packet from one node to the other via gen_udp:send i don't receive anything (trying flush() on the receiving node), So i'm wondering if there is something i'm doing wrong ? , i checked the firewalls and erlang and epmd is permitted.
did you try setting the controlling process of the Socket as the current process via :
gen_udp:controlling_process(Socket,Pid) ?
You should then setup a receive loop and messages will be sent to you. The format of the messages should be : {udp, Socket, IP, InPortNo, Packet}
You could also try setting the socket to passive mode by using inet:setopts(Socket, [{active, false}]) after you have opened it. After which you can use 'gen_udp:recv/3` to read from the socket.

How does TCP/IP report errors?

How does TCP/IP report errors when packet delivery fails permanently? All Socket.write() APIs I've seen simply pass bytes to the underlying TCP/IP output buffer and transfer the data asynchronously. How then is TCP/IP supposed to notify the developer if packet delivery fails permanently (i.e. the destination host is no longer reachable)?
Any protocol that requires the sender to wait for confirmation from the remote end will get an error message. But what happens for protocols where a sender doesn't have to read any bytes from the destination? Does TCP/IP just fail silently? Perhaps Socket.close() will return an error? Does the TCP/IP specification say anything about this?
TCP/IP is a reliable byte stream protocol. All your bytes will get to the receiver or you'll get an error indication.
The error indication will come in the form of a closed socket. Regardless of what the communication pattern (who does the sending), if the bytes can't be delivered, the socket will close.
So the question is, how do you see the socket close? If you're never reading, you'd eventually get an error trying to write to the closed socket (with ECONNRESET errno, I think).
If you have a need to sleep or wait for input on another file handle, you might want to do your waiting in a select() call where you include the socket in the list of sources you're waiting on (even if you never expect to receive anything). If the select() indicates that the socket is ready for a read call, you may get a -1 return (with ECONNRESET, I think). An EOF would indicate an orderly close (other side did a shutdown() or close().
How to distinguish this error close from a clean close (other program exiting, for example)? The errno values may be enough to distinguish error from orderly close.
If you want an unambiguous indication of a problem, you'll probably need to build some sort of application level protocol above the socket layer. For example, a short "ack" message sent by the receiver back to the sender. Then the violation of that higher level application protocol (sender didn't see an ack) would be a confirmation that it was an error close vs a clean close.
The sockets API has no way of informing the writer exactly how many bytes have been received as acknowledged by the peer. There are no guarantees made by the presence of a successful shutdown or close either.
The TCP/IP specification says nothing about the application interface (which is nearly always the sockets API).
SCTP is an alternative to TCP which attempts to address these shortcomings, among others.
In C, if you write to a socket that has failed with send(), you will get back the number of bytes that were sent. If this does not match the number of bytes you meant to send, then you have a problem. But also, when you write to a failed socket, you get SIGPIPE back. Before you start socket handling, you need to have a signal handler in place that will alert you when you get SIGPIPE.
If you are reading from a socket, you really should wrap it with an alarm so you can timeout. Like "alarm(timeout_val); recv(); alarm(0)". Check the return code of recv, and if it's 0, that indicates that the connection has been closed. A negative return result indicates a read failure and you need to check errno.
TCP is built upon the IP protocol, which is the centerpiece for the Internet, providing much of the interoperability that drives Routing, which is what determines how to get packets from their source to their destination. The IP protocol specifies that error messages should be sent back to the sender via Internet Control Message Protocol(ICMP) in the case of a packet failing to get to the sender. Some of these reasons include the Time To Live(TTL) field being decremented to zero, often meaning that the packet got stuck in a routing loop, or the packet getting dropped due to switch contention causing buffer overruns. As others have said, it is the responsibility of the Socket API that is being used to relay these errors at the IP layer up to the application interacting with the network at the TCP layer.
TCP/IP packets are either raw, UDP, or TCP. TCP requires each byte to be acked, and it will re-transmit bytes that are not acked in time. raw, and UDP are connectionless (aka best effort), so any lost packets (barring some ICMP cases, but many of these get filtered for security) are silently dropped. Upper layer protocols can add reliability, such as is done with some raw OSPF packets.

Resources