:: 행복하기 ::

며칠전 패킷분석을 많이 했었다는 글을 올리면서..
winpcap 예제들을 주석을 달아서 올려야겠다는 생각을 했습니다.

그 첫번째로 가장 기초가 되는 basic_dump.c 파일을 간단하게 분석했습니다.
완전 초보자가 본다고 생각하고.......

대학교 2학년때 처음 봤을 때는 뭐가 뭔지 하나도 몰랐었는데..
역시 그때 문제는 winpcap이 어렵기 보다....
제가 C를 못해서 그랬던거 같군요;;;...하하...
지금 보니...잘 설계된 라이브러리군요..ㅜㅜ;하하..
하긴...5년전이야기 입니다..-0-;;

시작합니다~~~~


#include "pcap.h"

/* prototype of the packet handler */
// pcap 라이브러리에서 패킷이 도착하면 호출해줄 함수의 프로토타입입니다.
// 즉, 패킷이 도착하면 packet_handler라는 함수가 콜백으로 호출됩니다~~
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

// 메인메인~!!
main()
{
        pcap_if_t *alldevs;            
        pcap_if_t *d;                    
        int inum;
        int i=0;
        pcap_t *adhandle;
        char errbuf[PCAP_ERRBUF_SIZE];
       
        /* Retrieve the device list */
        // pcap_findalldevs 함수는 시스템이 가지고 있는 모든 네트웍 인터페이스에
        // 대한 정보를 Linked List형태로 생성하여 List의 첫번째 노드의
        // 주소를 첫번째 인자에 넣어 반환해 줍니다.
        if(pcap_findalldevs(&alldevs, errbuf) == -1)
        {
                fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
                exit(1);
        }
       
        /* Print the list */
        // Linked List 이므로 순차적으로 하나씩 검색하면 됩니다.
        // 첫번째의 값은 alldevs에 저장되어 있을 것이고
        // 다음 인터페이스 정보를 담고있는 노드는 alldevs의 next란 놈이 가지고 있겠죠?
        // 마지막 노드의 next는 NULL값을 가집니다
        // 모든 인터페이스를 순회하며 정보를 출력합니다.
        //
        // 참고!
#if 0
        typedef struct pcap_if pcap_if_t;
        struct pcap_if {
                struct pcap_if *next;
                char *name;    
                char *description;  
                struct pcap_addr *addresses;
                u_int flags;        
        };
        typedef struct pcap_addr pcap_addr_t;
        struct pcap_addr {
                struct pcap_addr *next;         // 하나의 인터페이스가
                                                // 여러개의 주소를 가질수 있기 때문에
                                                // 이 부분 역시 리스트입니다.
                struct sockaddr *addr;          
                struct sockaddr *netmask;  
                struct sockaddr *broadaddr;
                struct sockaddr *dstaddr;  
        };
#endif
        for(d=alldevs; d; d=d->next)
        {
                printf("%d. %s", ++i, d->name);
                if (d->description)
                        printf(" (%s)\n", d->description);
                else
                        printf(" (No description available)\n");
        }
       
        // 인터페이스가 하나도 없다면~~ 프로그램 종료..
        if(i==0)
        {
                printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
                return -1;
        }
       
        // 사용할 인터페이스가 무엇인지 입력 받습니다.
        printf("Enter the interface number (1-%d):",i);
        scanf("%d", &inum);
       
        if(inum < 1 || inum > i)
        {
                printf("\nInterface number out of range.\n");
                /* Free the device list */
                pcap_freealldevs(alldevs);
                return -1;
        }
       
        /* Jump to the selected adapter */
        // Single Linked List이므로 처음부터 순회하며
        // 선택된 인터페이스를 찾아냅니다.
        for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
       
        /* Open the device */
        /* Open the adapter */
        // pcap_open_live를 사용하여 해당 인터페이스를 Open합니다.
        // 아래에서 Promiscuous mode란 자기 MAC주소가 아닌 패킷들까지 다 받아들이는 모드를 말합니다.
        if ((adhandle= pcap_open_live(d->name, // name of the device
                                 65536,             // portion of the packet to capture.
                                                // 65536 grants that the whole packet will be captured on all the MACs.
                                 1,         // promiscuous mode (nonzero means promiscuous)
                                 1000,              // read timeout
                                 errbuf         // error buffer
                                 )) == NULL)
        {
                fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
                /* Free the device list */
                pcap_freealldevs(alldevs);
                return -1;
        }
       
        printf("\nlistening on %s...\n", d->description);
       
        /* At this point, we don't need any more the device list. Free it */
        // 선택된 인터페이스를 pcap_open_live를 통해 열고 그것을 제어하기 위한 Handle을 받았으므로
        // 더 이상 인터페이스에 대한 정보가 필요없습니다.
        // 즉, pcap_findalldevs를 통해 생성되었던 Linked List가 삭제되어야겠죠?..
        // pcap_freealldevs를 통해 Linked List를 지웁니다~
        pcap_freealldevs(alldevs);
       
        /* start the capture */
        // pcap_loop 함수를 호출하게 되면
        // winpcap라이브러리가 무한루프(혹은 정해진 숫자만큼)를 돌면서 패킷이 감지되면
        // 세번째 인자에 해당하는 함수를 호출해줍니다.
        // 즉, 패킷이 도착하면 packet_handler라는 함수가 호출됩니다.
        // pcap_loop의
        // 첫번째 인자 : pcap_open_live를 통해 할당받은 Handler!
        // 두번째 인자 : 얼마만큼의 패킷을 받고 종료될 것인가?.. 0이면 무한루프.
        // 세번째 인자 : 패킷이 도착시 callback해줄 함수(즉..실행될 함수)
        // 네번째 인자 : ???? 모르겠네요.ㅡㅜ
        pcap_loop(adhandle, 0, packet_handler, NULL);
       
        pcap_close(adhandle);
        return 0;
}


