1
votes

I want to send a UDP packet using the raw socket. If that works, next, I'd like to send by my own protocol using raw socket at e.g 89 instead of 17. Unfortunately nothing happens when I try to send a UDP packet on the Windows.There is no error code, so it should be sent but not... In the wireshark, I don't see any traffic during the program launch. The Windows firewall is off, so there's nothing to block. App also running with admin privileges.

I'll add that the same program works without problems on linux. The only difference is that there is no "WSAStartup", and I use "errno.h" to get error codes, besides the whole code is identical.

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <stdint.h>
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#include <ws2ipdef.h>
#include <WS2tcpip.h>
#include <BaseTsd.h>
#include <inaddr.h>
typedef SSIZE_T ssize_t;


#define MAXHOSTNAMELEN 256
#define MSGSIZE 64
#define TTL 23
#define MESSAGE "azertyuiopqsdf"


static char     source_addr[INET_ADDRSTRLEN];
static int      protocol = 17;

static int      port = 572;


static char     progname[MAXHOSTNAMELEN + 1];

struct ip {
    u_char  ip_hl : 4,      /* header length */
        ip_v : 4;           /* version */

    u_char  ip_tos;         /* type of service */
    short   ip_len;         /* total length */
    u_short ip_id;          /* identification */
    short   ip_off;         /* fragment offset field */
#define IP_DF 0x4000            /* dont fragment flag */
#define IP_MF 0x2000            /* more fragments flag */
    u_char  ip_ttl;         /* time to live */
    u_char  ip_p;           /* protocol */
    u_short ip_sum;         /* checksum */
    struct  in_addr ip_src, ip_dst; /* source and dest address */
};
struct udphdr {
    u_short uh_sport;       /* source port */
    u_short uh_dport;       /* destination port */
    short   uh_ulen;        /* udp length */
    u_short uh_sum;         /* udp checksum */
};

struct udp_pseudo_header {
    struct  in_addr ip_src, ip_dst; /* source and dest address */
    u_char mbz, ip_p;
    u_short length;
};

struct opacket4 {
    struct ip       ip;
    struct udphdr   udp;
    char            payload[MSGSIZE];
};

uint16_t checksum(const void* buf, size_t buflen) {
    uint32_t r = 0;
    size_t len = buflen;

    const uint16_t* d = reinterpret_cast<const uint16_t*>(buf);

    while (len > 1) {
        r += *d++;
        len -= sizeof(uint16_t);
    }

    if (len) {
        r += *reinterpret_cast<const uint8_t*>(d);
    }

    while (r >> 16) {
        r = (r & 0xffff) + (r >> 16);
    }

    return static_cast<uint16_t>(~r);
}

char* text_of(struct sockaddr *address) {
    char           *text = (char*)malloc(INET_ADDRSTRLEN);
    struct sockaddr_in *address_v4;
    struct sockaddr_in6 *address_v6;
    if (address->sa_family == AF_INET) {
        address_v4 = (struct sockaddr_in *) address;
        inet_ntop(AF_INET, &address_v4->sin_addr, text, INET_ADDRSTRLEN);
    } else if (address->sa_family == AF_INET6) {
        address_v6 = (struct sockaddr_in6 *) address;
        inet_ntop(AF_INET6, &address_v6->sin6_addr, text, INET_ADDRSTRLEN);
    } else {
        strcpy(text, "Unknown address family");
    }
    return text;
}

