ICMP Echo request funktioniert nicht?!
-
hallo ihr!
ich habe mich längere zeit mit winsock beschäftigt und möchte jetzt den schritt zu raw sockets wagen.
nach einigen stunden lektüre (auch auf zotteljedis seite) habe ich ein tutorial programm von einer anderen seite versucht mit visual c++ 6 (standard) nachzubauen.
nun kam mir ein teil des codes (der ein icmp echo request sendet) etwas seltsam vor. zum verständnis hier mal der komplette code inclusive header.
die besagte stelle im quelltext ist durch kommentare gekennzeichnet gekennzeichnet.
kurze zusammenfassung des problems:
sendto wird hier mit einem *(SOCKADDR ) dip verwendet das kein zeiger auf ein sockaddr struct ist sondern ein zeiger auf eine inet_addr variable, deswegen meckerte WSAGetLastError auch immer mit "wrong parameter size".
ich veränderte den parameter zu einem zeiger auf ein sockaddr objekt nämlich *(const sockaddr ) &sin war das so korrekt?icmp.h:
/********************* icmp.h header file ************************/ // ICMP message types #define ICMP_ECHOREQ 13 // Echo request query // IP Header typedef struct ip_hdr { unsigned char ip_verlen; // version & IHL => 1 Bytes (combined size of both) unsigned char ip_tos; // TOS => 1 Bytes unsigned short ip_totallength; // Total length => 2 Bytes unsigned short ip_id; // Identification => 2 Bytes unsigned short ip_offset; // Fragment Offset => 2 Bytes unsigned char ip_ttl; // Time to live => 1 Bytes unsigned char ip_protocol; // Protocol => 1 Bytes unsigned short ip_checksum; // Header checksum => 2 Bytes unsigned int ip_srcaddr; // Source address => 4 Bytes unsigned int ip_destaddr; // Destination address => + 4 Bytes // = 20 Bytes }IP_HDR; // ICMP Header typedef struct tagICMPHDR { unsigned char icmp_type; // Type of message => 1 Bytes unsigned char icmp_code; // Type sub code => 1 Bytes unsigned short icmp_cksum; // Checksum => 2 Bytes unsigned short icmp_id; // Identifer => 2 Bytes unsigned short icmp_seq; // sequence number => + 2 Bytes // = 8 Bytes } ICMPHDR, *PICMPHDR; #define REQ_DATASIZE 32 // Echo Request Data size // ICMP Echo Request typedef struct tagECHOREQUEST { ICMPHDR icmpHdr; char cData[REQ_DATASIZE]; } ECHOREQUEST, *PECHOREQUEST; USHORT checksum(USHORT *buffer, int size) { ... checksum funktion halt ;) return (USHORT)(~cksum); }
icmp.c
/********************* icmp.c source file ************************/ // Make sure you always include your headers and link your libraries :) #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <stdlib.h> #include "icmp.h" void main(int argc, char **argv) { DWORD dip = inet_addr(argv[1]); WSADATA wsaData; SOCKET sock; static ECHOREQUEST echo_req; struct sockaddr_in sin; // Startup WinSock if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("WSAStartup failure!"); } // Create a raw socket if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == SOCKET_ERROR) { printf("Error starting socket"); } sin.sin_family = AF_INET; sin.sin_port = htons(0); sin.sin_addr.s_addr = dip; // Fill in echo request echo_req.icmpHdr.icmp_type = ICMP_ECHOREQ; echo_req.icmpHdr.icmp_code = 0; echo_req.icmpHdr.icmp_cksum = 0; echo_req.icmpHdr.icmp_id = 1; echo_req.icmpHdr.icmp_seq = 1; // Fill in some data to send memset(echo_req.cData, ' ', REQ_DATASIZE); // Compute checksum echo_req.icmpHdr.icmp_cksum = checksum((unsigned short *)&echo_req, sizeof(ECHOREQUEST)); // Status mesage printf("Sending Echo Request to <%s>.\n", argv[1]); // Send the echo request // ********************************************************************** // ********************************************************************** // *** P R O B L E M S T E L L E *** // original quelltext hat als parameter (SOCKADDR *) dip, jedoch wird ein zeiger auf ein sockaddr objekt erwartet! if (sendto(sock, (const char *) &echo_req, sizeof(ECHOREQUEST), 0, (SOCKADDR *) dip, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) // *** meine veränderte version ** // nach meinem denken wäre hier anstatt des (SOCKADDR *) dip ein (const sockaddr *) &sin zu verwenden, da dies ja ein zeiger auf ein sockaddr struct ist. das ganze compiliert und linkt dann auch ohne fehler, jedoch bin ich mir nicht sicher ob das alles auch richtig ist. hat jemand da eine idee? // hier meine veränderte version obiger codezeile: // if (sendto(sock, (const char *) &echo_req, sizeof(ECHOREQUEST), 0, (const // ********************************************************************** // ********************************************************************** sockaddr *) &sin, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) { printf("sendto() failed: %d\n", WSAGetLastError()); return -1; } // Status mesage printf("Message Sent\n"); // Close socket and WinSock closesocket(sock); WSACleanup(); return 0; } /********************* icmp.c source file ************************/
vielen dank schon jetzt für euere hilfe!
tschaui
root2
-
funktioniert es jetzt, oder funktioniert es nicht?
der cast kommt mir allerdings bekannt vor. auf zotteljedis seite ist übrigens ein Ping-programm zu finden. und ob du jetzt posix oder winsock machst, der unterschied ist verschwindend
-
nun...
der compiler meckert nicht mehr rum das irgendwas falsch gecastet wird.
und WSAGetLastError sagt auch nicht mehr das es den fehler 100014 (WSAEFAULT_bad address) hätte.also sollte es funktionieren so wie ich denke, tut es aber nicht.
ich habe mit Ethereal mal im LAN geschnüffelt und es gibt keine datagramme die auch nur im entferntesten zu dem passen würden was ich senden bzw. empfangen wollte.ich denke ja das mit der header-implementation etwas nicht richtig ist jedoch weiss ich nicht wo ich da ansetzen soll
ich war mir auch nicht sicher welcher cast jetzt der richtige ist, der den ich verbessert haben oder der ursprüngliche.
oder liegt der fehler schon weiter oben? muss ich da vielleicht mit einem setsockopt(Sock, IPPROTO_IP, IP_HDRINCL, ..., ...); erst die benutzung meiner eigenen header erzwingen?
danke für jede hilfe
root2
-
Ja du musst den setsockopt call machen um dem Kernel mitzuteilen dass du den Header reinpacken willst. Sonst packt er seinen eigenen davor.
Erm wo ist eigentlich dein IP header oder hab ich jetz was überlesen ?