connection error: Invalid argument at sockets - c++

I have this code
Server:
//"sock" has already been created with no problem and binding as well
void Connection::bind_connection(int port){
cout << "Port " << port << endl;
server.sin_family = AF_INET ;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
/* Bind socket to address */
struct sockaddr *serverptr = ( struct sockaddr *) &server;
if ( bind ( sock , serverptr , sizeof(server) ) < 0) {
perror("Binding error"); exit(BE);
}
cout << "Server binding completed!" << endl;
}
struct sockaddr_in client ;
socklen_t clientlen ;
struct sockaddr * clientptr =( struct sockaddr *) &client ;
if ( listen (sock , MAX_CONNECTIONS) < 0) {perror("listening error"); exit(LE);}
cout << "Listening for connections to port " << port << endl;
while (1) {
/* accept connection */
if (( newsock = accept ( sock , clientptr , &clientlen ) ) < 0) {
perror("Accepting error"); cout << "Errno = " << errno << endl; exit(AE);
}
//Code
....
}
and
Client:
//struct sockaddr_in server; <--- declared as data member of class "Connection"
//"sock" has already been created with no problem
void Connection::do_connect(){
struct sockaddr *serverptr = ( struct sockaddr *) &server;
if ( connect ( sock , serverptr , sizeof (server) ) < 0)
perror("client connect"); exit(CE);
cout << "Client connecting to the server" << endl;
}
and I get the above message. Most of the code is copied from the lesson slides but modified for my needs. Googling the problem it seems that I give wrong size at the syscall(s). Any idea where exactly the problem is? Thanks in advance.

Those lines always exit:
if ( connect ( sock , serverptr , sizeof (server) ) < 0)
perror("client connect"); exit(CE);
You might start to think about using a different indention scheme. Typically one that does not use more then one statement per line.
For the above code a tool like indent would have formatted it like this:
if (connect (sock, serverptr, sizeof (server)) < 0)
perror("client connect");
exit(CE);
This format makes the programming bug obvious.

You didn't initialize clientlen.
socklen_t clientlen = sizeof(client);
You can catch similar problems in future by running your code through valgrind.

As already indicated, you do not seem to be initializing your variables properly. You do not show how you initialize your sockaddr_in structures, which is likely the culprit. A relatively easy way to specify the address for bind() or connect() is to use getaddrinfo()/freeaddrinfo(). From the documentation:
Synopsis
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
void freeaddrinfo(struct addrinfo *res);
Description
Given node and service, which identify an Internet host and a service, getaddrinfo() returns one or more addrinfo structures, each of which contains an Internet address that can be specified in a call to bind(2) or connect(2). ...
The freeaddrinfo()function frees the memory that was allocated for the dynamically allocated linked list res.
As a simple example, here is a function that can connect to a server specified by a string that has the format <servername>:<port>:
int connect_tcp (std::string hostspec) {
struct addrinfo hints = { .ai_flags = AI_NUMERICSERV };
struct addrinfo *res = 0;
std::istringstream ss(hostspec);
std::string node, service;
int sock = -1;
std::getline(ss, node, ':');
std::getline(ss, service, ':');
getaddrinfo(node.c_str(), service.c_str(), &hints, &res);
for (struct addrinfo *rp = res; rp != 0; rp = rp->ai_next) {
if (rp->ai_socktype != SOCK_STREAM) continue;
int sock = socket(rp->ai_family, SOCK_STREAM, 0);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
break;
close(sock);
sock = -1;
}
freeaddrinfo(res);
if (sock == -1) errno = EHOSTDOWN;
return sock;
}

Related

Recvfrom working locally, but don't receive anything on random ports between executions

