본문 바로가기
프로그래밍/C

IcmpSendEcho

by eteo 2023. 12. 23.

 

 

 

IcmpSendEcho 함수는 Windows 운영 체제에서 ICMP 에코 요청을 보내고 응답을 받는 데 사용되는 함수로 주로 네트워크 연결 상태를 확인하거나 호스트의 응답 시간을 측정하는 데 사용됩니다.

 

📝 ICMP (Internet Control Message Protocol) : 네트워크에서 발생하는 여러 상태 및 오류 메시지를 전송하는 데 사용되는 프로토콜

 

DWORD IcmpSendEcho(
  HANDLE                 IcmpHandle,
  IPAddr                 DestinationAddress,
  LPVOID                 RequestData,
  WORD                   RequestSize,
  PIP_OPTION_INFORMATION RequestOptions,
  LPVOID                 ReplyBuffer,
  DWORD                  ReplySize,
  DWORD                  Timeout
);

 

  • IcmpHandle: ICMP 핸들, IcmpCreateFile 함수를 사용하여 얻을 수 있다.
  • DestinationAddress: 응답을 받고자 하는 호스트의 IP 주소
  • RequestData: ICMP 에코 요청에 포함되는 데이터를
  • RequestSize: RequestData의 크기(바이트)
  • RequestOptions: ICMP 요청의 옵션 정보를 나타내는 포인터
  • ReplyBuffer: 응답 데이터를 저장할 버퍼
  • ReplySize: ReplyBuffer의 크기(바이트)
  • Timeout: 응답을 기다리는 최대 시간(밀리초)
  • 반환값 : 성공적으로 에코 요청이 전송된 경우 응답의 수. 실패한 경우에는 0이 반환

 

 

 

 

사용 예시.

 

ICMP 에코 응답이 내가 요청한 특정 호스트가 아니라 로컬 루프백 인터페이스를 통해서 응답이 오거나 게이트웨이가 응답할 수도 있으므로 응답을 받은 경우 ReplyBuffer를 PICMP_ECHO_REPLY로 캐스팅해서 내가 ICMP 요청을 보낸 호스트로부터 응답이 온게 맞는지 확인할 필요가 있다.

그 외 Status나 DataSize, RoundTripTime 등의 멤버변수를 확인해 네트워크 연결 상태를 확인한다. Status는 정상인 경우 IP_SUCCESS(0)으로 정의되어 있다.

 

#include <winsock2.h>
#include <iphlpapi.h>
#include <icmpapi.h>
#include <stdio.h>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

int main(int argc, char** argv) {

    // Declare and initialize variables

    HANDLE hIcmpFile;
    unsigned long ipaddr = INADDR_NONE;
    DWORD dwRetVal = 0;
    char SendData[32] = "Data Buffer";
    LPVOID ReplyBuffer = NULL;
    DWORD ReplySize = 0;
    
    const char* ip = "192.168.0.11";

    ipaddr = inet_addr(ip);

    hIcmpFile = IcmpCreateFile();
    if (hIcmpFile == INVALID_HANDLE_VALUE) {
        printf("Unable to open handle.\n");
        printf("IcmpCreatefile returned error: %ld\n", GetLastError());
        return 1;
    }

    // ReplySize >= sizeof(ICMP_ECHO_REPLY) + sizeof(SendData) + 8 이어야 한다.
    ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData) + 8;
    ReplyBuffer = (VOID*)malloc(ReplySize);
    if (ReplyBuffer == NULL) {
        printf("Unable to allocate memory\n");
        return 1;
    }


    dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData), NULL, ReplyBuffer, ReplySize, 1000);
    if (dwRetVal != 0) {
        PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
        struct in_addr ReplyAddr;
        ReplyAddr.S_un.S_addr = pEchoReply->Address;
        printf("Sent icmp message to %s\n", ip);
        printf("Received %ld icmp message responses\n", dwRetVal);
        printf("Received %d bytes from %s\n", pEchoReply->DataSize, inet_ntoa(ReplyAddr));
        printf("Status = %ld\n", pEchoReply->Status);
        printf("Roundtrip time = %ld ms\n", pEchoReply->RoundTripTime);
    }
    else {
        printf("Call to IcmpSendEcho failed.\n");
        printf("IcmpSendEcho returned error: %ld\n", GetLastError());
        return 1;
    }
    return 0;
}

 

 

 

 

 

IcmpSendEcho 함수의 확장된 버전인 IcmpSendEcho2IcmpSendEcho2Ex 함수도 있다. 추가적인 기능과 옵션을 제공하며 IcmpSendEcho 함수와의 주된 차이는 비동기 작업을 지원하는 데 있다.

 

 

 

출처 :

https://learn.microsoft.com/en-us/windows/win32/api/icmpapi/nf-icmpapi-icmpsendecho

 

IcmpSendEcho function (icmpapi.h) - Win32 apps

The IcmpSendEcho function sends an IPv4 ICMP echo request and returns any echo response replies. The call returns when the time-out has expired or the reply buffer is filled.

learn.microsoft.com