Setting SO_BROADCAST to a socket fails with "Invalid argument" - c++

My IDE: xCode, OS X 10.10.4
int s = socket(AF_INET, SOCK_DGRAM, 0);
bool bc = true;
int ret = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (const void*)&bc, sizeof(bool));
if(ret < 0){
perror("set opt err:");
}
sockaddr_in tarAddr;
memset(&tarAddr, 0, sizeof(sockaddr_in));
tarAddr.sin_family = AF_INET;
tarAddr.sin_port = htons(5000);
tarAddr.sin_addr.s_addr = INADDR_BROADCAST;
char szMsg[100] = {0};
strcpy(szMsg, "hello");
int len = sizeof(sockaddr);
ret = sendto(s, szMsg, strlen(szMsg), 0, (sockaddr*)&tarAddr, len);
if(ret < 0){
perror("sendto err:");
}
close(s);
The above code is about send udp message to broadcast, but the result info is:
set opt err: Invalid argument
sendto err: Permission denied
and the same code go fine in vc++/windows.

Maybe the argument sizeof(bool) returns an invalid value. As you can see in the following link, it is not defined that sizeof(bool)should deliver 1.
Is sizeof(bool) defined?
I also think that you don't have to cast the pointer in the function call. It would be enough only to have the &.
Can you provide some code of the sendto()function to determine the other error?

I changed bc to int and this solve the problem

As has been insinuated, your optval is wrong.
From the socket manpage:
The socket options listed below can be set by using setsockopt(2) and
read with getsockopt(2) with the socket level set to SOL_SOCKET for
all sockets. Unless otherwise noted, optval is a pointer to an int.
You're giving it a pointer to a bool instead.
Fortunately, the function is able to detect this (possibly sizeof(bool) differs from sizeof(int) on your platform, or otherwise its reinterpreting a bool as an int simply results in a value it doesn't recognise; it's UB anyway), so you get a nice error telling you that your argument is wrong.
Remember, the function doesn't know the type of your data (as it gets a void*), so even if it wanted to be able to accept an int or a bool or llama it would have no way of doing so.

Related

Why am I getting "Invalid argument" from this sendto()?

So I'm passing an argument to my main which is an IP as char* name ipStr.
Then I'm initialising a variable to hold the length of it before calling sendto():
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
char buffer[8];
socklen_t ipLen = sizeof(ipStr);
res = sendto(sock, buffer, sizeof(buffer), 0,
(struct sockaddr*) &ipStr, ipLen);
Yet I'm still getting Invalid argument as a returned error.
I'm getting no compile errors with g++ so I'm not sure where the problem is.
EDIT
I noticed I hadn't deleted sizeof before ipLen, changed the above and still getting Invalid argument.
Your sockaddr is probably wrong, it's a struct with a binary representation of the address and some other data in it. It's a sockaddr_in cast to a sockaddr.
Try:
struct sockaddr_in ip4addr;
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons(1234);
addrDest.sin_addr.s_addr = inet_addr("1.2.3.4");
socklen_t ipLen = sizeof(ipStr) returns the size of ipStr data type, not the length of the string it points to. The data type of ipStr is char *, and sizeof(ipStr)therefore yields 8 (or 4 on 32 bit systems). So your parameter will probably not be interpreted correctly.
Use socklen_t ipLen = strlen(ipStr) instead.

Winsock error on accept function

I'm trying to make a simple botnet(not for evil purposes) with winsock, the client is ok(at least at the syntax), but the server has error when i call the accept function, it returns SOCKET_ERROR, i called WSAGetLastError() to get the error number and it returned 10014. In the MSDN page, it says this:
Bad address.
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).
Well, i don't have any idea of what to do.
botnetserver.cpp
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#define PORT 5051
#define BUFFMAX 1024 // Buffer max
using namespace std;
int main() {
SOCKADDR_IN svaddr; // server address
SOCKADDR_IN claddr; // client addres
SOCKET listensocket;
SOCKET client;
WSADATA WsaData;
char buffer[BUFFMAX];
int i = sizeof(client);
//ShowWindow(GetConsoleWindow(), SW_HIDE);, fail
WSAStartup(MAKEWORD(2, 2), &WsaData);
listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
svaddr.sin_family = AF_INET;
svaddr.sin_port = htons(PORT);
svaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(listensocket, (SOCKADDR*) &svaddr, sizeof(svaddr));
client = listen(listensocket, 5)) == SOCKET_ERROR
accept(listensocket, (SOCKADDR*)&claddr, &i) // Error here
while(true) {
/* other things i tried
cout << "\n\n" << buffer << "\n\n";
cout << o << "\n";
buffer[BUFFMAX] = '\0';*/
recv(client, buffer, BUFFMAX, 0);
if(strcmp(buffer, "<fim>") != 0) {
system(buffer);
//break;
} else {break;}
}
closesocket(client);
closesocket(listensocket);
WSACleanup();
system("pause");
}
There are two mistakes in your code:
int i = sizeof(client);
i needs to be initialized as sizeof(claddr) instead. This is what accept() is failing on. sizeof(client) is smaller than sizeof(claddr) so accept() thinks your claddr buffer is too small to receive the client's IP address. This is clearly stated in the documentation you quoted:
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).
client = listen(listensocket, 5)) == SOCKET_ERROR
client is a SOCKET handle. You cannot assign the result of the == operator to a SOCKET. You need to assign the result of accept() to client instead.
Change those lines to look like this instead:
int i = sizeof(claddr);
...
listen(listensocket, 5);
client = accept(listensocket, (SOCKADDR*)&claddr, &i);
With that said, you also need to fix your recv() loop. recv() does not return null-terminated data, but strcmp() requires that. You need to null-terminate the buffer after reading, or use strncmp() instead, using the result of recv() as the buffer length. And you need to take into account that it may take multiple calls to recv() to receive <fim>, so you need to implement proper buffering.
And, you need to add proper error handling on ALL function calls.

