Skip to content
Advertisement

How to reproduce the accept error in Linux

I’m learning Unix Network Programming Volume 1, I want to reproduce the accept error for RST in Linux.

  1. server: call socket(), bind(), listen(), and sleep(10)
  2. client: call socket(), connect(), setsockopt() of LINGER, close() and return
  3. server: call accept()

I think that the 3rd steps will get an error like ECONNABORTED, but not.

Do I want to know why?

I will appreciate it if you help me.

The follow is server code :

#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct sockaddr_in addr;

    bzero(&addr, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(6666);
    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

    bind(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));
    listen(sock, 5);
    sleep(10);

    if (accept(sock, NULL, NULL) < 0)
        perror("error");
    else
        printf("right");

    return 0;
}

The following is the client code

#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct sockaddr_in addr;

    bzero(&addr, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(6666);
    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);

    connect(sock, (struct sockaddr*)(&addr), (socklen_t)(sizeof addr));

    struct linger ling;
    ling.l_onoff = 1;
    ling.l_linger = 0;
    setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof ling);
    close(sock);

    return 0;
}

Advertisement

Answer

Nope. I think you’ll get an empty, but complete connection (with no data). The kernel will manage the complete connection establishment and then it’ll get an immediate FIN packet (meaning EOF, not reset) and will handle it (or wait for user space process to close its side, to send the FIN to the other side) For a connection abort you need to reboot the client machine (or the server) without allowing it to send the FIN packets (or disconnecting it from the network before rebooting it) An ACK is never answered, so you won’t get a RST sent from an ACK.

RST packets are sent automatically by the kernel when some state mismatch is in between two parties. For this to happen in a correct implementation you must force such a state mismatch (this is why the machine reboot is necessary)

  • Make a connection between both parties and stop it (with a sleep) to ensure the connection is in the ESTABLISHED state before disconnecting the cable.
  • disconnect physically one of the peers from the network, so you don’t allow its traffic to go to the network.
  • reboot the machine, so all sockets are in the IDLE state.
  • reconnect the cable. As soon as the waiting machine gets out of the sleep and begins sending packets again, it will receive a RST segment from the other side, because it has been rebooted and TCP does not know about that connection.

Other ways of getting a RST segment involve bad implementations of TCP, or mangling the packets in transit (changing the sender or receiver sequence numbers in transit)

The purpose of RST packets is not to add functionality to TCP, but to detect misbehaviours, to there should be no means to get a reset with proper use of sockets. Listen syscall is there to allow you to reserve resources in kernel space to allow the user space process to prepare to handle the connection while the clients are trying to connect. If you do what you intend you’ll get a connection with no data, but valid connection, SO_LINGER is there to force a loss of status when machines don’t have the time to send the packets to each other… but being connected, the whole connection is handled in the kernel and no abort is to be expected.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement