SlideShare ist ein Scribd-Unternehmen logo
1 von 18
패킷 캡쳐 라이브러리
주요함수 코드분석


         정보통신공학과
           200801559
              윤천호
목           차
1. 패킷 캡쳐 과정

2. pcap_lookupdev()
  2-1. pcap_findalldevs()
  2-2. pcap_freealldevs()


3. pcap_open_live()
  3-1. pcap_create()
  3-2. pcap_set_ 3가지 ()
  3-3. pcap_check_activated()
  3-4. pcap_activate()


4. pcap_next()
1. 패킷 캡쳐 과정
1. 패킷캡쳐 과정


디바이스 이름 얻기          디바이스 열기
pcap_lookupdev()   pcap_open_live()




 디바이스 닫기              패킷캡처
 pcap_close()        pcap_next()
2. pcap_lookupdev()
  디바이스 이름얻기
  2-1    pcap_findalldevs()


  2-2    pcap_freealldevs()
2. pcap_lookupdev()
char *pcap_lookupdev(errbuf)
          register char *errbuf;
                                                 pcap_if_t 타입의 주소값을 저장하는 alldevs 선언
{
          pcap_if_t *alldevs;
                                                          만약 IF_NAMESIZE가 정의 되어있지 않으면
          #ifndef IF_NAMESIZE                               IF_NAMESIZE 는 IFNAMSIZ로 정의
          #define IF_NAMESIZE IFNAMSIZ                     케릭터 배열 device[]의 크기는 IF_NAMESIZE
          #endif                                                          +1
                                                                 그리고 스트링 ret 선언
          static char device[IF_NAMESIZE + 1];
          char *ret;                                            함수 pcap_findalldevs() 의 반환값으로
                                                                exception에러 검출 후 그에 따른 조치
           if (pcap_findalldevs(&alldevs, errbuf) == -1)      그리고 디바이스가 검색되지 않았을 경우에도
                        return (NULL);                          최종 반환하는 ret에 NULL값을 대입.
           if (alldevs == NULL || (alldevs->flags &
PCAP_IF_LOOPBACK)) {                                                          포인터 인자를 사용했기에 name에 접근이 가능
                        (void)strlcpy(errbuf, "no suitable device found", 위의 반환값에서 오류가 검출되지 않았으면
                         PCAP_ERRBUF_SIZE);                               name값을 device에 복사 그리고 ret에 복사
                        ret = NULL;
           }
           else {
                        (void)strlcpy(device, alldevs-
>name, sizeof(device));
                        ret = device;
                                                                함수 pcap_freealldevs() 로 포인터 변수 alldevs를 초
           }
                                                                                     기화
           pcap_freealldevs(alldevs);
                                                                                 및 결과 반환
2-1. pcap_findalldevs()
int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf){
               pcap_if_t *devlist = NULL;
               int ret = 0;
               const char *desc;                                       만약 PacketGetAdapterNames() 함수로 디바이스의 길이를 먼저 파악.
               char *AdaptersName;                                                반환값 이 부정이면 -1을 반환하여 에러처리
               ULONG NameLength;
               char *name;
               if (!PacketGetAdapterNames(NULL, &NameLength)){
                                 DWORD last_error = GetLastError();
 메모리할당                           if (last_error != ERROR_INSUFFICIENT_BUFFER){
     오류                                           snprintf(errbuf, PCAP_ERRBUF_SIZE,"PacketGetAdapterNames: %s“,pcap_win32strerror()); return
(-1);}}                                                                                              길이가 양수이면 Adapters 메모리할당을
               if (NameLength > 0) {AdaptersName = (char*) malloc(NameLength);}                     하고 0 또는 음수이면 0을 리턴 하고 종료.
               else {*alldevsp = NULL; return 0; }
               if (AdaptersName == NULL){snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); return
(-1);}
               if (!PacketGetAdapterNames(AdaptersName,만약 PacketGetAdapterNames() 함수로 어뎁터의 이름을 얻지 못했으면 -1을 반환하여 에러처
                                                                    &NameLength))
                                                                                                           리
                              {snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s", pcap_win32strerror()); free(AdaptersName);
return (-1);}
               desc = &AdaptersName[0];                              얻은 이름을 name에 대입.
               while (*desc != '0' || *(desc + 1) != '0')    lookupdev함수에서 이 name을 참조함.
                                 desc++;
               desc += 2;
               name = &AdaptersName[0];
               while (*name != '0') {
                                 if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {ret = -1; break}
                                 name += strlen(name) + 1;
                                 desc += strlen(desc) + 1;}
               if (ret != -1) {
                                 if (pcap_platform_finddevs(&devlist, errbuf) < 0) ret = -1;}

              if (ret == -1) {
                                 if (devlist != NULL) {pcap_freealldevs(devlist); devlist = NULL;}}
2-2. pcap_freealldevs()
void pcap_freealldevs(pcap_if_t *alldevs)
{                                                       인자로 받은 alldevs를 차례로 하나씩 순회 Linked List
           pcap_if_t *curdev, *nextdev;
           pcap_addr_t *curaddr, *nextaddr;
           for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
                       nextdev = curdev->next;
                       for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
                                   nextaddr = curaddr->next;
     순회된 각 디바이스의                   if (curaddr->addr){free(curaddr->addr);}
   주소정보가 담긴 구조체를                   if (curaddr->netmask){free(curaddr->netmask);}
  순회면서 주소 정보들을 반환.                 if (curaddr->broadaddr){free(curaddr->broadaddr);}
                                   if (curaddr->dstaddr){free(curaddr->dstaddr);}
                                   free(curaddr);
                       }
                       free(curdev->name);
                       if (curdev->description != NULL)
                                   free(curdev->description);
                       free(curdev);
           }
}
                     디바이스의 이름을 반환하고,
       만약 디바이스의 디스크립션이 존재하면 그것도 반환한다.
     마지막으로 디바이스 자체를 반환한다음 다음 디바이스로 순회