setsockopt: Bad file descriptor in C++

I have the famous error "address already in use" because I have no check for the bind function.
Here is my code:
memset(&(this->serv_addr), 0, sizeof(this->serv_addr));
this->serv_addr.sin_family = AF_INET;
this->serv_addr.sin_port = htons(port);
this->serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int yes = 1;
if (setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
But running code I got this:
setsockopt: Bad file descriptor
The code is right, from the guide Beejnet.
But why I got the error?
Maybe the position of the code is wrong?
The first the that sock_fd is called is in the function w_socket:
int retv;
retv = socket(AF_INET, SOCK_STREAM, 0);
if(retv == -1)
{
std::string err_msg(strerror(errno));
err_msg = "[socket] " + err_msg;
throw err_msg;
}
else
{
int reuse_opt = 1;
setsockopt(this->sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse_opt, sizeof(int));
return retv;
}
}
By default there's the sesockopt but no check.
I've tried but it doesn't work.
You need to first create the socket via the socket call, like:
sock_fd = socket(PF_INET, SOCK_STREAM, 0);
(and check the return value; see man 2 socket for details)
Only then you may do your setsockopt call. Before the call to socket, your sock_fd variable will contain a random value (or 0) instead of a socket file descriptor.
Edit after updated question:
Your call to setsockopt needs to use retv instead of this->sock_fd as at that point in time, the this->sock_fd variable is not yet containing the result of your call to socket.

linux system call getpeername c++

In my c++ application I'm using getpeername system call and it return 0.0.0.0 in the var sa.
there is no error in errno, and the return code is 0.
here is the code:
int GetSock(int sock)
{
struct sockaddr_storage ss;
socklen_t salen = sizeof(ss);
struct sockaddr *sa;
struct addrinfo hints, *paddr, *paddrp;
sa = (struct sockaddr *)&ss;
if (getpeername(sock, sa, &salen) != 0) {
error = errno;
return -1;
}
}
note: I'm compiling this code with GCC in eclipse.
any help?
thanks!
error = errno;
return -1;
}
/* Did you mean to return something right here? */
}
Upon successful completion, 0 shall be returned. Otherwise, -1 shall be returned and errno set to indicate the error.
EDIT: Check what is the value of sock is. getpeername only extracts and stores the peer address of the socket, in this case sock, and stores it in sa. If your socket isn't created or your socket isn't bound to a named socket, what sa points to is unspecified and this may be your case.

Socket Send error

I am using a unix socket. When buffer is send to the socket it gives me unknown error 196.
Please help on this.
BOOL SendData(int iBuffer)
{
//Send data over socket
int nRet = send(m_listenSock, m_cBuffer, iBuffer, 0);
if(SOCKET_ERROR > nRet)
{
//log the error char temp;
int length= sizeof(int);
int rc = getsockopt(m_listenSock,SOL_SOCKET,SO_ERROR,&temp,(socklen_t *)&length);
//if(rc == 0)
{
errno = temp;
perror("\nError is");
}
#ifndef LINUX
WSACleanup();
#else
close(m_listenSock);
#endif
printf("\nSend data failed to");
return FALSE;
}
return TRUE;
}
If errno is set but the call didn't fail (i.e. it didn't return -1), then errno's value isn't related to the last call you did. You can try clearing first:
errno = 0;
To be on the safe side. What I'm trying to say is that you can't know that the value of errno is relevant except right after the call that set it. You must check all calls you do that can fail for success/failure.
To detect an error you SHOULD be checking that send returns -1. I don't know what SOCKET_ERROR is, but if it's -1, then the above code won't work right anyway.
Assuming you do get -1 from send(), then an error code will be in errno. It is not necessary to do a getsockopt to retrieve it.
There is no error code 196, so I'd be deeply suspicious about your error handling.
Also, if send() fails, you should probably not close the socket. You haven't specified either the address family or socket type, but I'm assuming AF_INET and SOCK_DGRAM respectively (i.e. UDP)