2017-02-13 3 views
2

Der folgende Code ist ein Programm zum Senden von ICMP-Echoanforderungen und zum Empfangen von Antworten.RAW ICMP-Socket: recvfrom() empfängt keine Daten

/* 
    Forgive my lack of error handling :) 
*/ 
SOCKET ASOCKET = INVALID_SOCKET; 
struct sockaddr saddr; 
struct sockaddr_in *to = (struct sockaddr_in *) &saddr; 
struct sockaddr_in from; 
int fromsize = sizeof(from); 
std::string ip = "[arbitrary ip address]"; 

struct ICMP { 
    USHORT type; 
    USHORT code; 
    USHORT cksum; 
    USHORT id; 
    USHORT seq; 
}*_ICMP; 

char sendBuffer[sizeof(struct ICMP)]; 
char recvBuffer[256]; 

WSADATA wsaData; 
WSAStartup(MAKEWORD(2, 2), &wsaData); 

memset(&saddr, NULL, sizeof(saddr)); 
ASOCKET = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 

// Configure timeout 
DWORD timeoutmilsec = 3000; 
setsockopt(ASOCKET, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeoutmilsec, sizeof(timeoutmilsec)); 

to->sin_family = AF_INET; 
inet_pton(AF_INET, ip.c_str(), &(to->sin_addr)); 

_ICMP = new ICMP(); 

_ICMP->type = 8; 
_ICMP->code = 0; 
_ICMP->cksum = 0; 
_ICMP->id = rand(); 
_ICMP->seq++; 
// I have omitted my declaration of checksum() for simplicity 
_ICMP->cksum = checksum((u_short *)_ICMP, sizeof(struct ICMP)); 

memcpy(sendBuffer, _ICMP, sizeof(struct ICMP)); 

if (sendto(ASOCKET, sendBuffer, sizeof(sendBuffer), NULL, (sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR) 
{ 
    printf("sendto() failed with error: %u\n", WSAGetLastError()); 
    return false; 
} 

if (recvfrom(ASOCKET, recvBuffer, sizeof(recvBuffer), NULL, (sockaddr *)&from, &fromsize) == SOCKET_ERROR) 
{ 
    if (WSAGetLastError() == TIMEOUTERROR) 
    { 
     printf("Timed out\n\n"); 
     return false; 
    } 

    printf("recvfrom() failed with error: %u\n", WSAGetLastError()); 
    return false; 
} 

Mein Problem ist, dass mein recvfrom() Anruf keine Daten empfängt und gibt Timeouterror (10060) trotz der Tatsache, dass der Ping hat beantwortet worden (Wireshark fängt die Anfrage und Antwort gesendet werden). sendto() funktioniert aber recvfrom() verhält sich seltsam und ich kann nicht herausfinden, was das Problem ist.

Was ich interessant finde, ist recvfrom() wird Daten nur empfangen, wenn das Gateway mir sagt, dass ein Host nicht erreichbar ist; Es wird nicht angezeigt, wenn der Host erreichbar ist und auf den Ping geantwortet hat.

+1

Könnte die Windows-Firewall das Paket blockieren? –

Antwort

1

Es stellt sich heraus die ganze Zeit meine Firewall die Antworten blockiert war:

So sollte es geändert werden. Der einzige Fehler in meinem Code war die Größe meiner ICMP-Struktur (von cshu erwähnt).

Danke für die Hilfe allen.

3

Das Problem liegt in struct ICMP.

type und code von ICMP sollte unsigned char sein.

Header von ICMP sollte 8-Byte sein, aber die Größe struct ICMP ist 10 Bytes.

struct ICMP { 
    unsigned char type; 
    unsigned char code; 
    USHORT cksum; 
    USHORT id; 
    USHORT seq; 
}*_ICMP; 
+1

Korrekt, siehe [RFC 792] (https://tools.ietf.org/html/rfc792). – EJP