Freebsd is not RECV the packet, although successfully sent

22 views Asked by At

I have a new problem with the migration to freebsd. I've tried to give everything I can. The problem with recvfrom is it just can't wait for a packet, even when I remove the timeout.

Here is a screenshot from wireshark which shows that the packets are sent successfully, and the packets from the host side are also sent successfully in response.

Wireshark

Here is the function I receive packets with, on linux it works on freebsd it refuses, I think this is a feature of RAW sockets on freebsd, with TCP protocol.

int recv_tcp_packet(const char* dest_ip, int recv_timeout_ms, unsigned char** buffer) {
    /* Set target. */
    struct in_addr dest;
    dest.s_addr = inet_addr(dest_ip);

    /* Temporary buffer */
    unsigned char* read_buffer = *buffer;

    /* Creation sock. */
    int sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    if (sock == -1) {
#ifdef PRINT_ERRORS
        perror("recv_tcp_packet/create-socket-error");
#endif
        return -1;
    }

    /* Set timeout on socket. */
    struct timeval timeout;
    timeout.tv_sec = recv_timeout_ms / 1000;
    timeout.tv_usec = (recv_timeout_ms % 1000) * 1000;
    int result = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
    if (result == -1) {
#ifdef PRINT_ERRORS
        perror("recv_tcp_packet/setsockopt-error(timeout)");
#endif
        /* Timeout. */
        close(sock);
        return -1;
    }

    struct sockaddr saddr;
    time_t start_time = time(NULL);

    /* Infinite loop, on accepting all ICMP packets. */
    for (;;) {
        /* Updating the IP size with each new packet. */
        int saddr_size = sizeof(saddr);
        int data_size = recvfrom(sock, read_buffer, RECV_BUFFER_SIZE, 0, &saddr, (socklen_t*)&saddr_size);
        if (data_size == -1) {
#ifdef PRINT_ERRORS
            perror("recv_tcp_packet/recvfrom-error");
#endif
            close(sock);
            return -1;
        }

        /* Creating an IP stub to verify packet sorting. */
        struct ip_header* iph = (struct ip_header*)read_buffer;
        unsigned short iphdrlen = (iph->ihl) * 4;
        if (iphdrlen < 20) {
            close(sock);
            return -1;
        }

        /* Verification of the received packet's protocol. */
        if (iph->protocol != IPPROTO_TCP) {
            close(sock);
            return -1;
        }

        /* Obtains the sender's IP from the RECEIVED packet. */
        struct sockaddr_in source;
        memset(&source, 0, sizeof(source));
        source.sin_addr.s_addr = iph->saddr;

        /* Comparing the IP from the received packet with the IP
         * to which the packet was sent. */
        if (source.sin_addr.s_addr != dest.s_addr) {
            time_t current_time = time(NULL);
            int elapsed_time = (int)(current_time - start_time) * 1000;

            /* Timeout on a windowless loop where packets are received. */
            if (elapsed_time >= recv_timeout_ms) {
#ifdef PRINT_ERRORS
                printf("recv_tcp_packet/timeout: a timeout on the packet receiving loop has occurred.\n");
#endif
                close(sock);
                return -1;
            }
            continue;
        } else {
#ifdef PACKET_TRACE
            struct tcp_header* tcph = (struct tcp_header*)read_buffer;
            char ip_str[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &(source.sin_addr.s_addr), ip_str, INET_ADDRSTRLEN);
            printf("TCP & RCVD %d bytes from %s: ttl=%d ident=%d window=%d seq=%d sum=%d\n",
                   (int)sizeof(&iph) + (int)sizeof(&tcph), ip_str, iph->ttl, iph->id, tcph->window, tcph->seq, iph->check);
#endif

            /* Success read, fill the buffer. */
            *buffer = read_buffer;
            close(sock);
            return 0;
        }
    }

    /* Ну ок :) */
    close(sock);
    return -1;
}

It just waits for the packet windowlessly, starting with recvfrom. She's not even accepting them.

Moreover, the logic of accepting ICMP packets works successfully for me.

I also tried writing acceptance via pcap, but it was the same there, I didn't have the code saved with pcap.

0

There are 0 answers