How to test connect timeout on RHEL c/cpp application - c++

I have an application which talks to server over HTTP. I have written a code to control connect timeout (amount of time it will wait before server replies) . But I am finding it hard to generate a test case to test my connect timeout code. Could you please help me.
Basically, TCp handshake will contain
Host A sends a TCP SYNchronize packet to Host B
Host B receives A's SYN
Host B sends a SYNchronize-ACKnowledgement
Host A receives B's SYN-ACK
Host A sends ACKnowledge
Host B receives ACK.
TCP socket connection is ESTABLISHED.
In my application, if server does not complete TCP handshek in x seconds, applications moves to next server. But to test this code, I need a server stub which will probably accept SYN packet from client but will not set SYN+ACK packet to client. Thus making client wait for server's reply.
Could you please help me to create small server stub which will listen to particular port but will not complete handshake.

Given you mentioned RHEL I think you're best off using iptables to help test this. For example you could call:
iptables -I INPUT -s hostb -d hosta -p tcp --dport $port --tcp-flags SYN,ACK SYN,ACK -j DROP
calling that before running the test (or even during it perhaps?) and an equivalent matched -X to delete it seems to be by far the simplest way of breaking a handshake halfway through.
Drop all SYN+ACK (warning, WILL break new SSH connections):
iptables -I INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -j DROP
Drop all from or to 10.10.22.34:
iptables -I INPUT -s 10.10.22.34 -j DROP
iptables -I OUTPUT -d 10.10.22.34 -j DROP
Personally I would use the most specific match you can possibly write to avoid accidentally breaking remote access or anything else at the same time.
You could get fancier and use the -m owner match to only apply this rule for packets to/from the UID you run this test as.

I wouldn't rely on iptables, or any other tool for unit testing, as those tests would be too brittle. What if the IP address changes, or the unit tests are run on another machine ? What if the code has to be ported on an OS where iptables is not available ?
In order to keep the unit tests isolated from the network, I would encapsulate the socket API in a Socket class. Then I would have a Connection class that uses the Socket class. I would unit test the Connection class with a TimeoutSocket class (derived from Socket) that simulates the server not accepting the first connection request.
Your code should not depend on what's going on on the wire.

Related

nc -L disconnect after transmission