2-2. pcap_freealldevs()
     pcap_if_t alldevs                      pcap_if_t alldevs

addres                                 addres
   s                                      s
  addr -> free                           addr -> free
 netmsk ->free                          netmsk ->free
broadaddr ->free                       broadaddr ->free
 dstaddr ->free                         dstaddr ->free
             next                                   next

addres                                 addres
   s                                      s
  addr -> free           null            addr -> free           null
 netmsk ->free                          netmsk ->free
broadaddr ->free                       broadaddr ->free
 dstaddr ->free                         dstaddr ->free
             next                                   next

addres                                 addres
   s                                      s
  addr -> free                           addr -> free
 netmsk ->free                          netmsk ->free
broadaddr ->free                       broadaddr ->free
 dstaddr ->free                         dstaddr ->free
             next               next                next               next
3. pcap_open_live()
   디바이스 열기
  3-1        pcap_create()

          pcap_set_snaplen()
  3-2     pcap_set_snaplen()
          pcap_set_snaplen()

  3-3    pcap_check_activated()


  3-4       pcap_activate()
3. pcap_open_live()
pcap_t *pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf)
{
             pcap_t *p;                                   pcap_t, status 선언 및
             int status;                                  함수 pcap_create()함수로 pcap_t을 생성한다.
             p = pcap_create(source, errbuf);             생성이 정상적으로 되지 않을 경우 NULL 을 반환하고 종료.
             if (p == NULL)
                               return (NULL);
             status = pcap_set_snaplen(p, snaplen);
             if (status < 0)
                               goto fail;
             status = pcap_set_promisc(p, promisc);          3개의 set 함수에는 pcap_check_activated() 라는 함수가 있다. 이 함수도 디바이스의 개
             if (status < 0)                                 방 여부를 체크한다. 이상이 없다고 판단되면, 포인터로 pcap_t에 접근하여 각각 값을 set
                               goto fail;                    한다. set까지 완료되면 0을 반환한다. 만약 0보다 작은 값을 반환하면 goto fail.
             status = pcap_set_timeout(p, to_ms);
             if (status < 0)
                               goto fail;                    포인터로 pcap_t에 접근하여 oldstyle을 1로 입력.
             p->oldstyle = 1;                                모든 에러를 통과하면 함수 pcap_activate() 로 디바이스를 연다.
             status = pcap_activate(p);
                                                             이때도 반환값으로 열기가 성공했는지 못했는지 검출하여 에러가 있으면 goto fail.
             if (status < 0)
                                                             에러가 없다면 정상적으로 디바이스가 열린것으로 간주하여 pcap_t의 주소를 반환.
                               goto fail;
             return (p);
     fail:
             if (status == PCAP_ERROR)
                               snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, p->errbuf);
             else if (status == PCAP_ERROR_NO_SUCH_DEVICE|| status == PCAP_ERROR_PERM_DENIED || status ==
PCAP_ERROR_PROMISC_PERM_DENIED)
                               snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source, pcap_statustostr(status), p->errbuf);
             else
                               snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_statustostr(status));
             pcap_close(p);
             return (NULL);
}
3-1. pcap_create()
pcap_t *pcap_create(const char *source, char *ebuf){                pcap_t 메모리 할당 및 에러처리
          pcap_t *p;
          p = malloc(sizeof(*p));
          if (p == NULL) {
                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
                       return (NULL);
          }
          memset(p, 0, sizeof(*p));
#ifndef WIN32
          p->fd = -1; p->selectable_fd = -1; p->send_fd = -1;
#endif
          p->opt.source = strdup(source);
          if (p->opt.source == NULL) {
                       snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s“, pcap_strerror(errno));
                       free(p);
                       return (NULL);
          }
          p->can_set_rfmon_op = pcap_cant_set_rfmon;
          initialize_ops(p);
          pcap_set_timeout(p, 0);
          pcap_set_snaplen(p, 65535);
          p->opt.promisc = 0;
          p->opt.buffer_size = 0;
          p->opt.tstamp_type = -1;
          return (p);
}
3-2. pcap_set_ 3가지 ()
                                                       함수 pcap_check_activated() 로
                                                         현재 활성화인지 판단.