I'm working on a multithreaded UDP listener and I'm stuck in a problem that definitely surpasses me.
So, I'm required to receive huge amounts of UDP packets in several ports. Locally, the best solution for me was to call non blocking recvfrom in as much threads as ports I'm listening (select and poll were too slow for my requirements). I'm using a thread pool manager, it simply calls on threads and queues tasks. Here's the code:
void receiveFromSocket(void * arguments){
sockaddr_in client; // Local
socklen_t clientSize = sizeof(client);
memset(&client, 0, sizeof(client));
struct arg_struct_listenPort *args2 = (struct arg_struct_listenPort *)arguments;
int fd = args2->arg_fd;
int port = args2->arg_port;
for(;;) {
char buf[158];
memset(buf,0,158*sizeof(char));
int n = recvfrom(fd, (char * ) buf, 158, MSG_DONTWAIT, ( struct sockaddr *) &client, &clientSize);
if(n == -1){
//cerr << "Error while receiving from client: " << errno << endl;
continue;
}
if(n != 158){
cerr << "Discarded message since it's not 158 bytes." << endl;
continue;
}
struct arg_struct args;
args.arg_port = port;
memcpy(args.buf,buf,158);
thpool_add_work(globals.thpool, socketThread, (void*)(&args));
}
}
/// Runs the Socket listener
int network_accept_any()
{
vector<int>::iterator i;
for(i = globals.fds.begin(); i != globals.fds.end(); i++){
int port = distance(globals.fds.begin(),i);
struct arg_struct_listenPort args;
args.arg_fd = *i;
args.arg_port = globals.cmnSystemCatalogs[port].diag_port;
thpool_add_work(globals.thpool, receiveFromSocket, (void*)(&args));
}
cout << "Listening threads created..." << endl;
return 0;
}
This works perfectly fine locally. But when I compile it on a production environment, some ports listen the packets and other's simply don't! And the working ports change in each execution. I can , confirm that it is not a firewall problem. I also can clearly see the packets through Wireshark. I can receive packets on those ports through netcat. Netstat shows all ports open.
My local environment is an Ubuntu 18.04 VM, and the production environment is a Debian 9.8.
Here's how I call the sockets:
int lSocket(int port) {
//Crear Socket
int listening = socket(AF_INET, SOCK_DGRAM, 0);
if (listening == -1) {
cerr << "No se puede crear el socket";
exit(EXIT_FAILURE);
}
//Enlazar socket a un IP / puerto
struct sockaddr_in hint;
memset(&hint, 0, sizeof(hint));
hint.sin_family = AF_INET; //IPv4
hint.sin_port = htons(port); //Port
hint.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listening, (struct sockaddr*)&hint, sizeof(hint)) == -1) { //Enlaza las opciones definidas al socket
cerr << "No se puede enlazar IP/puerto" << endl;
exit(EXIT_FAILURE);
}
return listening;
}
Any advise is greatly appreciated!
EDIT:
As suggested, I tried switching to blocking I/O, but the main issue remains. Still not receiving at all the opened ports.
What an amazing welcome!
#molbdnilo was absolutely right:
You're using pointers to objects whose lifetime has ended (&args).
This has undefined behaviour - it might appear to work, but it's a bug
that needs a-fixin'.
Here's the fixed code. Gotta be careful when feeding arguments to threads!
void receiveFromSocket(void * arguments){
sockaddr_in client; // Local
socklen_t clientSize = sizeof(client);
memset(&client, 0, sizeof(client));
struct arg_struct_listenPort *args2 = (struct arg_struct_listenPort *)arguments;
int fd = args2->arg_fd;
int port = args2->arg_port;
for(;;) {
char buf[158];
memset(buf,0,158*sizeof(char));
int n = recvfrom(fd, (char * ) buf, 158, MSG_WAITALL, ( struct sockaddr *) &client, &clientSize);
if(n == -1){
cerr << "Error while receiving from client: " << errno << endl;
continue;
}
if(n != 158){
cerr << "Discarded message since it's not 158 bytes." << endl;
continue;
}
arg_struct *args = new arg_struct;
args->arg_port = port;
memcpy(args->buf,buf,158);
thpool_add_work(globals.thpool, socketThread, (void*)(args));
}
}
/// Runs the Socket listener
int network_accept_any()
{
vector<int>::iterator i;
for(i = globals.fds.begin(); i != globals.fds.end(); i++){
int port = distance(globals.fds.begin(),i);
arg_struct_listenPort *args = new arg_struct_listenPort;
args->arg_fd = *i;
args->arg_port = globals.cmnSystemCatalogs[port].diag_port;
thpool_add_work(globals.thpool, receiveFromSocket, (void*)(args));
}
cout << "Listening threads created..." << endl;
return 0;
}
Also, I'll keep an eye on #John Bollinger 's and #Superlokkus comments.
Thank you all!

c++ address family not supported by protocol

