2017-02-13 11 views
2

다음 코드는 ICMP 에코 요청을 보내고 응답을 받기 위해 고안된 프로그램입니다.RAW ICMP 소켓 : recvfrom()이 데이터를 수신하지 않습니다.

/* 
    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; 
} 

내 문제는 내 recvfrom() 전화가 데이터를 수신하지 않는다는 것입니다 및 핑 이 회신되었다는 사실에도 불구하고 (10060) TIMEOUTERROR를 반환 (와이어 샤크는 요청을 캡처하고 전송되는 응답). sendto()은 작동하지만 recvfrom()은 이상하게 작동하며 문제가 무엇인지 파악할 수 없습니다.

흥미로운 점은 recvfrom()은 게이트웨이가 호스트에 도달 할 수 없다고 알리는 경우에만 데이터를 수신합니다. 호스트가 도달 가능하고 핑에 응답 한 경우에는 그렇지 않습니다.

+1

패킷을 차단하는 Windows 방화벽이있을 수 있습니까? –

답변

1

:에

는 그래서 변경해야합니다. 내 코드의 유일한 오류는 내 ICMP 구조체 (cshu에서 언급 한)의 크기입니다.

모두에게 도움을 주셔서 감사합니다.

3

문제는 struct ICMP에 있습니다.

typecodeunsigned char이어야합니다.

ICMP의 헤더는 8 바이트 여야하지만, struct ICMP의 크기는 10 바이트 여야합니다. 그것은 내 방화벽이 응답을 차단했다 전체 시간을 밝혀

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

수정, [RFC 792] (https://tools.ietf.org/html/rfc792)를 참조하십시오. – EJP