int pcap_set_snaplen(pcap_t *p, int snaplen){          활성화이면 에러. 아니면 패스
          if (pcap_check_activated(p))
                      return (PCAP_ERROR_ACTIVATED);
          p->snapshot = snaplen;
                                                        정보 저장 후 종료
          return (0);
}
int pcap_set_promisc(pcap_t *p, int promisc){
          if (pcap_check_activated(p))
                      return (PCAP_ERROR_ACTIVATED);
          p->opt.promisc = promisc;
          return (0);
}
int pcap_set_timeout(pcap_t *p, int timeout_ms){
          if (pcap_check_activated(p))
                      return (PCAP_ERROR_ACTIVATED);
          p->md.timeout = timeout_ms;
          return (0);
}
3-3. pcap_check_activated()

int pcap_check_activated(pcap_t *p)
{
           if (p->activated) {
                        snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
                                     " operation on activated capture");
                        return (-1);
           }
           return (0);
}

                                                        activated값이 0이 아니면 -1반환


  activated값이 0이면 0반환
3-4. pcap_activate()
ㅇint pcap_activate(pcap_t *p)
{
          int status;                                                             활성화인지 판단
          if (pcap_check_activated(p))
                       return (PCAP_ERROR_ACTIVATED);
          status = p->activate_op(p);                               activate_op() 함수의 반환값이 0이거
          if (status >= 0)                                                          나
                       p->activated = 1;                            0보다 크면 pcap_t을 활성화시키고,
          else {                                                             그렇지 않으면 에러
                       if (p->errbuf[0] == '0') {
                                    snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
                                     pcap_statustostr(status));
                       }
                       initialize_ops(p);
          }
          return (status);
}
4. pcap_next()
   패킷캡쳐
4. pcap_next()
                                                                       struct oneshot_userdata {
                                                                                  struct pcap_pkthdr
const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)              *hdr;
{                                                                                 const u_char **pkt;
          struct oneshot_userdata s;                                              pcap_t *pd;
          const u_char *pkt;                                           };
          s.hdr = h;
          s.pkt = &pkt;
          s.pd = p;
          if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s)
<= 0)                                                                  반환값은 성공시 읽은 패킷의 갯수
                       return (0);                                     0 : 저장 파일의 EOF
          return (pkt);                                                -1 : 에러가 발생했을 때.
}                                                                      pcap_perror()이나 pcap_geterr()을
                                                                       사용해 에러 메시지를 확인할 수 있
int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char
                                                                       다.
*user)
{
            return (p->read_op(p, cnt, callback, user));
}
끝

Weitere ähnliche Inhalte

Was ist angesagt?

Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)
fefe7270
 
Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)
fefe7270
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
Esun Kim
 
Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)
fefe7270
 