I write a method, that creates a socket, connect it to the endpoint, and then returns its descriptor:
static int open_socket(const char* host, unsigned short port)
{
#ifdef USE_IPV4
struct hostent* _hostent;
struct sockaddr_in _sockaddr_in;
// Variables
size_t sockaddr_len;
int sock_family;
int sock_type;
int sock_protocol;
int sockfd;
_hostent = gethostbyname(host);
if (_hostent == (struct hostent*) 0)
{
// Not Found
}
_sockaddr_in.sin_family = AF_INET;
sock_family = AF_INET;
sock_type = SOCK_STREAM;
sock_protocol = IPPROTO_TCP;
sockaddr_len = sizeof(_sockaddr_in);
(void*) memmove(&_sockaddr_in, _hostent->h_addr, _hostent->h_length);
_sockaddr_in.sin_port = htons(port);
// Now create socket
sockfd = socket(sock_family, sock_type, sock_protocol);
if (sockfd < 0)
{
// "Internal Error"
}
if (connect(sockfd, (struct sockaddr*) &_sockaddr_in, sockaddr_len) < 0)
{
std::cerr << strerror(errno) << std::endl;
std::cerr << "Endpoint is unavailable" << std::endl;
return 0;
// "Unavailable"
}
return sockfd;
#endif
}
The error occures when i try to connect socket. strerror(errno) returns "Address family not supported by protocol". I cannot figure out why it happens, because in other samples AF_INET fine works with IPPROTO_TCP
You need to store the address in sockaddr_in::sin_addr instead. You are overwriting the entire struct (starting from the sin_family) when you call memmove(&_sockaddr_in, ...).

connect to socket failed - errno 88 (cpp)

