U E D R , A S I H C RSS

Computer Network Class/Report2006/Packet Analyzer


= 추가 요구사항 =
  • 홈페이지 나온 내용.
패킷분석기는 다음 사항을 최소 구현하여야 함.

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
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:00
Processing time 0.0245 sec