I'm porting my program from Unix to Windows, and I have a problem with the recvfrom() function to accept a packet. I haven't written anything with Winsock until now. I think I've done everything, according to the manual.
Also, as I read from the manual, a TCP RAW socket does not need binding via bind(), but it still doesn't work.
#define NESCA
int
ncread(const char* dest_ip, int recv_timeout_ms, unsigned char **buffer, bool debug,
int dest_port, int source_port, bool packet_trace)
{
/*Create a structure and pass the recipient's IP into it.*/
struct in_addr dest; dest.s_addr = inet_addr(dest_ip);
/*Time buffer.*/
unsigned char *read_buffer = *buffer;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
return -1;
}
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock == -1) {return SOCKET_ERROR;}
#ifdef NESCA
/*Function similar to the entry below*/
int result = set_socket_timeout(sock, recv_timeout_ms, 1, 1);
#else
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));
#endif
if (result < 0)
{
std::cout << "timeout infinity\n\n";
/*Timeout.*/
fuck_fd(sock);
return -1;
}
/*To compare the IPs.*/
struct sockaddr saddr;
int saddr_size = sizeof(saddr);
auto start_time = std::chrono::steady_clock::now();
/*An endless loop, on accepting any packets from the system at all.*/
for (;;)
{
/*Receive packet to buffer.*/
int data_size = recvfrom(sock, (char*)read_buffer, READ_BUFFER_SIZE, 0, (sockaddr*)&saddr,
if (data_size == -1)
{
/*ERROR: 10022*/
wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
fuck_fd(sock);
return READ_ERROR;
}
/*Obtaining the IP header of the received packet.*/
struct ip_header *iph = (struct ip_header*)read_buffer;
unsigned short iphdrlen = (iph->ihl) * 4;
if (iphdrlen < 20)
{
fuck_fd(sock);
return IP_HEADER_LEN_ERROR;
}
/*Retrieve the sender's IP from it.*/
struct sockaddr_in source;
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iph->saddr;
/*Compare the IP to see if it matches the one we sent it to.
* This is to discard other packets.*/
if (source.sin_addr.s_addr != dest.s_addr)
{
if (debug) {std::cout << "Got the wrong package.\n";}
/*A windowless for timeout might work here.*/
auto current_time = std::chrono::steady_clock::now();
auto elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();
if (elapsed_time >= recv_timeout_ms)
{
std::cout << "timeout infinity\n\n";
fuck_fd(sock);
return INFINITY_TIMEOUT_EXITED;
}
/*If it's the wrong one, it catches again until it times out,
* on a windowless loop. Or until the right packet arrives.*/
continue;
}
else
{
#ifdef NESCA
if (packet_trace)
{
struct in_addr addr;
addr.s_addr = iph->saddr;
std::string source_ip = inet_ntoa(addr);
addr.s_addr = iph->daddr;
std::string dest_ip = inet_ntoa(addr);
struct tcp_header *tcph = (struct tcp_header*)(buffer+ iphdrlen);
unsigned short id = ntohs(iph->id);
unsigned int seq = ntohl(tcph->seq);
unsigned int iplen = ntohs(iph->tot_len);
packet_trace1.lock();
np3.nlog_packet_trace("RCVD", "TCP", source_ip, dest_ip, dest_port, source_port, "", iph->ttl, id, tcph->window, seq, iplen);
packet_trace1.unlock();
}
#endif
/*If it's the right packet.
* Fill the buffer with it.*/
*buffer = read_buffer;
fuck_fd(sock);
return SUCCESS_READ;
}
}
/*oh.*/
fuck_fd(sock);
return READ_ERROR;
}
Close sock function:
int fuck_fd(int fd)
{
#ifdef _WIN32
WSACleanup();
closesocket(fd);
#else
close(fd);
#endif