I'm trying to create server/client communication and it faileson the connect function with errno 88. I checked if the socketfd is valid (because this errno means that I'm trying to make socket operation on non socket object).
int main (int argc, char *argv[])
{
// Validity check
if (argc != VALID_ARG_NUM) {
std::cout << INVALID_ARG;
return 0; // todo - return 0 is correct??
}
int port;
struct sockaddr_in server_address;
// server_address initialization.
server_address.sin_family = AF_INET;
server_address.sin_port = htons((uint32_t)atof(argv[3]));
server_address.sin_addr.s_addr = inet_addr(argv[2]);
memset(&(server_address.sin_zero), '\0', sizeof(server_address));
// Create the client socket.
if (sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0) {
std::cout << "ERROR: socket " << errno << "." << std::endl;
exit(1);
}
// Connect to server.
if (connect(sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {
std::cout << "ERROR: connect " << errno << "." << std::endl;
std::cout << CON_FAIL;
close(sockfd);
exit(1);
}
.......
thank you.
The precedence of the statement
sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0
is
sockfd = ((socket(AF_INET, SOCK_STREAM, 0)) < 0)
and you are therefore assigning a boolean, which is implicitly converted to an integer (or whatever type sockfd has). What you probably meant was instead
(sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0
I think this part is causing buffer overrun:
memset(&(server_address.sin_zero), '\0', sizeof(server_address));
You should zero the whole struct before writing somefields:
struct sockaddr_in server_address;
// server_address initialization.
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
Broken pipe usually means that remote peer closes connection. Are you sure your server code is OK? Maybe it just do something like this?
int main()
{
...
listen();
accept();
return 0;//procees exits and therefore brakes connection
}

Raw Socket send TCP SYN-FIN-.. in c++

My teacher want us to do an exercise on raw socket in c ++ on Windows (for learning tcp communication).
I have got a problem with it. I saw a lot of documentation but I don't know how to solve it.
int raw()
{
WSADATA WSAData;
SOCKET sock;
SOCKADDR_IN sin,din;
WSAStartup(MAKEWORD(2, 2), &WSAData);
char datagram[MAX_PACKET_SIZE];
struct iphdr *iph = (struct iphdr *)datagram;
struct tcphdr *tcph = (struct tcphdr *)((UCHAR *)iph + sizeof(tcphdr));
char new_ip[sizeof "255.255.255.255"];
sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
cout << "failled init socket" << endl ;
else{
memset(datagram, 0, MAX_PACKET_SIZE); // Clear the data
setup_ip_header(iph);
setup_tcp_header(tcph);
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.s_addr = inet_addr("192.168.1.10"); //source ip
din.sin_family = AF_INET;
din.sin_port = htons(DEST_PORT);
din.sin_addr.s_addr = inet_addr(TARGET_SERV_IP); //ip serv to connect
tcph->port_dest = htons(DEST_PORT);
iph->ip_dest = din.sin_addr.s_addr;
iph->ip_source = sin.sin_addr.s_addr;
iph->ip_dest = inet_addr(TARGET_SERV_IP); //ip serv to connect
iph->ip_source = inet_addr("192.168.1.10"); //source ip
//iph->checksum = csum((unsigned short *)datagram, iph->tot_len >> 1);
iph->checksum = csum((unsigned short *)datagram, sizeof(struct iphdr));
int one = 1;
const int *val = &one;
if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)val, sizeof(one)) < 0)
printf("failled set socket option IP_HDRINCL");
else{
if (sendto(sock, /* our socket */
datagram, /* the buffer containing headers and data */
ntohs( iph->tot_len), /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &sin, /* socket addr, just like in */
sizeof(sin)) < 0) /* a normal send() */
cout << stderr << "sendto() error!!!.\n " << WSAGetLastError() << endl;
else
cout << "packet send\n" << endl;
}
closesocket(sock);
}
}
My error occurs at the sendto(). it return 10022 error = WSAEINVAL
I saw that can be a new windows protection?
Have you any idea to fix my problem or bypass the protection (go deeper, driver, etc)
You don't set iph->tot_len in your code.
My recommendation for networking code using c++ would be to use std::string or std::vector:
std::vector<uint8_t> packet(MAX_PACKET_SIZE, 0);
...
packet.resize(real_size);
then use the address (&packet[0]) for your pointer manipulations.

Problem with simple UDP client/server application

Ok. So I have a simple client program sending images over UDP to a specified IP address. At the specified IP a server program is listening and should receive the images.
When I try both programs on localhost (i.e. they are both running at 127.0.0.1) it works and the server receives the images. When I try to put the client and the server programs on different PCs in the same network it does not work.
147.232.24.163 is the server IP, 147.232.24.150 is the client IP.
Here is my client program:
// Initialize UDP.
struct sockaddr_in server;
int n_sent;
int socketId = socket(AF_INET, SOCK_DGRAM, 0);
if (socketId < 0)
{
cout << "Problem creating socket." << endl;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("147.232.24.163");
// Establish the server port number - we must use network byte order!
server.sin_port = htons(42001);
for ( int iter = 0; iter < 60; iter++ )
{
// load image into jpegBuf
n_sent = sendto(socketId, reinterpret_cast<char*> (&jpegBuf[0]), jpegBuf.size(), 0, (struct sockaddr*) &server, sizeof(server));
if (n_sent < 0) {
cout << "Problem sending data." << endl;
}
}
close(socketId);
Here is my server program:
int main()
{
int bufferSize = 1024000;
int iSockFd = -1;
int iLength = 0;
struct sockaddr_in servAddr, cliAddr;
char buff[bufferSize];
iSockFd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset(&servAddr, 0, sizeof(servAddr));
memset(&cliAddr, 0, sizeof(cliAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr("147.232.24.163");
servAddr.sin_port = htons(42001);
int cliAddrLen = sizeof(struct sockaddr_in);
int bindRet = bind(iSockFd, (struct sockaddr*)&servAddr, sizeof(servAddr));
cout << "Bind returned " << bindRet << endl;
int i = 0;
while (true)
{
int iRcvdBytes=recvfrom(iSockFd, buff, bufferSize, 0,
(struct sockaddr*)&cliAddr, (socklen_t*)&cliAddrLen);
if (0 == i % 5)
{
cout << "Received " << iRcvdBytes << " bytes from the client" << endl;
}
i++;
}
close(iSockFd);
return 0;
}
Any ideas why it does not work? I don't get any error messages.
This is not a solution but your code should be checking iRcvdbytes for error in the same way as the send code checks the result of sendto.
A return of 0 means the socket was closed gracefully (if connection-oriented - that should not apply here), SOCKET_ERROR means an error (in WinSock2 at least).
The socket on the send side needs to be created with IPPROTO_UDP, not 0. This could definitely be causing your failure.