问题
I'm trying to modify my current socketing program to capture packets in promiscuous. What I currently have is able to capture packets normally. I've seen other answer for how to do this on Linux but I need to find a way to accomplish this on Windows.
Here is my code:
int main(int argc, char const *argv[])
{
SOCKET s; //The bound socket
struct sockaddr_in server;
int recv_len; //Size of received data
char udpbuf[BUFLEN]; //A buffer for the incoming data.
float data; //The data in the packet
//Create a socket
if ((s = socket(AF_INET, SOCK_RAW, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ADDR);
server.sin_port = htons(PORT);
//Bind socket to address
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done\n");
while (true)
{
//Block statment. Code will wait until it detect packets.
if ((recv_len = recvfrom(s, udpbuf, BUFLEN, 0, 0, 0)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
return 0;
}
回答1:
To put a socket into promiscuous mode on Windows, you need to call WSAIoCtl() to issue a SIO_RCVALL control code to the socket.
int main(int argc, char const *argv[])
{
WSADATA wsa;
SOCKET s; //The bound socket
struct sockaddr_in server;
int recv_len; //Size of received data
char udpbuf[BUFLEN]; //A buffer for the incoming data.
//Initialize Winsock
int err = WSAStartup(MAKEWORD(2,0), &wsa);
if (err != 0)
{
printf("Could not initialize Winsock : %d", err);
exit(EXIT_FAILURE);
}
//Create a socket
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
WSACleanup();
exit(EXIT_FAILURE);
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ADDR);
server.sin_port = htons(PORT);
//Bind socket to address
if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d", WSAGetLastError());
closesocket(s);
WSACleanup();
exit(EXIT_FAILURE);
}
puts("Bind done\n");
// enable promiscuous mode
DWORD dwValue = RCVALL_ON;
DWORD dwBytesReturned = 0;
if (WSAIoctl(s, SIO_RCVALL, &dwValue, sizeof(dwValue), NULL, 0, &dwBytesReturned, NULL, NULL) == SOCKET_ERROR)
{
printf("Ioctl failed with error code : %d", WSAGetLastError());
closesocket(s);
WSACleanup();
exit(EXIT_FAILURE);
}
puts("Ioctl done\n");
while (true)
{
//Block statment. Code will wait until it detect packets.
if ((recv_len = recvfrom(s, udpbuf, BUFLEN, 0, 0, 0)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d", WSAGetLastError());
closesocket(s);
WSACleanup();
exit(EXIT_FAILURE);
}
}
closesocket(s);
WSACleanup();
return 0;
}
Alternatively, Microsoft also has a separate Network Monitor API that allows you to monitor and capture network traffic without using Winsock at all.
回答2:
I'd recommend you to use the winpcap library. See www.winpcap.org. They have comprehensive documentation and examples on how to do this: https://www.winpcap.org/docs/docs_412/html/group__wpcap__tut3.html
E.g. Wireshark uses winpcap on windows.
来源:https://stackoverflow.com/questions/53160861/c-sockets-enabling-promiscuous-mode-in-windows