Receiving raw ethernet packets - timing issues - c

I have a scenario where I construct and send a raw ethernet packet to a bespoke hardware device. The packet triggers a response packet to be sent back by the device.
My code performs a sendto() call to transmit the outgoing packet and after that a recvfrom() call to try and receive the response. The recvfrom() is in a while loop such that it keeps trying to receive a packet until recvfrom() indicates its received > 0 bytes.
I've run Wireshark to confirm that my outgoing packet is constructed correctly and sent, I can also see the response packet from the device and it is correctly formed.
What I can't do is receive it with my recvfrom() call. The while loop effectively hangs as recvfrom() never returns a value other than 0.
I'm thinking that maybe I need the recvfrom() call in a separate 'listener' thread that is running prior to the sendto() call. Currently my application isn't threaded. I just run the recvfrom() after the sendto().
Is it possible that I am simply missing the packet with my non-threaded approach, or are packets buffered in some way such that they can be received even if they are sent before a corresponding recvfrom() is executed?
I would be very interested to know if there is a defacto way of doing this sort of thing. It would be great not to have to make my app multithreaded, but I can if need be.

Related

lwIP echo server error sending data

I am working with the ethernet communication under echo server lwIP. I would like to capture samples from DMA to the HOST by ethernet. The system captures samples via UART.
I am not able to make lwIP to send more than 2 packages higher than 1500 bytes without waiting for ACK. My application sends packet continuously to the client. Client receives the packet without any delay but it sends the ACK after 200ms (see attached wireshark capture image). LWIP get stuck always waiting for ACK packet before it sends the next packet. My lwIP could only send no more than 2 TCP segment and then wait for ACK. The network delay will cause performance to get down.
Is there any configuration which makes the LWIP to send packet without waiting for the ACK packet? Do you have any suggestion?
If you don't want to wait how about using UDP instead of TCP? TCP is a stream protocol and is going to ensure that everything arrives and is in-order (so long as there aren't errors). echo usually makes me think of a situation where you don't care about ordering, only whether a particular packet makes it or not and how long it took.

Read UDP/TCP payload with divert socket

I need to intercept/redirect TCP and UDP packets that have its payloads matching some regex patterns and also get original destination address and port.
I can't just redirect TCP and UDP packets to my application by the use of DSTNAT on firewall (and splice() if don't match patterns) because that wouldn't allow me to get their original destination addresses and ports from before they are changed/translated.
So I read about divert sockets and they look promising. I'm in doubt however, as I couldn't find anywhere how much an application can read of a packet received on a divert socket. Is it possible to read entire packet (including TCP and UDP payload) or just its headers? Is entire packet sent to divert socket or just first received fragment (maybe limited by MTU/MRU or how much send() could push on single call on other end...)?
If it matters, the firewall I'm going to use for diverting packets is ipfw.

how does non-blocking tcp socket notify application on packets which fail to get sent.

Im working on a non-blocking C tcp sockets for linux system. I've read that in non-blocking mode, the "send" command will return "bytes sent" immediately if there is no error. I'm guessing this value returned does not actually mean that those data have been delivered to the destination but rather the data has been passed to kernel memory for it to handle further and send.
If that is the case, how would my application know which packet has really been sent out by kernel to the other end, assuming that the network connection had some problems and kernel decides to give up only after several retries in a span of a few minutes later?
Im asking because i would want my application to resend those failed packets again at a later time.
If that is the case, how would my application know which packet has
really been sent out by kernel to the other end, assuming that the
network connection had some problems and kernel decides to give up
only after several retries in a span of a few minutes later?
Your application won't know, unless it is able to recontact the receiving application and ask the receiving application about what data it had previously received.
Keep in mind that even with blocking I/O your application doesn't block until the data is received by the remote application -- it only blocks until there is some room in the kernel's outgoing-data buffer to hold the bytes you asked the TCP stack to send(). So even with blocking I/O you would face the same issue.
Also keep in mind that the byte arrays you pass to send() do not have a guaranteed 1-to-1 correspondence to the TCP packets that the TCP stack sends out. The TCP stack is free to pack your bytes into TCP packets any way it likes (e.g. the data from multiple send() calls can end up in a single TCP packet, or the data from a single send() call can end up in multiple TCP packets, or any other combination you can think of). Depending on network conditions, TCP stacks can and do pack things various different ways, their only promise is that the bytes will be received in FIFO order (if they get received at all).
Anyway, the answer to your question is: you can't know, unless you later ask the receiving program about what it got (or didn't get).
TCP internally takes care of retrying, application doesn't need to do any special handling for it. If you wish to confirm a packet received the other end of the TCP stack then you can set the send socket buffer (setsockopt(SOL_SOCKET, SO_SNDBUF)) to zero. In this case, kernel uses your application buffer to send the data & its only released after the TCP receives acknowledgement for this data. This way you can confirm that the data is pushed to the receiver end of the TCP stack. It doesn't confirm that the application has received the data. You need to have application layer acknowledgement in your protocol to confirm that the data reached the receiver application.

