hey guys i have been trying to make a simple console application to see my network traffic :P im trying to just read it.
anyways im getting an error from the WSAIoctl function and the error code WSAGetLastError is giving me is 10022 and the MSDN tells me that it is associated with this:
Invalid argument.
Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socket—for instance, calling accept on a socket that is not listening.
i have tried messing with the arguments without luck :/ please help me :P
here's my code:
WSADATA wsaData;
int startup = WSAStartup(0x0202, &wsaData);
if(startup != 0) {
cout << "Error: could not initalize WSADATA for target socket." << endl;
system("pause");
}
unsigned long BytesReturned;
int InBuffer, OutBuffer, LPCVoid;
int optValue = 1;
SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
Sleep(await);
cout << "creating and configuring RAW_SOCK" << endl;
int listening = listen(sock, SOMAXCONN); // tried debugging using this.
int sockopt = setsockopt(sock, IPPROTO_IP, 2, (char*)&optValue, sizeof(optValue));
int SockMode = WSAIoctl(sock, SIO_RCVALL, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL, NULL);
//0x98000001
if(SockMode == 0) {
Sleep(await);
cout << "RAW_SOCKET created successfully!" << endl << "Trying to listen for incoming network packets..." << endl;
int listeningk = listen(sock, SOMAXCONN);
if(listening == 0) {
Sleep(await);
cout << "socket listening without problems, looking for incoming request..." << endl;
}
else {
Sleep(await);
cout << "Error: could not listen on socket." << endl;
exit(EXIT_FAILURE);
}
}
else {
Sleep(await);
cout << "Error: could not create RAW_SOCKET..." << endl << "Dumping SockMode!\r\nint SockMode = " << SockMode << endl;
cout << "setsockopt = " << sockopt << endl;
cout << "WSAGetLastError: " << WSAGetLastError() << endl;
system("pause");
}
Your socket needs to be bound before you can listen. Moreover for this WSAIoctl option you have to obey (from the MSDN docs):
The socket also must be bound to an explicit local IPv4 or IPv6
interface, which means that you cannot bind to INADDR_ANY or
in6addr_any.
I'd suggest some basic self-education is in order before trying to progress this code. There are code samples for common ops like socket setup in MSDN.
Related
I'm trying to make a winsock server and I want to display the client's ip on the server when he connects but that's where there is a problem. Every time I try to connect it display 204.204.204.204. I tried to connect with another computer but the result was the same.
result in localhost
After this, I started looking for people having the same problem as me on this website and I found several people who had the same as me but they all had either the accept or the inet_ntop function that wasn't working correctly. So I check and none of this two functions return an error. Maybe I'm stupid but I really can't figured out what's the problem. (btw english is not my first language so please tell me if you noticed or if my english isn't too bad)
the part of the code that isn't working
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
the whole code if you need it
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <string>
#pragma comment(lib, "ws2_32.lib")
int main()
{
std::cout << "--- Tcp/ip Server ---" << std::endl;
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKET server = socket(AF_INET, SOCK_STREAM, 0);
if (server == INVALID_SOCKET)
{
std::cout << "error in SOCKET(): "<< WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in s;
s.sin_family = AF_INET;
s.sin_addr.s_addr = INADDR_ANY;
s.sin_port = htons(52000);
// bind
if (bind(server, (sockaddr*)&s, sizeof(s)) == SOCKET_ERROR)
{
std::cout << "Error: bind()" << std::endl;
}
//listen
if (listen(server, SOMAXCONN) == SOCKET_ERROR)
{
std::cout << "Error in listen(): " << WSAGetLastError() << std::endl;
WSACleanup();
}
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&client, &clientlen);
if (client == INVALID_SOCKET)
{
std::cout << "Error in accept(): " << WSAGetLastError << std::endl;
WSACleanup();
}
else
{
char clientIp[17];
if (inet_ntop(AF_INET, &from.sin_addr, clientIp, 17) == NULL)
{
std::cout << "Can't get the client's ip: " << WSAGetLastError() << std::endl;
}
std::cout << "ip connected: " << clientIp << std::endl;
// the code isn't finished yet
system("pause");
WSACleanup();
}
return 0;
}
You are passing the address of the wrong variable in the second parameter of accept().
You are passing the address of your SOCKET client variable that you are about to assign the result of accept() to. C++ allows a variable's address to be taken when declaring and initializing the variable in the same statement. But that is not what you want in this case. You need to pass the address of your sockaddr_in from variable instead:
sockaddr_in from;
int clientlen = sizeof(from);
// accept
SOCKET client = accept(server, (SOCKADDR*)&from, &clientlen); // <-- &from instead of &client
You are leaving your from variable uninitialized, and your compiler fills uninitialized variables with 0xCC (decimal 204) bytes in debug mode, so that is why you end up seeing 204.204.204.204 (hex 0xCC 0xCC 0xCC 0xCC) from inet_ntop() when you don't initialize your from variable properly.
This question already has answers here:
What are the use cases of SO_REUSEADDR?
(2 answers)
Closed 7 years ago.
discovering TCP socket, I made a very simple test based on my understanding of the subject and some tuto found on the net
Server :
void Server(void)
{
int localSocket;
int distantSocket;
sockaddr_in serverInfo;
sockaddr_in clientInfo;
int sizeOfSocketInfo = sizeof(struct sockaddr_in);
/* Open Socket */
std::cout << "open socket" << std::endl;
localSocket = socket(AF_INET, SOCK_STREAM, 0);
if (localSocket == -1)
{
std::cout << "open failed, error - " << (int)errno << std::endl;
exit(errno);
}
/* Configure server */
serverInfo.sin_addr.s_addr = INADDR_ANY;
serverInfo.sin_family = AF_INET;
serverInfo.sin_port = htons(61001);
/* Bind Socket */
std::cout << "bind socket" << std::endl;
if (bind (localSocket, (sockaddr *) &serverInfo, sizeof(serverInfo)) == -1)
{
std::cout << "bind failed, error - " << (int)errno << std::endl;
exit(errno);
}
/* Wait for client */
std::cout << "Wait for client ..." << std::endl;
listen(localSocket, 1);
distantSocket = accept(localSocket, (sockaddr *)&clientInfo, (socklen_t*)&sizeOfSocketInfo);
std::cout << "client connected - " << inet_ntoa(clientInfo.sin_addr) << std::endl;
/* Close Socket */
close (localSocket);
close (distantSocket);
std::cout << "socket closed" << std::endl;
}
and client :
void Client(void)
{
int localSocket;
sockaddr_in clientInfo;
/* Open Socket */
std::cout << "open socket" << std::endl;
localSocket = socket(AF_INET, SOCK_STREAM, 0);
if (localSocket == -1)
{
std::cout << "open failed, error - " << (int)errno << std::endl;
exit(errno);
}
clientInfo.sin_family = AF_INET;
clientInfo.sin_port = htons(61001);
clientInfo.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Open Socket */
std::cout << "connect to server" << std::endl;
if (connect(localSocket, (sockaddr*)&clientInfo, sizeof(clientInfo)) < (int)0)
{
std::cout << "connect failed, error - " << (int)errno << std::endl;
exit(errno);
}
std::cout << "connected !" << std::endl;
close(localSocket);
}
When I launch the server in one terminal and the client in another one, it seems to be ok :
server side :
> ./tcpTest -s
open socket
bind socket
Wait for client ...
client connected - 127.0.0.1
socket closed
>
and client side :
> ./tcpTest -c
open socket
connect to server
connected !
>
But, if, just after this first try, I launch the server again ...
> ./tcpTest -s
open socket
bind socket
bind failed, error - 98
>
And I have to wait a "certain time", I don't know exactly how long, one minute maybe, to have the server working again.
I can't figure out what's happening, looking to open socket with sockstat does not show anything strange (I only see mozilla socket).
I found this guy having the same problem but in Ruby
basic Ruby TCP server demo fails on startup: `bind': Address already in use, Errno::EADDRINUSE
If this is really the same problem, how can I apply the same solution in C++ ? Or do you have any idea ?
Thank you
You may need to use both SO_REUSEADDR and SO_REUSEPORT. You can further go through the documentation of Socket: Socket Docs
const int trueFlag = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &trueFlag, sizeof(int)) < 0)
error("Failure");
You can use reuse Port in similar way. Hope this helps
Try setsockopt(SO_REUSEADDR), this should help.
it may be a strange request, but, actually, I would like make my call to recv() blocking.
It appears that it should be blocking by default, but for me, it is not, and I can't find any way to make it.
I have a very simple server application, "open socket - bind - wait for connection - receive" on one hand,
and, on the other hand, a simple "open socket - connect - send" client application.
They communicate on LocalHost.
Server :
int clTcpServer::openSocket(void)
{
this->__iLocalSocketId = socket(AF_INET, //stand for IPV4
SOCK_STREAM, //using TCP protocol
0); //no specified / ip protocol
return 0;
}
int clTcpServer::openServer(uint16_t u16Port)
{
this->__strServerInfo.sin_family = AF_INET; // stand for IPV4
this->__strServerInfo.sin_addr.s_addr = INADDR_ANY; // Listen to any address (no filter)
this->__strServerInfo.sin_port = htons(u16Port);
if(bind(this->__iLocalSocketId, (sockaddr *)&this->__strServerInfo, sizeof(this->__strServerInfo)) < 0)
{
std::cout << "TCP server - ERROR - Can't bind socket to port " << std::dec << (int)u16Port << std::endl;
return -1;
}
std::cout << "TCP server - Server opened" << std::endl;
listen(this->__iLocalSocketId, 3);
return 0;
}
int clTcpServer::waitForConnection(void)
{
int iClientIpInfo;
char* pcClientIp;
std::cout << "Waiting for connection ..." << std::endl;
iClientIpInfo = sizeof(struct sockaddr_in);
this->__iDistantSocketId = accept(this->__iLocalSocketId,
(sockaddr *)&this->__strClientInfo,
(socklen_t*)&iClientIpInfo);
if(this->__iDistantSocketId < 0)
{
std::cout << "TCP server - ERROR - Connection refused" << std::endl;
return -1;
}
pcClientIp = inet_ntoa(this->__strClientInfo.sin_addr);
std::cout << "Connection accepted from " << pcClientIp << std::endl;
return 0;
}
int clTcpServer::receiveDataBuffer(void * pvidBuffer, size_t sizeMaxBufferSize)
{
int iRecvSize;
iRecvSize = recv(this->__iDistantSocketId, pvidBuffer, sizeMaxBufferSize, (int)0);
if (iRecvSize < (int)0 )
{
std::cout << "TCP server - ERROR - Recv failed" << std::endl;
return -1;
}
return iSentSize;
}
Client :
int clTcpClient::openSocket(void)
{
/* Create a new socket for client comm. */
this->__iSocketId = socket( AF_INET, //stand for IPV4
SOCK_STREAM, //using TCP protocol
0); //no specified / ip protocol
if (this->__iSocketId == (int)-1)
{
std::cout << "TCP client - ERROR - Can't open Socket" << std::endl;
return -1;
}
return 0;
}
int clTcpClient::connectToServer(std::string stgIpAddress, uint16_t u16Port)
{
/* configure server info according to parameters */
this->__strServerInfo.sin_family = AF_INET; //stand for IPV4
this->__strServerInfo.sin_port = htons(u16Port);
/* Retrieve IP addr*/
this->__strServerInfo.sin_addr.s_addr = inet_addr(stgIpAddress.c_str());
/* Try to connect to the server */
if (connect(this->__iSocketId,
(sockaddr*)&this->__strServerInfo,
sizeof(this->__strServerInfo)) < 0)
{
std::cout << "TCP client - ERROR - Can't connect to " << stgIpAddress << ":" << std::dec << (int)u16Port << std::endl;
return -1;
}
std::cout << "TCP client - Connected" << std::endl;
return 0;
}
int clTcpClient::sendDataBuffer(const void *kpvidData, size_t sizeDataLength)
{
ssize_t sizeSentSize;
/* Send the buffer */
sizeSentSize = send(this->__iSocketId, kpvidData, sizeDataLength, (int)0);
if (sizeSentSize < (ssize_t)0 )
{
std::cout << "TCP client - ERROR - Send failed" << std::endl;
return -1;
}
std::cout << "TCP client - " << (int)sizeSentSize << " byte(s) sent." << std::endl;
return 0;
}
This is working fine, but recv() here is not blocking. If I call it (after having initialized all the stuff, of course), if there is nothing to receive, the function returns 0, as "0 byte received", and that's all.
It means If I want to put this recv function in a loop, CPU is working 100% to receive ... nothing.
What's wrong here ?How can I make it blocking ?
Thank you
I am new to Winsock programming and came across this code while reading the book "Network Programming For Microsoft Windows " . But it seems that this code is not able to connect to the client. Please tell me how can I fix this problem .
My Server Code :
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main(){
WSADATA wsadata;
int ret;
if ((ret = WSAStartup(MAKEWORD(2, 2), &wsadata)) != 0){
cout << "Wsastartup failed" << endl;
}
else{
cout << "connection made successfully" << endl;
}
SOCKET ListeningSocket, NewConnection;
SOCKADDR_IN ServerAddr, ClientAddr;
int port = 80;
ListeningSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(port);
inet_pton(ServerAddr.sin_family,"127.0.0.1",&ServerAddr.sin_addr.s_addr);
int res= bind(ListeningSocket,(SOCKADDR*)&ServerAddr,sizeof(ServerAddr));
if (res == SOCKET_ERROR){
cout << "binding failed" << endl;
}
res = listen(ListeningSocket,5);
if (res == SOCKET_ERROR){
cout << "Listening failed" << endl;
}
int c = 1;
NewConnection= accept(ListeningSocket,(SOCKADDR*)&ClientAddr,&c);
if (NewConnection == INVALID_SOCKET){
cout << "COULD not CONNECT TO CLIENT . err code : "<<WSAGetLastError() << endl;
}
closesocket(ListeningSocket);
if (WSACleanup() == SOCKET_ERROR){
cout << "WSACleanup failed with error : " << WSAGetLastError() << endl;
}
else{
cout << "WinSock data cleaned successfully" << endl;
}
cin.get();
}
On running this code , it shows "COULD not CONNECT TO CLIENT. err code 10014" .
I've found this Description of the error code on windows dev center :
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).
How can I fix this error ?
When you call accept, the variable that the third parameter points to needs to hold the size of the buffer the second parameter points to. (When accept returns, it will hold the amount of space actually used)
In your code, change:
int c = 1;
to
int c = sizeof(ClientAddr);
im stuck with sending a raw ethernet frame.
[edit]
I found some errors.
1. It has to be AF_PACKET in the socket call.
2. AF_PACKET doesnt have an option SOCK_PACKET, but SOCK_DGRAM and SOCK_RAW
With SOCK_DGRAM wireshark captures a malformed LLC packet.
But with SOCK_RAW no error message and no captured packet.
i dont find whats really going wrong.
[/edit]
the code:
if ((ethernet_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1)
cout << "Ethernet Socket: "<< strerror(errno) << endl;
struct sockaddr_ll socket_address;
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_ifindex=if_nametoindex("eth0");
socket_address.sll_hatype = 1; // ARPHRD_ETHER
socket_address.sll_pkttype = PACKET_OTHERHOST;
socket_address.sll_halen = ETH_ALEN;
memcpy(socket_address.sll_addr,dest_mac_addr,ETH_ALEN);
int send_result = 0;
char *opt=(char*)malloc(4*sizeof(char));
strcpy(opt,"eth0");
if(setsockopt(ethernet_socket, SOL_SOCKET, SO_BINDTODEVICE, opt, 4)==-1)
cout << "Could not bind socket to device: " << strerror(errno) << endl;
if ((send_result
= sendto(ethernet_socket, &buffer, sizeof(buffer), 0,
(struct sockaddr*)&socket_address, sizeof(socket_address)))==-1){
cout << "sendto error: "<< strerror(errno) << endl;
return send_result;
}
regards
Ck
I found the solution how this works.
i took a look at the source code of the Linux program PackEth.
the following code works for me.
if ((ethernet_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1)
cout << "Ethernet Socket: "<< strerror(errno) << endl; //errorhandling
memset(&ifr, 0, sizeof(ifr));
strncpy (ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
if (ioctl(ethernet_socket, SIOCGIFINDEX, &ifr) == -1) {
cout << "No such interface:"<< strerror(errno) << endl;
close(ethernet_socket);
}
ioctl(ethernet_socket, SIOCGIFFLAGS, &ifr);
if ( (ifr.ifr_flags & 0x1) == 0) {
cout << "Interface is down: "<< strerror(errno) << endl;
close(ethernet_socket);
}
ioctl(ethernet_socket, SIOCGIFINDEX, &ifr);
memset(&socket_address, 0, sizeof (socket_address));
socket_address.sll_family = AF_PACKET;
socket_address.sll_ifindex = ifr.ifr_ifindex;
socket_address.sll_protocol = htons(ETH_P_ALL);
if ((raw_send = sendto(ethernet_socket, buffer, size_payload+14,0,(struct sockaddr*)
&socket_address, sizeof(socket_address)))==-1){
cout << "sendto error: "<< strerror(errno) << endl;
return raw_send;
}
$ man 7 packet
"SOCK_RAW packets are passed to and from the device driver without any changes in the packet data. When receiving a packet, the address is still parsed and passed in a standard sockaddr_ll address structure. When transmitting a packet, the user supplied buffer should contain the physical layer header. That packet is then queued unmodified to the network driver of the interface defined by the destination address. Some device drivers always add other headers.
SOCK_DGRAM operates on a slightly higher level. The physical header is removed before the packet is passed to the user. Packets sent through a SOCK_DGRAM packet socket get a suitable physical layer header based on the information in the sockaddr_ll destination address before they are queued."