/* Callback function invoked by libpcap for every incoming packet */
// 패킷이 유입되었을 때 winpcap에 의해서 호출되는 함수입니다.
//
// u_char *param : 사용자가 정의한 파라미터 값이 넘어옵니다. 아마도 pcap_loop의 마지막 인자값이 아닐까 생각되네요~//
// const struct pcap_pkthdr *header : 캡쳐된 패킷의 정보를 가지고 있는 구조체입니다.
// struct pcap_pkthdr {
//      struct timeval ts;              // 패킷이 캡쳐된 시간입니다.
//      bpf_u_int32 caplen;             // 캡쳐된 패킷의 길이
//      bpf_u_int32 len;                // 실제 패킷의 길이..
//      // caplen과 len이 두가지의 길이 정보가 있는 것은 실제 패킷의 길이에 상관없이
//      // winpcap에서 패킷을 특정 길이만큼만 끊어 캡쳐할 수 있기 때문입니다
//      // pcap_open_live()함수에서 최대 저장 길이를 지정할 수 있습니다.
//};
// const u_char *pkt_data               // 캡쳐된 패킷의 시작 주소.
//                                      // 일반적인 환경에서 가장 앞 부분에는 ethernet header가 붙어있겠죠?
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
        // 아래 내용은 단순히 시간을 출력하고 패킷의 길이를 출력해주는 부분입니다.
        // winpcap과 큰 관련이 없기에 생략~~
        struct tm *ltime;
        char timestr[16];
        time_t local_tv_sec;
       
        /* convert the timestamp to readable format */
        local_tv_sec = header->ts.tv_sec;
        ltime=localtime(&local_tv_sec);
        strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
       
        printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
       
}

행여나 혹시나 궁금한게 있으시면// 질문 남겨주세요..
찾아서라도............쿨럭.;ㅋㅋ
Posted by heestory.kr Trackback 1 Comment 23

