Raw Sockets Fehlermeldung



  • hi,

    ich habe ein Programm in Visual C++ 2008 geschrieben das UDP über RawSockets versendet.

    Das Programm soll UDP Pakete direkt senden ohne vorher einen ARP Request zu machen wie es sonst bei der "normalen" Socketprogrammierung üblich ist.

    Um die einzelnen Pakete zu sniffen verwende ich Wireshark.

    Ich bekomme immer die WSAGetLastFehlermeldung: 10038

    Ich vermute das der Socket nicht richtig initialisiert wurde. Es kann aber auch sein das es auf meinem Windows XP SP3 einfach nicht läuft (Hab gehört das es da Einschränkungen gibt).

    Ich weiß nicht genau was ich bei der setsockopt angeben soll. IP_HDRINCL findet er nicht!

    Über jede hilfreiche Antwort freue ich mich 🙂

    Gruß profcoder

    Hier der Code:

    #include "stdafx.h"
    #include <windows.h>
    //#include <winsock2.h>
    #include <stdlib.h>
    #include <iostream>
    //Wird benötigt!
    #pragma comment( lib, "ws2_32.lib" )
    
    /*
    Der IP Header:
    --------------
    
    |  Byte 0       |   Byte 1      |  Byte 2       |  Byte 3       |
    
    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |Version|  IHL  |Type of Service|          Total Length         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |         Identification        |Flags|      Fragment Offset    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |  Time to Live |    Protocol   |         Header Checksum       |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                       Source Address                          |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                    Destination Address                        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    */
    
    struct IP_HEADER
    {
      unsigned int   h_len:4;          // Länge des Headers
      unsigned int   version:4;        // IP Version
      unsigned char  tos;              // Type of service
      unsigned short total_len;        // Gesamt länge des Pakets
      unsigned short ident;            // unique identifier
      unsigned short frag_and_flags;   // flags
      unsigned char  ttl;              // TTL
      unsigned char  proto;            // Protokoll (TCP, UDP etc)
      unsigned short checksum;         // IP Checksumme
      unsigned int   sourceIP;         // Source IP
      unsigned int   destIP;           // Ziel IP
    };
    
    // The UDP header structure
    //
    typedef struct _udphdr
    {
    unsigned short sport; // Source Port
    unsigned short dport; // Destination Port
    unsigned short Length; // Length
    unsigned short Checksum; // Checksum
    
    }UdpHeader, * LPUdpHeader;
    
    struct UDP_HEADER
    {
    unsigned short sport; // Source Port
    unsigned short dport; // Destination Port
    unsigned short Length; // Length
    unsigned short Checksum; // Checksum
    };
    
    typedef struct _PSHeader
    {
    unsigned long srcaddr;
    unsigned long destaddr;
    
    unsigned char zero;
    unsigned char protocol;
    unsigned short len;
    
    }PSHeader; 
    
    long WinsockStartup();
    
    int main(int argc, char** argv)
    {
    
    IP_HEADER *iphdr;
    UDP_HEADER *udphdr, udpHdr;
    PSHeader pseudo_header;
    SOCKET sock = socket(AF_INET,SOCK_RAW,IPPROTO_UDP);
    SOCKADDR_IN sock_addr;
    int iUdpSize, error;
    long rc;
    unsigned char sendBuf[2048];
    memset(sendBuf,0,2048);
    char RecvTimeout=1000;
    unsigned char data[32];
    memset(data,0,20);
    
    //
    unsigned char rspace[32];
      WSADATA wsa_data;
    //Winsock initialisieren
      rc = WinsockStartup();
    
      if (rc == SOCKET_ERROR)
      {
    	  std::cout << "Error: WinsockStartup failed: " << WSAGetLastError();
        return SOCKET_ERROR;
      }
     //------- Hier weiß ich nicht wie ich die setsockopt einstellen soll! IP_HDRINCL findet er nicht! -------------
    
      //  rc = setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&RecvTimeout, sizeof(RecvTimeout));
       //char on = 1;
      //setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on)); 
    
    //---------------------------------------------------------------------------------------------------------------
    
      //iphdr auf den Puffer zeigen lassen
    iphdr = (IP_HEADER *) sendBuf; // the ip header now points to the top of the sendBuf
    udphdr= (UDP_HEADER *) (sendBuf + sizeof(IP_HEADER)); // the udp header points to the part next to the ip header
    
    sock_addr.sin_family = AF_INET;
    sock_addr.sin_port = htons (1526);
    sock_addr.sin_addr.s_addr = inet_addr("192.168.0.22");
    
    //IP Header initialisieren
    iphdr->version = 4;
    iphdr->h_len = 5;
    iphdr->tos = 0;
    iphdr->total_len = sizeof (IP_HEADER) + sizeof (UDP_HEADER) + sizeof (data);
    iphdr->ident = 1;
    iphdr->frag_and_flags = 0;
    iphdr->ttl = 255;
    iphdr->proto = IPPROTO_UDP; //UDP
    iphdr->checksum = 0;
    
    iphdr->sourceIP = inet_addr ("192.168.0.1"); // your source ip
    iphdr->destIP = sock_addr.sin_addr.s_addr;
    
    // Initalize the UDP header
    //
    iUdpSize = sizeof(udpHdr) + strlen((char*)data);
    
    udphdr->sport = htons(13371) ;
    udphdr->dport = htons(13371) ;
    udphdr->Length = htons(iUdpSize) ;
    udphdr->Checksum = 0 ;
    
    //calculate UDP CheckSum
    pseudo_header.destaddr = inet_addr("192.168.0.22");
    pseudo_header.srcaddr = inet_addr("192.168.0.1");
    pseudo_header.zero = 0;
    pseudo_header.protocol = 17;
    pseudo_header.len = sizeof(data) + sizeof(udphdr);
    
    //Gebe den Inhalt des Sendepuffers aus
    for(int i=0;i<40;i++)
    printf("%x",sendBuf[i]);
    //Sende den Inhalt des Puffers (Das Paket)
    error = sendto(sock,(char*)sendBuf,40,0,(LPSOCKADDR)&sock_addr,sizeof(SOCKADDR_IN));
    //Bei Fehler gebe Fehlermeldung aus
    if(error == SOCKET_ERROR)
    {
    std::cout << "\nError: ";
    std::cout << WSAGetLastError();
    }
    else
    std::cout << "sent";
    //Warte 3Sekunden, dann fahre fort
    Sleep(3000);
    //Programmende
    return 0;
      }
    
    long WinsockStartup()
    {
      long rc;
    
      WORD wVersionRequested;
      WSADATA wsaData;
      wVersionRequested = MAKEWORD(2, 1);
    
      rc = WSAStartup( wVersionRequested, &wsaData );
      return rc;
    }
    


  • Ich würde erstmal WinsockStartup() VOR socket() aufrufen...



  • Danke xD

    Das war der Fehler. Oh man xD

    Hm jetzt läuft das Programm. Aber wenn ich mit Wireshark sniffe, dann schickt er immernoch zuerst ein ARP Whois Requests raus. Er soll aber sofort ein UDP Paket senden.

    Weißt du wie ich das hinbekomm?



  • Ist klar wenn du sendto() benutzt!



  • und ausserdem muss er ja ein arp req. machen wen er den gw nicht kennt.. und dieses req. wird vom kernel initiert.



  • Ja das will ich ja vermeiden das er ein Request macht. Er soll einfach das was ich ihm gebe direkt rausschicken ohne irgendwelche Standardabläufe durchzugehen. Also direkt auf unterster Ebene.

    Kennst du einen anderen Befehl als sendto? Ich hab nichts gefunden...

    Hm wenn das der Kernel macht. Ist das dann überhaupt möglich? Auf Umwegen evtl.?



  • lowbyte_ schrieb:

    und ausserdem muss er ja ein arp req. machen wen er den gw nicht kennt..

    "gw"? Und warum muss er, ist doch nichts zu resolven. Versteh ich nich.



  • Wären die bisherigen Poster so nett noch ne Antwort auf die an sie zuletzt gerichteten Fragen zu stellen? Würde mich auch interessieren.

    Danke


Anmelden zum Antworten