TCP send semantics on linux

My understanding about send() on linux is that if the sending process's data can be successfully copied into the kernel buffer, send() returns. The application is then free to move on.
If this is true, and say TCP is unable to deliver that packet, how does TCP report an error?
If error is received after multiple send()(Rwnd was large at beginning), how does application know, which particular send() failed or in other words, which message failed to reach?
If this is true, and say TCP is unable to deliver that packet, how does TCP report an error?
TCP will retry/resend silently until the connection ends or abends.
If you want to know whether it has been received, then you need the receiving application to send a confirmation (an application-level message).
Edit:
The TCP protocol receives an end-to-end ACK ... but that ACK is swallowed by the TCP stack: I don't think it's exposed to the application, via the normal 'sockets' API.
A packet sniffer hooks into the network/TCP stack at a level that enables it to see the ACK: see for example the answers to How can I verify that a TCP packet has received an ACK in C#? ... I don't know what the equivalent is for Linux, but there must be one.
Note this answer which warns that even if the message is received by the remote TCP stack, that doesn't guarantee that it has been processed (i.e. retrieved from the stack) by the receiving application.
You'll get an error eventually reported by another send or recv. Eventually - by default TCP can take a very long time to decide that there's a problem in the connection. You may get a whole selection of "successful" sends first, it depends on the error condition. You may only find out things have gone awry by send moaning that its buffer is full.

raw socket listener

This is a quick question for linux c programming raw sockets. If I wanted to just listen to any interface with a raw socket, must I actually bind to an ip address or interface to listen to traffic? From what I understand, I feel like I should be able to just call sock(); and then start recvfrom() traffic. Maybe I'm wrong, but I've seen some programs that don't use it.
You are right, the only thing you will need to do is call socket() and then recvfrom(). Nevertheless be aware of the fact that there are some limitations with listening using SOCK_RAW.
If you're not using raw sockets on a "send-and-forget" basis, you will
be interested in reading the reply packet(s) for your raw packet(s).
The decision logic for whether a packet will be delivered to a raw
socket can be enumarated as such:
TCP and UDP packets are never delivered to raw sockets, they are always handled by the kernel protocol stack.
Copies of ICMP packets are delivered to a matching raw socket. For some of the ICMP types (ICMP echo request, ICMP timestamp request,
mask request) the kernel, at the same time, may wish to do some
processing and generate replies.
All IGMP packets are delivered to raw sockets: e.g. OSPF packets.
All other packets destined for protocols that are not processed by a kernel subsystem are delivered to raw sockets.
The fact that you're dealing with a protocol for which reply packets
are delivered to your raw socket does not necessarily mean that you'll
get the reply packet. For this you may also need to consider:
setting the protocol accordingly while creating your socket via socket(2)system call. For instance, if you're sending an ICMP
echo-request packet, and want to receive ICMP echo-reply, you can set
the protocol argument (3rd argument) to IPPROTO_ICMP).
setting the protocol argument in socket(2) to 0, so any protocol number in the received packet header will match.
defining a local address for your socket (via e.g. bind(2)), so if the destination address matches the socket's local address, it'll be
delivered to your application also.
For more details you can read e.g. this.
If you meant to capture the traffic on a interface, you can use libpcap.

Resources