= 추가 요구사항 =
패킷분석기는 다음 사항을 최소한 구현하여야 함.

1. 선택적 capture
- 수신자 주소 등에 따라 원하는 패킷만 분석
2. IP 헤더의 graphical한 표시
- 리스트에서 하나의 패킷을 선택하면 IP 헤더를 분석해서 보여주는 기능
3. ethereal의 기능 중 1개 또는 새로운 기능을 한가지 구현
- 예, TCP connection 설정과정 분석

이상의 기능이 동작하는 것을 반드시 보여야 함.
- 이런, -_-; 할게 늘어버렸넹
네트워크 숙제를 하란 건지 GUI코딩을 하란 건지...
- ㅋㅋ 그러게 잘짜야지... ㅋㅋㅋ - eternalbleu

1. WSAIoctl

WSAIoctl 은 소켓이나 트랜스포트 계층 프로토콜, 통신 시스템의 구성과 관련된 사항을 설정하거나 설정값을 가져오기위해서 만들어졌다.
WSA prefix 를 가진 함수의 경우 대부분 Winsock 2에서 제공 되기 시작한 것이며, 이 WSAIoctl 역시도 윈속 2에서 지원된다.
네트워크의 3번째 프로젝트를 하기위해서는 SIO_RCVALL 라는 옵션을 설정하여 사용할 줄 알아야한다. 유사한 옵션으로는
SIO_RCVALL_IGMPMCAST, SIO_RCVALL_MCAST 가있다.
자세한 사항은 MSDN 혹은 Network Programming For Microsoft Windows 를 참조하기 바란다.

※ 윈도우 소켓 프로그래밍을 위해서는 윈속 라이브러리를 같이 linking 해야하며, WSActrl 을 사용하기 위해서는 winsock2 라이브러리인 ws2_32.lib 를 포함해야한다.
~cpp
#include <mstcpip.h>
※ 'SIO_RCVALL' : undeclared identifier 에러가 뜰 경우에 아래 코드를 추가 한다.
~cpp
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)

2. Sample Code

~cpp
int _cdecl main(int argc, char **argv)
{
    SOCKET        s;
    WSADATA       wsd;
    SOCKADDR_IN   if0;
    int           ret,
                  count;
    unsigned int  optval;
    DWORD         dwBytesRet,
                  dwFlags,
                  nproc;
    char          rcvbuf[MAX_IP_SIZE];
    WSABUF        wbuf;

    // Load Winsock
    //
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        printf("WSAStartup() failed: %d\n", GetLastError());
        return -1;
    }
    // Parse the command line
    //
    ValidateArgs(argc, argv);
    if (bFilter)
    {
        printf("Source Port: %d\n", usSourcePort);
        printf("Dest   Port: %d\n", usDestPort);
    }
    // Create a raw socket for receiving IP datagrams
    //
    s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (s == INVALID_SOCKET)
    {
        printf("WSASocket() failed: %d\n", WSAGetLastError());
        return -1;
    }
    // Get an interface to read IP packets on
    //
    if (GetInterface(s, &if0, dwInterface) != 0)
    {
        printf("Unable to obtain an interface\n");
        return -1;
    }
    printf("Binding to IF: %s\n", inet_ntoa(if0.sin_addr));
    //
    // This socket MUST be bound before calling the ioctl
    //
    if0.sin_family = AF_INET;
    if0.sin_port = htons(0);

    if (bind(s, (SOCKADDR *)&if0, sizeof(if0)) == SOCKET_ERROR)
    {
        printf("bind() failed: %d\n", WSAGetLastError());
        return -1;
    }
    //
    // Set the SIO_RCVALLxxx ioctl
    //
    optval = 1;
    if (WSAIoctl(s, SIO_RCVALL, &optval, sizeof(optval),
            NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR)
    {
        printf("WSAIotcl(%d) failed; %d\n", dwIoControlCode,
            WSAGetLastError());
        return -1;
    }
    // Start receiving IP datagrams until interrupted
    // 
    count = 0;
    while (1)
    {
        wbuf.len = MAX_IP_SIZE;
        wbuf.buf = rcvbuf;
        dwFlags  = 0;

        ret = WSARecv(s, &wbuf, 1, &dwBytesRet, &dwFlags, NULL, NULL);
        if (ret == SOCKET_ERROR)
        {
            printf("WSARecv() failed: %d\n", WSAGetLastError());
            return -1;
        }
        // Decode the IP header
        //
    }
    // Cleanup
    //
    closesocket(s);
    WSACleanup();
    return 0;
}
상기와 같이 기존의 서버 프로그램과 다른 점은 별로 없다. (Listen과 accept가 없네요. WSAIoctrl에서 다 처리하는건지...) 단지 소켓을 ioctrl 로 조정해서 ip 수준에서 올라오는 패킷을 기존과 다르게 처리할 뿐이다.
SIO_RCVALL 을 통해서 NIC를 통해 올라오는 모든 패킷의 캡쳐가 가능하다. NIC를 통해 나가는 패킷을 캡쳐하지 못하는 듯 하다.

아마도 listen, accept 가 패킷 필터링을 하는 것으로 보이는데 dst 상관없이 무조겁 application 까지 올라오니깐 필요없는 것이 아닐까? 그런 생각하고 있음. -_- - eternalbleu

3. 참고

  • MFC 각 데이터 타입 크기
Type Size
bool 1 byte
char, unsigned char, signed char 1 byte
short, unsigned short 2 bytes
int, unsigned int 4 bytes
__intn 1, 2, 4, or 8 bytes depending on the value of n. __intn is Microsoft-specific.
long, unsigned long 4 bytes
float 4 bytes
double 8 bytes
long double1 8 bytes
long long Equivalent to __int64.

4. 데이터 변환

const char* szIpAddr to DWORD ipvalue
inet_addr() :

Unsigned short interger 변환 (2바이트 체계)
htons() : host-to-network 바이트 변환
ntohs() : network-to-host 바이트 변환

Unsigned long interger 변환 (4바이트 체계)
htonl() : host-to-network 바이트 변환
ntohl() : network-to-host 바이트 변환

5. 추천 개발 과정

(1) 콘솔로 캡쳐기, 필터, 컨테이너 클래스를 구성한다.
필터기는 가능하면 propery 를 설정해서 동작하도록 구성한다.
(2) MFC, VB 등을 이용해서 GUI 부분을 짠다. (핵심은 리포트 모듈 작성)
컨테이너와 리스트 컨트롤을 옵저버 패턴으로 연결할 것을 염두에 둔다.
캡쳐기의 동작으로 인한 UI 딜레이 현상을 막기위해서 쓰레드를 이용.
(3) 만들어진 front-end, back-end 를 통합한다.
리포트 모듈을 리스트 컨트롤과 옵저버 패턴 혹은 이벤트 드리븐으로 연동

6. postscript

일단 캡쳐기만 완성하니 그야말로 일사천리로 풀리는데 -_-; 귀차니즘이 발동하는구만.. 쿨럭 - eternalbleu
Retrieved from http://wiki.zeropage.org/wiki.php/ComputerNetworkClass/Report2006/PacketAnalyzer
last modified 2021-02-07 05:23:00