Android audio system(pcm데이터출력요청-서비스클라이언트)
Android audio system(pcm데이터출력요청-서비스클라이언트)Android audio system(pcm데이터출력요청-서비스클라이언트)
Android audio system(pcm데이터출력요청-서비스클라이언트)
fefe7270
 
Android audio system(pcm데이터출력준비-서비스서버)
Android audio system(pcm데이터출력준비-서비스서버)Android audio system(pcm데이터출력준비-서비스서버)
Android audio system(pcm데이터출력준비-서비스서버)
fefe7270
 
Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)
fefe7270
 

Was ist angesagt? (20)

Jupyter notebok tensorboard 실행하기_20160706
Jupyter notebok tensorboard 실행하기_20160706Jupyter notebok tensorboard 실행하기_20160706
Jupyter notebok tensorboard 실행하기_20160706
 
04장 고급변수 사용
04장 고급변수 사용04장 고급변수 사용
04장 고급변수 사용
 
Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?
 
android_thread
android_threadandroid_thread
android_thread
 
Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)Android audio system(오디오 플링거 서비스 초기화)
Android audio system(오디오 플링거 서비스 초기화)
 
Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)Android audio system(audiopolicy_manager)
Android audio system(audiopolicy_manager)
 
파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
 
Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기
Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기
Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기
 
[2012 CodeEngn Conference 07] nesk - Defcon 20th : 본선 CTF 문제풀이
[2012 CodeEngn Conference 07] nesk - Defcon 20th : 본선 CTF 문제풀이[2012 CodeEngn Conference 07] nesk - Defcon 20th : 본선 CTF 문제풀이
[2012 CodeEngn Conference 07] nesk - Defcon 20th : 본선 CTF 문제풀이
 
[2010 CodeEngn Conference 04] hahah - Defcon 18 CTF 문제풀이
[2010 CodeEngn Conference 04] hahah - Defcon 18 CTF 문제풀이[2010 CodeEngn Conference 04] hahah - Defcon 18 CTF 문제풀이
[2010 CodeEngn Conference 04] hahah - Defcon 18 CTF 문제풀이
 
Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)Android audio system(오디오 출력-트랙생성)
Android audio system(오디오 출력-트랙생성)
 
Android audio system(pcm데이터출력요청-서비스클라이언트)
Android audio system(pcm데이터출력요청-서비스클라이언트)Android audio system(pcm데이터출력요청-서비스클라이언트)
Android audio system(pcm데이터출력요청-서비스클라이언트)
 
[2009 CodeEngn Conference 03] hkpco - DEFCON CTF 2009 Binary Leetness 100-500...
[2009 CodeEngn Conference 03] hkpco - DEFCON CTF 2009 Binary Leetness 100-500...[2009 CodeEngn Conference 03] hkpco - DEFCON CTF 2009 Binary Leetness 100-500...
[2009 CodeEngn Conference 03] hkpco - DEFCON CTF 2009 Binary Leetness 100-500...
 
Android audio system(pcm데이터출력준비-서비스서버)
Android audio system(pcm데이터출력준비-서비스서버)Android audio system(pcm데이터출력준비-서비스서버)
Android audio system(pcm데이터출력준비-서비스서버)
 
PostgreSql vaccum
PostgreSql vaccumPostgreSql vaccum
PostgreSql vaccum
 
Device driver
Device driverDevice driver
Device driver
 
Linux blue borne-vulnerabilities
Linux blue borne-vulnerabilitiesLinux blue borne-vulnerabilities
Linux blue borne-vulnerabilities
 
Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)Android audio system(오디오 출력-트랙활성화)
Android audio system(오디오 출력-트랙활성화)
 
파이썬 기본 문법
파이썬 기본 문법파이썬 기본 문법
파이썬 기본 문법
 

Ähnlich wie Pcap 세미나

Ähnlich wie Pcap 세미나 (17)

#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#17.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
 
Chapter3 - learning spark
Chapter3 - learning sparkChapter3 - learning spark
Chapter3 - learning spark
 
Perl Script Document
Perl Script DocumentPerl Script Document
Perl Script Document
 
[Pgday.Seoul 2018] PostgreSQL 11 새 기능 소개
[Pgday.Seoul 2018]  PostgreSQL 11 새 기능 소개[Pgday.Seoul 2018]  PostgreSQL 11 새 기능 소개
[Pgday.Seoul 2018] PostgreSQL 11 새 기능 소개
 