int main(int argc, char **argv) {
    char            c;
    char            hostname[MAXHOSTNAMELEN + 1] = "31.24.11.66";
    char            message[MSGSIZE];
    int             status;
    struct addrinfo hints_numeric, hints;
    struct addrinfo *result, *source;
    size_t          packetsize, headersize, extraipheadersize;
    struct opacket4 op4;
    struct sockaddr_in *sockaddr4;
    struct sockaddr_in6 *sockaddr6;
    void           *packet;
    int             on = 1;


    strncpy(progname, argv[0], MAXHOSTNAMELEN);
    progname[MAXHOSTNAMELEN] = 0;
    int             sd;         // Socket Descriptor */
    ssize_t         num;
    strcpy(message, MESSAGE);
    strcpy(source_addr, "");

    WSADATA wsaData;
    
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
        printf("Initialization error.\n");

    int protocol = 17;//UDP

    memset(&hints_numeric, 0, sizeof(hints_numeric));
    hints_numeric.ai_flags = AI_NUMERICHOST;
    hints_numeric.ai_socktype = SOCK_RAW;
    hints_numeric.ai_protocol = IPPROTO_RAW;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_RAW;
    hints.ai_protocol = IPPROTO_RAW;
    result = (addrinfo*)malloc(sizeof(struct addrinfo));
    status = getaddrinfo(hostname, NULL, &hints_numeric, &result);
    if (status && status == EAI_NONAME) {   // It may be a name, but it is * certainly not an address  
        status = getaddrinfo(hostname, NULL, &hints, &result);
        if (status) {
            fprintf(stderr, "Nothing found about host name %s\n", hostname);
            abort();
        }
    }
    fprintf(stdout, "Connecting to %s...\n", text_of(result->ai_addr));

    sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    if (sd == SOCKET_ERROR) {
        printf("Cannot create raw socket: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) == SOCKET_ERROR) {
        printf("Cannot set IP_HDRINCL: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    sockaddr4 = (struct sockaddr_in *) result->ai_addr;
    memset(&op4.ip, '\0', sizeof(op4.ip));
    op4.ip.ip_v = 4;
    op4.ip.ip_hl = sizeof(op4.ip) >> 2;
    op4.ip.ip_dst = sockaddr4->sin_addr;
    op4.ip.ip_p = protocol;
    op4.ip.ip_ttl = TTL;
    headersize = sizeof(op4.ip) + sizeof(op4.udp);
    packetsize = headersize + strlen(message);
    op4.ip.ip_len = htons(packetsize);
    memset(&op4.udp, '\0', sizeof(op4.udp));
    op4.udp.uh_dport = htons(port);
    op4.udp.uh_sport = htons(port);
    op4.udp.uh_ulen = htons(strlen(message) + sizeof(op4.udp));


    //Checksum
    udp_pseudo_header uph;
    memset(&uph, 0x00, sizeof(uph));
    uph.ip_src = op4.ip.ip_src;
    uph.ip_dst = op4.ip.ip_dst;
    uph.mbz = 0x00;
    uph.ip_p = op4.ip.ip_p;
    uph.length = strlen(MESSAGE);

    char* buff = new char[sizeof(uph) + sizeof(op4.udp) + strlen(message)];

    memset(buff, 0x00, sizeof(uph) + sizeof(op4.udp) + strlen(message));
    memcpy(buff, &uph, sizeof(uph));
    memcpy(&buff[sizeof(uph)], &op4.udp, sizeof(op4.udp));
    memcpy(&buff[sizeof(uph) + sizeof(op4.udp)], message, strlen(message));

    op4.udp.uh_sum = checksum(buff, sizeof(uph) + sizeof(op4.udp) + strlen(message));
    delete[] buff;



    memset(op4.payload, '\0', MSGSIZE);
    strcpy(op4.payload, message);
    packet = &op4;
    extraipheadersize = 0;

    fprintf(stdout, "Sending %i bytes (%i for the headers)...\n", (int)packetsize, (int)headersize);

    num = sendto(sd, (char*)packet, packetsize + extraipheadersize, 0, result->ai_addr, result->ai_addrlen);
    if (num <= 0) {
        printf("Cannot send message: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    return (0);
}
I believe the port needs to be defined as a string, not an int. Also you should be using INET6_ADDRSTRLEN rather than INET6_ADDRSTRLEN where you have.daniel mcgregor
INET6_ADDRSTRLEN is for IPv6 but I wanna send throught IPv4 so I use INET_ADDRSTRLEN.Łukasz Mleczko
As far as the port is concerned, it would make no sense if it was a sequence of characters(string), how the computer is supposed to understand it? there would have to be some kind of translation function.Łukasz Mleczko
if ur using ipv4 then thats fine, but on the msdn docs here, link, it specifies that the address and port are PCSTR's, which essentially are strings/chars, but that might not make a differencedaniel mcgregor