Trackback : http://heestory.kr/trackback/220 관련글 쓰기

  1.  삭제

    Winpcap을 사용하여 패킷을 생성하기!!..

    2009/03/22 02:12 Tracked from :: -ㅅ- 아직은 20대. 그녀석의 잡담 ::

    예전에 썼던 글( 2007/06/24 - [컴퓨터 이야기] - [WinpCap] winpcap 예제..basic_dump.c 분석~!// : http://heestory.kr/220 ) 에 이어서... winpcap을 이용하여 패킷을 생성하는 샘플을 작성해보고자 한다. (이어서 쓴다라고는 하지만...이미 1년 반전에 쓴글이네요-;;..ㅋㅋㅋ) winpcap developer's packs 인 WpdPack를 다운 받으면 그 안에 샘플들이 많이 있어서..

댓글을 달아 주세요

  1.  댓글주소 수정/삭제 댓글쓰기 휭~ 2007/06/25 13:15

    성실하게 잘 달아 놓으셨네요, 잘 보고 갑니다~

    •  댓글주소 수정/삭제 BlogIcon thedino 2007/06/25 13:18

      프로그래밍 초보가..
      처음 winpcap을 공부한다는 마음으로 달았습니다-ㅋ
      5년전을 기억하며...ㅋㅋ
      방문 감사합니당~~ㅋ 자주 놀러오세욧.ㅎ

  2.  댓글주소 수정/삭제 댓글쓰기 Jwagun 2007/11/08 01:12

    멋지세요~
    pcap 참 쓰기 간략하게 잘 만들어진거 같아요 ㅎ
    이거 아님 NDIS 삽질을 얼마나 하려나 ㅡ,..ㅡ
    잘보고 갑니다~

    •  댓글주소 수정/삭제 BlogIcon heestory.kr 2007/11/08 12:27

      감사합니다^-^...
      pcap 참 쓰기 편하죠...ㅎ
      윈도우에서 NDIS 한번 해볼꺼라고 원서보다가 잠들었던 기억이.....쿨럭;;ㅎ

      방문 감사드리고~ 다음에 또 놀러오세요.ㅋㅋ

  3.  댓글주소 수정/삭제 댓글쓰기 미남 2008/01/17 22:43

    참 고맙네요 pcap가 어느정도 보이네요 그전에는 전혀보일것같지 않더니

    다른것은 더 분석하지 못햇나요. 인차 분석해서 또 올렷으면 고맙겠네요. 화이팅 ^^

    •  댓글주소 수정/삭제 BlogIcon heestory.kr 2008/01/18 00:47

      방문 감사합니다^-^ㅋ
      도움이 되셨다니..기쁘네요.하핫..ㅋㅋ
      어떤걸 더 분석할까 고민하다가..
      마땅한게 없어서..;;
      혹시 궁금한거 있으면 요청하시면 제가 아는 선에서 분석해드리겠습니다^-^..

  4.  댓글주소 수정/삭제 댓글쓰기 키라키라 2008/10/15 21:04

    오~성실하게 주석 달아놓으셨네요^-^
    담아갈께요!!!

  5.  댓글주소 수정/삭제 댓글쓰기 김미나 2009/03/25 15:20

    안녕하세요.
    좋은자료 감사히 읽고 공부하는데 쓰겠습니다.
    혹시 제가 하다가 모르는 부분에 대해서 질문 메일 보내고 싶은데
    혹시 메일주소 알수 있을까요?

  6.  댓글주소 수정/삭제 댓글쓰기 유창훈 2009/03/31 21:50

    정말감사합니다. 이번에 라우터에 패킷을 분석해서 DB를 구축하려하는데
    정말 찾던 자료입니다 .
    좋은자료 참고해서 좋은자료 만들어 보겠습니다.

  7.  댓글주소 수정/삭제 댓글쓰기 유창훈 2009/04/03 17:01

    네 알겠습니다 ^^

  8.  댓글주소 수정/삭제 댓글쓰기 현동형 2009/05/22 21:14

    와 찾던자료인데!! 퍼가도되나요?

  9.  댓글주소 수정/삭제 댓글쓰기 BlogIcon yundream 2009/06/16 13:36

    윈도우 환경에서의 패킷캡춰 누수율이 어느정도 될까요 ? 리눅스는 커널컴파일 없이는 누수율이 상당해서 패킷량 많은 곳에서 사용하기는 좀 애매모호 하더라구요.

    •  댓글주소 수정/삭제 BlogIcon heestory.kr 2009/06/16 23:46

      글쎄요...??하하;;
      리눅스에서는..drop되는 패킷수가 나와서..
      인식을 했었는데...윈도우에서는 별 생각없이 썼더니;;;
      전혀 모르겠네요-ㅎㅎ
      예전에 대학원에서...같은 연구실에 선배가..queue를 여러개 사용해서 누수율을 최소화 시키는 걸 개발했었는데...ㅋㅋ
      관련 자료들이 없어요..하핫;;ㅋㅋ

  10.  댓글주소 수정/삭제 댓글쓰기 영이 2009/07/01 10:29

    멋지시네요 ㅎㅎ

    이제 네트워킹 프로그래밍을 공부 시작한 초본데요;;;

    시작부터 막혀서 쫌 여쭤볼려고요 ㅎㅎㅎ

    bgy.obj : error LNK2019: _pcap_close 외부 기호(참조 위치: _main 함수)에서 확인하지 못했습니다.
    bgy.obj : error LNK2019: _pcap_loop 외부 기호(참조 위치: _main 함수)에서 확인하지 못했습니다.
    bgy.obj : error LNK2019: _pcap_open_live 외부 기호(참조 위치: _main 함수)에서 확인하지 못했습니다.
    bgy.obj : error LNK2019: _pcap_freealldevs 외부 기호(참조 위치: _main 함수)에서 확인하지 못했습니다.
    bgy.obj : error LNK2019: _pcap_findalldevs 외부 기호(참조 위치: _main 함수)에서 확인하지 못했습니다.

    대체 이것들은;;;;;; pcap을 잘못 연결한건가요?? ㅡㅡ;;;;;

  11.  댓글주소 수정/삭제 댓글쓰기 영이 2009/07/01 11:12

    아;; 라이브러리가 문제였던거 같네요 ㅎㅎㅎ 위에 소스 실행해보니까... 길이만 나오네요?? ㅎㅎㅎ 좋은자료 감사 합니다~ 열공할께요 ㅎ

  12.  댓글주소 수정/삭제 댓글쓰기 BlogIcon 2차원소년 2009/11/14 02:13

    잘보고 퍼갑니다 __)

  13.  댓글주소 수정/삭제 댓글쓰기 hattush 2010/06/28 15:25

    좋은 내용 잘 보고 갑니다.
    네이버 블로그로 퍼갑니다~^^
    출처는 당연히 표시할게요~감사.