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.
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.