I'm currently preparing a unit test and therefore I need to emulate a client server connection.
I tried doing it like this:
nc -l 6543 < dummy-result.txt
But netcat does not close the connection after returning the content of the file. So my client is waiting for the server to close the connection endlessly.
Does anyone know how to get ncat to close the connection after serving the file? Also it would be useful to have ncat serve this file (and close the connection) for multiple requests (aka. -k).
Actually this was a bug in the openbsd implementation of netcat.
The option -N (server side) did not terminate the connection if the client was another netcat. If the client was telnet, it terminated as expected (Now I'm using the nmap netcat and it works).
For handling multiple connections I used a simple "while true" loop around it.

sending IP address of machine to server

I need to send a simple request to one of my server on defined intervals, let's say one every 2 seconds, in order to tell my server my machine's IP address(since I've dynamic one). I'm currently doing it in a while loop with a delay for std::system call for curl command with --silent option and redirecting rest to /dev/null. Something like this -
curl -s 'http://example.com' > /dev/null
The server currently parses the request and finds out the required IP address from it. Is there any other way to do this?
Another alternative would be sending a simple UDP datagram packet. The server can obtain the sender's address, upon receipt, equally well.
That requires a little bit less overhead than establishing a TCP connection. Of course, UDP offers no guarantee of deliverability, and an occasional UDP datagram would be lost; but since you're pinging the server regularly that should be fine. More importantly, however, is that a UDP sender's IP address is trivially forged. Whether or not this is an issue for your application is something that only you can determine.
If you're going to stick with TCP, one thing you can do is to establish a socket connection yourself. Let's examine what executing system(), just for the purpose of having curl do a dummy connection, involves:
forking a new child process.
the child process executing /bin/bash, passing it the command to parse.
Bash reading $HOME/.bashrc, and executing any commands in there. If your shell is something other than bash, the shell will have its own equivalent of a startup script to execute.
The shell forking a new child process.
The child process executing curl.
The loader finding all of the libraries that curl requires, and opening them.
curl now executes. Only then, after all this work, there will be code running to open a socket and attempt to connect to the remote host.
Steps 1 through 6 can be trivially skipped, simply by creating a socket, and connecting, yourself. It's not rocket science. socket(), connect(), close(), that's it. This task does not require HTTP. The server process only needs to socket(), bind(), listen(), and accept(), and then obtain the IP address from the connection. Done.

Packets looping forever in libnetfilter_queue

I want to implement a network delay model for TCP/UDP traffic as described in Linux libnetfilter_queue delayed packet problem. I have followed the suggestion of Andy there, copying entire packet to my program and placing it an a priority queue. As time passes, packets in priority queue are removed and dispatched using RAW sockets.
The problem I am facing is this: Initial capture of packets by libnetfilter_queue is being done by matching the ports (sudo iptables -A OUTPUT -p udp --dport 8000 -j NFQUEUE --queue-num 0). When these packets are reinjected by RAW sockets, they are picked up once again by libnetfilter_queue (since the port remains the same) and hence continue to loop forever.
I am really confused and cannot think of a way out. Please help me.
Use skb->mark. It's a marking which only exists within the IP stack of your host. It does not affect anything in the network packet itself.
You can filter it using iptables using the '--mark' filter. Use it to return from your delay chain so that your re-inserted packets are not delayed again.
iptables -A DELAY -m mark --mark 0xE -j RETURN
iptables -A DELAY -j DELAY
You can configure the raw socket to apply a mark, using setsockopt(fd, SOL_SOCKET, SO_MARK, ...). You only need to do this once after opening the socket. The mark value will be automatically applied to each packet you send through the socket.
This probably isn't the best way to do it, but here is one possible solution. You could use the DSCP field in the IP header to differentiate new packets and packets you are re-injecting. Change your iptables rule to only enqueue packets with a DSCP of 0 (see http://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#DSCPMATCH). This assumes when your OS sends a packet, it will set the DSCP to 0. Now all new packets generated by the OS will be sent to your program because they still match the iptables rule. When you are creating a new packet in your program using a RAW socket, set the DSCP value to a non-zero value. When your new packet is re-injected, it will no longer match the iptables rule and will go out over the network.
If you don't want packets going out over the network with DSCP values set, you could add another iptables rule to re-write the dscp values to 0.

C++ UDP Socket port multiplexing

How can I create a client UDP socket in C++ so that it can listen on a port which is being listened to by another application? In other words, how can I apply port multiplexing in C++?
I want to listen on only one port
You can do that with a sniffer. Just ignore the packets from different ports.
I might need to stop it from sending out some particular packets, because my program will send it instead of the original application
Okay, here I suggest you to discard sniffers, and use a MITM technique.
You'll need to rely on a PREROUTING firewall rule to divert the packets to a "proxy" application. Assuming UDP, Linux, iptables, and the "proxy" running on the same host, here's what the "proxy" actually needs to do:
1. Add the firewall rule to divert the packets (do it manually, if you prefer):
iptables -t nat -A PREROUTING -i <iface> -p <proto> --dport <dport>
-j REDIRECT --to-port <newport>
2. Bind and listen on <newport>.
3. Relay all the traffic between the 2 endpoints (client, and original destination). If you're running the "proxy" on a different host, use getsockopt with SO_ORIGINAL_DST to retrieve the original destination address.
It might sound tricky, but... yeah, that's because it's a bit tricky :-)
Consult your firewall documentation if my assumption diverges.
This is just packet sniffing like tcpdump or snoop, open up a raw socket and pull everything from the wire and filter as you require. You will probably want to use libpcap to make things a little easier.
Without administrator or super-user privileges you will need the target application to open ports with SO_REUSEADDR and SO_REUSEPORT as appropriate for the platform. The caveat being you can only receive broadcast and multicast packets, unicast packets are delivered to the first open socket.
This is not multiplexing - that term is reserved for handling I/O on multiple channels in the same process and where things like select(2) and poll(2) are most useful.
What you are asking for is multicast. Here is the basic example.
Note that IP reserves a special range of addresses (a.k.a. groups) for multicasting. These get mapped to special ethernet addresses. The listener(s) would have to join the multicast group, while sender does not have to, it just sends as usual.
Hope this helps.

to verify connectivity of remote machine without using ping command

Is there any method in c++/vc++/mfc so that I can verify whether remote machine is on network or not. I don't want to use ping command. I tried to use WSAConnect method but it takes lot of time in searching if remote machine is not on network. In that case application windoe freezes for long time. I need alternate way to verify remote machine netwotk connectivity. Plz help
You can check to see if a host name exists and if DNS can resolve an IP address for it, but this won't tell you if it's online. In order to determine if it's online, you must exchange data with the host. For this to happen the host must be listening on a port, and must send some sort of response.
Generally, the lowest common denominator for hosts is the ICMP packet - aka ping. You can write your own service in C++ to send these UDP packets, and detect a reply.
Some hosts and some routers disable ICMP to appear 'invisible'. If you know that your host accepts connections on a TCP port, you can attempt to create a tcp socket. For example, from a shell you can test using nc
nc -z google.com 80
Connection to google.com 80 port [tcp/http] succeeded!
If you do raw socket programming, you can attempt to connect to a host via, and then call select() with a short timeout.
If you don't want your app to block, use a thread.
If the only issue is that calling WSAConnect locks up your UI, you can try calling it in nonblocking mode.
Call WSAEventSelect to set the socket to nonblocking mode prior to calling WSAConnect. You then call WSAAsyncSelect or WSAEventSelect to check the status of the connection.
MSDN's page on WSAConnect has some remarks about nonblocking mode here.
You can use tracert command. Example:
tracert -w 1000 192.168.0.77
You can check if the machine is connected to a network, but without trying to transmit data to a site residing on the internet I don't think there is a way to check if that network is actually online. For example your end user might as well be connected to a DSL router which is not online at the moment.
You can use arping for it.
Also some smart switch can talk about attached host.