I'am writing a simple network sniffer on windows xp.
Here is the code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
void die(const char* msg) {
printf("Error: %s\n", msg);
exit(-1);
}
int Init(WSADATA wsa) {
return WSAStartup(0x0101, &wsa);
}
int main(int argc, char** argv) {
WSADATA wsa;
if(Init(wsa)) die("init");
SOCKET s;
long flag = 1;
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = 0;
local.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET) die("invalid socket");
if(bind(s, (SOCKADDR*) &local, sizeof(local)) == SOCKET_ERROR) die("bind");
if(ioctlsocket(s, SIO_RCVALL, &flag)) die("ioctl");
struct sockaddr_in remote;
int rsize = sizeof(remote);
int rcvd = 0;
char buff[0xFFFF]; //64k
int ip_len = 0;
int i = 0;
while((rcvd = recvfrom(s, buff, sizeof(buff), 0, (SOCKADDR*) &remote, &rsize)) != SOCKET_ERROR) {
ip_len = (buff[2] & 0xFF << 8) | (buff[3] & 0xFF);
if(ip_len != rcvd) {
printf("\nIPLEN: %6i, RECVFROM: %6i", ip_len, rcvd);
} else {
printf(".");
}
}
printf("Error: %i\n", WSAGetLastError());
return (EXIT_SUCCESS);
}
Packets are caught, but i have a problem: value, returned by recvfrom (number of bytes read) differs from IPv4 packet's ip_len field.
Here is the example of output:
Code:
IPLEN: 39, RECVFROM: 551...
IPLEN: 187, RECVFROM: 955..
IPLEN: 112, RECVFROM: 880..
IPLEN: 250, RECVFROM: 762
IPLEN: 122, RECVFROM: 890.
IPLEN: 39, RECVFROM: 295...
IPLEN: 96, RECVFROM: 608........
IPLEN: 122, RECVFROM: 890....
IPLEN: 22, RECVFROM: 534.....
IPLEN: 9, RECVFROM: 521..
IPLEN: 79, RECVFROM: 847..
(dots means packets with equal values)
So, how to fix this?