Sha 2017-teaser-round website attack writeup
Sha 2017-teaser-round website attack writeupSha 2017-teaser-round website attack writeup
Sha 2017-teaser-round website attack writeup
 
Es2015 Simple Overview
Es2015 Simple OverviewEs2015 Simple Overview
Es2015 Simple Overview
 
DB와암호화 패턴
DB와암호화 패턴DB와암호화 패턴
DB와암호화 패턴
 
[2013 CodeEngn Conference 09] wh1ant - various tricks for linux remote exploits
[2013 CodeEngn Conference 09] wh1ant - various tricks for linux remote exploits[2013 CodeEngn Conference 09] wh1ant - various tricks for linux remote exploits
[2013 CodeEngn Conference 09] wh1ant - various tricks for linux remote exploits
 
Java mentoring of samsung scsc 2
Java mentoring of samsung scsc   2Java mentoring of samsung scsc   2
Java mentoring of samsung scsc 2
 
Mean 스택을 사용한 IoT 개발
Mean 스택을 사용한 IoT 개발Mean 스택을 사용한 IoT 개발
Mean 스택을 사용한 IoT 개발
 
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
 
Windows via c++ chapter6
Windows via c++   chapter6Windows via c++   chapter6
Windows via c++ chapter6
 
RPG Maker와 Ruby로 코딩 시작하기 Day 3
RPG Maker와 Ruby로 코딩 시작하기 Day 3RPG Maker와 Ruby로 코딩 시작하기 Day 3
RPG Maker와 Ruby로 코딩 시작하기 Day 3
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차
 
ffmpeg optimization using CUDA
ffmpeg optimization using CUDAffmpeg optimization using CUDA
ffmpeg optimization using CUDA
 
파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄
 
Ryu with OpenFlow 1.3, REST API
Ryu with OpenFlow 1.3, REST APIRyu with OpenFlow 1.3, REST API
Ryu with OpenFlow 1.3, REST API
 

