2

I'm trying to handle incoming network packets with RAW SOCKET in Windows 10.

When I call recvfrom() function it returns -1 value. WSAGetLastError is 10022.

Microsoft Docs page give me the following description:

WSAEINVAL: 10022
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 to use setsockopt() to set IP_HDRINCL to 1, but it returns the same error when I call recvfrom().

My source code:

#include "stdio.h"
#include "winsock2.h"
#include "ws2tcpip.h"


int main(){
    SOCKET s;
    char* buff = malloc(256);
    int optval = 1;
    struct sockaddr_in adr;
    int adr_length = sizeof(adr);
    int i;
    int rcv_len;
    WSADATA wsa;

    memset(buff, 0, 256);

    if(WSAStartup(MAKEWORD(2,2), &wsa) != 0){
        printf("Error in WSAStartup: %d\n", WSAGetLastError());
        getch();
        return 0;
    }

    s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if(s == SOCKET_ERROR){
        printf("Error in socket creation: %d\n", WSAGetLastError());
        getch();
        return 0;
    }

    if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval)) == -1){
        printf("Error in setsockopt(): %d\n", WSAGetLastError());
        getch();
        closesocket(s);
        return 0;
    }

    while(1){
        rcv_len = recvfrom(s, buff, 256, 0, (struct sockaddr*)&adr, &adr_length);

        if(rcv_len == -1){
            printf("Error in recvfrom(): %d\n", WSAGetLastError());
            getch();
            break;
        }

        for(i = 0; i < 256; i ++){
            printf("%c", *(buff + i));
        }
    }

    closesocket(s);

    return 1;
}

Return:

Error in recvfrom(): 10022
Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
Raphael
  • 114
  • 6
  • Do you really need a raw socket? Microsoft has been gradually clamping down on what can be done with raw sockets in Windows. In fact, I am not sure they ever really supported it completely, the way some *nix OS's do. – jwdonahue May 09 '20 at 18:43
  • Do you keep obtaining the error if you set both `addr`and `addrLen` to NULL? – Roberto Caboni May 09 '20 at 18:51
  • @jwdonahue, I'm studing RAW SOCKET, this project is only for study purpose. I will try to study winpcap too, but I'm trying to handle packets with RAW SOCKET before. Maybe I won't get success to handle IP PACKETS in this way? – Raphael May 09 '20 at 23:44
  • @RobertoCaboni, the same error occurs without initializing adr and adr_length, or initializing with 0 in all structure's variables, or initializing with AF_INET, INADR_ANNY, port = 0 and adr_length = sizeof(adr). When I use bind() the recvfrom() call don't returns error, but I don't receive any packets. – Raphael May 09 '20 at 23:52

1 Answers1

3

I have fixed the problem.

What was missing:

  1. Turn on the SOCKET with bind() using the IP of the interface you are handling
  2. Set opt SO_RCVALL to 1 with WSAIoctl()

So, now the code is working with this source:

#include "stdio.h"
#include "winsock2.h"
#include "ws2tcpip.h"

int main(){
    SOCKET s;
    unsigned char* buff = malloc(32768);
    int optval = 1;
    struct sockaddr_in adr;
    struct sockaddr_in sadr;
    int adr_length = 0;
    int i;
    int in;
    int rcv_len;
    WSADATA wsa;

    memset(buff, 0, 32768);

    if(WSAStartup(MAKEWORD(2,2), &wsa) != 0){
        printf("Error in WSAStartup: %d\n", WSAGetLastError());
        getch();
        return 0;
    }

    s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if(s == SOCKET_ERROR){
        printf("Error in socket creation: %d\n", WSAGetLastError());
        getch();
        return 0;
    }

    sadr.sin_family = AF_INET;
    sadr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sadr.sin_port = htons(0);

    bind(s, (struct sockaddr*)&sadr, sizeof(sadr));

    if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval)) == -1){
        printf("Error in setsockopt(): %d\n", WSAGetLastError());
        getch();
        closesocket(s);
        return 0;
    }

    optval = 1;
    WSAIoctl(s, SIO_RCVALL, &optval, sizeof(optval), 0, 0, (LPDWORD) &in, 0, 0);

    while(1){
        adr_length = sizeof(adr);
        rcv_len = recvfrom(s, buff, 32768, 0, (struct sockaddr*)&adr, &adr_length);

        if(rcv_len == -1){
            printf("Error in recvfrom(): %d\n", WSAGetLastError());
            getch();
            break;
        }

        for(i = 0; i < rcv_len; i ++){
            printf("%d ", *(buff + i));
        }
    }

    closesocket(s);

    return 1;
}

Thank you all!

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
Raphael
  • 114
  • 6