Pcap 세미나

  • 1. 패킷 캡쳐 라이브러리 주요함수 코드분석 정보통신공학과 200801559 윤천호
  • 2. 차 1. 패킷 캡쳐 과정 2. pcap_lookupdev() 2-1. pcap_findalldevs() 2-2. pcap_freealldevs() 3. pcap_open_live() 3-1. pcap_create() 3-2. pcap_set_ 3가지 () 3-3. pcap_check_activated() 3-4. pcap_activate() 4. pcap_next()
  • 4. 1. 패킷캡쳐 과정 디바이스 이름 얻기 디바이스 열기 pcap_lookupdev() pcap_open_live() 디바이스 닫기 패킷캡처 pcap_close() pcap_next()
  • 5. 2. pcap_lookupdev() 디바이스 이름얻기 2-1 pcap_findalldevs() 2-2 pcap_freealldevs()
  • 6. 2. pcap_lookupdev() char *pcap_lookupdev(errbuf) register char *errbuf; pcap_if_t 타입의 주소값을 저장하는 alldevs 선언 { pcap_if_t *alldevs; 만약 IF_NAMESIZE가 정의 되어있지 않으면 #ifndef IF_NAMESIZE IF_NAMESIZE 는 IFNAMSIZ로 정의 #define IF_NAMESIZE IFNAMSIZ 케릭터 배열 device[]의 크기는 IF_NAMESIZE #endif +1 그리고 스트링 ret 선언 static char device[IF_NAMESIZE + 1]; char *ret; 함수 pcap_findalldevs() 의 반환값으로 exception에러 검출 후 그에 따른 조치 if (pcap_findalldevs(&alldevs, errbuf) == -1) 그리고 디바이스가 검색되지 않았을 경우에도 return (NULL); 최종 반환하는 ret에 NULL값을 대입. if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) { 포인터 인자를 사용했기에 name에 접근이 가능 (void)strlcpy(errbuf, "no suitable device found", 위의 반환값에서 오류가 검출되지 않았으면 PCAP_ERRBUF_SIZE); name값을 device에 복사 그리고 ret에 복사 ret = NULL; } else { (void)strlcpy(device, alldevs- >name, sizeof(device)); ret = device; 함수 pcap_freealldevs() 로 포인터 변수 alldevs를 초 } 기화 pcap_freealldevs(alldevs); 및 결과 반환
  • 7. 2-1. pcap_findalldevs() int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf){ pcap_if_t *devlist = NULL; int ret = 0; const char *desc; 만약 PacketGetAdapterNames() 함수로 디바이스의 길이를 먼저 파악. char *AdaptersName; 반환값 이 부정이면 -1을 반환하여 에러처리 ULONG NameLength; char *name; if (!PacketGetAdapterNames(NULL, &NameLength)){ DWORD last_error = GetLastError(); 메모리할당 if (last_error != ERROR_INSUFFICIENT_BUFFER){ 오류 snprintf(errbuf, PCAP_ERRBUF_SIZE,"PacketGetAdapterNames: %s“,pcap_win32strerror()); return (-1);}} 길이가 양수이면 Adapters 메모리할당을 if (NameLength > 0) {AdaptersName = (char*) malloc(NameLength);} 하고 0 또는 음수이면 0을 리턴 하고 종료. else {*alldevsp = NULL; return 0; } if (AdaptersName == NULL){snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); return (-1);} if (!PacketGetAdapterNames(AdaptersName,만약 PacketGetAdapterNames() 함수로 어뎁터의 이름을 얻지 못했으면 -1을 반환하여 에러처 &NameLength)) 리 {snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s", pcap_win32strerror()); free(AdaptersName); return (-1);} desc = &AdaptersName[0]; 얻은 이름을 name에 대입. while (*desc != '0' || *(desc + 1) != '0') lookupdev함수에서 이 name을 참조함. desc++; desc += 2; name = &AdaptersName[0]; while (*name != '0') { if (pcap_add_if_win32(&devlist, name, desc, errbuf) == -1) {ret = -1; break} name += strlen(name) + 1; desc += strlen(desc) + 1;} if (ret != -1) { if (pcap_platform_finddevs(&devlist, errbuf) < 0) ret = -1;} if (ret == -1) { if (devlist != NULL) {pcap_freealldevs(devlist); devlist = NULL;}}
  • 8. 2-2. pcap_freealldevs() void pcap_freealldevs(pcap_if_t *alldevs) { 인자로 받은 alldevs를 차례로 하나씩 순회 Linked List pcap_if_t *curdev, *nextdev; pcap_addr_t *curaddr, *nextaddr; for (curdev = alldevs; curdev != NULL; curdev = nextdev) { nextdev = curdev->next; for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) { nextaddr = curaddr->next; 순회된 각 디바이스의 if (curaddr->addr){free(curaddr->addr);} 주소정보가 담긴 구조체를 if (curaddr->netmask){free(curaddr->netmask);} 순회면서 주소 정보들을 반환. if (curaddr->broadaddr){free(curaddr->broadaddr);} if (curaddr->dstaddr){free(curaddr->dstaddr);} free(curaddr); } free(curdev->name); if (curdev->description != NULL) free(curdev->description); free(curdev); } } 디바이스의 이름을 반환하고, 만약 디바이스의 디스크립션이 존재하면 그것도 반환한다. 마지막으로 디바이스 자체를 반환한다음 다음 디바이스로 순회
  • 9. 2-2. pcap_freealldevs() pcap_if_t alldevs pcap_if_t alldevs addres addres s s addr -> free addr -> free netmsk ->free netmsk ->free broadaddr ->free broadaddr ->free dstaddr ->free dstaddr ->free next next addres addres s s addr -> free null addr -> free null netmsk ->free netmsk ->free broadaddr ->free broadaddr ->free dstaddr ->free dstaddr ->free next next addres addres s s addr -> free addr -> free netmsk ->free netmsk ->free broadaddr ->free broadaddr ->free dstaddr ->free dstaddr ->free next next next next
  • 10. 3. pcap_open_live() 디바이스 열기 3-1 pcap_create() pcap_set_snaplen() 3-2 pcap_set_snaplen() pcap_set_snaplen() 3-3 pcap_check_activated() 3-4 pcap_activate()
  • 11. 3. pcap_open_live() pcap_t *pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf) { pcap_t *p; pcap_t, status 선언 및 int status; 함수 pcap_create()함수로 pcap_t을 생성한다. p = pcap_create(source, errbuf); 생성이 정상적으로 되지 않을 경우 NULL 을 반환하고 종료. if (p == NULL) return (NULL); status = pcap_set_snaplen(p, snaplen); if (status < 0) goto fail; status = pcap_set_promisc(p, promisc); 3개의 set 함수에는 pcap_check_activated() 라는 함수가 있다. 이 함수도 디바이스의 개 if (status < 0) 방 여부를 체크한다. 이상이 없다고 판단되면, 포인터로 pcap_t에 접근하여 각각 값을 set goto fail; 한다. set까지 완료되면 0을 반환한다. 만약 0보다 작은 값을 반환하면 goto fail. status = pcap_set_timeout(p, to_ms); if (status < 0) goto fail; 포인터로 pcap_t에 접근하여 oldstyle을 1로 입력. p->oldstyle = 1; 모든 에러를 통과하면 함수 pcap_activate() 로 디바이스를 연다. status = pcap_activate(p); 이때도 반환값으로 열기가 성공했는지 못했는지 검출하여 에러가 있으면 goto fail. if (status < 0) 에러가 없다면 정상적으로 디바이스가 열린것으로 간주하여 pcap_t의 주소를 반환. goto fail; return (p); fail: if (status == PCAP_ERROR) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, p->errbuf); else if (status == PCAP_ERROR_NO_SUCH_DEVICE|| status == PCAP_ERROR_PERM_DENIED || status == PCAP_ERROR_PROMISC_PERM_DENIED) snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source, pcap_statustostr(status), p->errbuf); else snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, pcap_statustostr(status)); pcap_close(p); return (NULL); }
  • 12. 3-1. pcap_create() pcap_t *pcap_create(const char *source, char *ebuf){ pcap_t 메모리 할당 및 에러처리 pcap_t *p; p = malloc(sizeof(*p)); if (p == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } memset(p, 0, sizeof(*p)); #ifndef WIN32 p->fd = -1; p->selectable_fd = -1; p->send_fd = -1; #endif p->opt.source = strdup(source); if (p->opt.source == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s“, pcap_strerror(errno)); free(p); return (NULL); } p->can_set_rfmon_op = pcap_cant_set_rfmon; initialize_ops(p); pcap_set_timeout(p, 0); pcap_set_snaplen(p, 65535); p->opt.promisc = 0; p->opt.buffer_size = 0; p->opt.tstamp_type = -1; return (p); }
  • 13. 3-2. pcap_set_ 3가지 () 함수 pcap_check_activated() 로 현재 활성화인지 판단. int pcap_set_snaplen(pcap_t *p, int snaplen){ 활성화이면 에러. 아니면 패스 if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->snapshot = snaplen; 정보 저장 후 종료 return (0); } int pcap_set_promisc(pcap_t *p, int promisc){ if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->opt.promisc = promisc; return (0); } int pcap_set_timeout(pcap_t *p, int timeout_ms){ if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); p->md.timeout = timeout_ms; return (0); }
  • 14. 3-3. pcap_check_activated() int pcap_check_activated(pcap_t *p) { if (p->activated) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform " " operation on activated capture"); return (-1); } return (0); } activated값이 0이 아니면 -1반환 activated값이 0이면 0반환
  • 15. 3-4. pcap_activate() ㅇint pcap_activate(pcap_t *p) { int status; 활성화인지 판단 if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); status = p->activate_op(p); activate_op() 함수의 반환값이 0이거 if (status >= 0) 나 p->activated = 1; 0보다 크면 pcap_t을 활성화시키고, else { 그렇지 않으면 에러 if (p->errbuf[0] == '0') { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_statustostr(status)); } initialize_ops(p); } return (status); }
  • 16. 4. pcap_next() 패킷캡쳐
  • 17. 4. pcap_next() struct oneshot_userdata { struct pcap_pkthdr const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) *hdr; { const u_char **pkt; struct oneshot_userdata s; pcap_t *pd; const u_char *pkt; }; s.hdr = h; s.pkt = &pkt; s.pd = p; if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0) 반환값은 성공시 읽은 패킷의 갯수 return (0); 0 : 저장 파일의 EOF return (pkt); -1 : 에러가 발생했을 때. } pcap_perror()이나 pcap_geterr()을 사용해 에러 메시지를 확인할 수 있 int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char 다. *user) { return (p->read_op(p, cnt, callback, user)); }
  • 18.