pcap 사용법
#include <stdio.h>
#include <pcap/pcap.h>

int main()
{
  char *NIC;
  char errbuf[PCAP_ERRBUF_SIZE];
  
  NIC = pcap_lookupdev(errbuf);
  if(0 != NIC)
  {
    printf("NETWORK CADR : [%s]\n", NIC);
  }
  else
  {
    printf("ERROR        : [%s]\n", errbuf);
  }

  return 0;
}

pcap 라이브러리 사용하기 위해서는 컴파일 할때 마지막에 -lpcap를 적어주어야 한다. 
패킷 아날라이져 소스
#include <stdio.h>
#include <stdlib.h>
#include <pcap/pcap.h>

void PrintHexaNAscii(const unsigned char *buffer, int size);

int const PROMISC = 1;
int const TIME_DELAY = 0;
int const READ_PACKET_Length = 1500;

int main()
{
  char *IName;
  const unsigned char *RBuf;
  char EBuf[PCAP_ERRBUF_SIZE];
  struct pcap_pkthdr CInfo;
  int counter = 0;
  pcap_t *CD;

  
  write(1"\033[1;1H\033[2J"10);  // 화면 클리어

  IName = pcap_lookupdev(EBuf); // 장치 이름 확인
  if(NULL == IName)
  {
    perror(EBuf);
    exit(100);
  }
  else
  {
    printf("### Interface              : [%s]\n", IName);
  }

  CD = pcap_open_live(IName, READ_PACKET_Length, PROMISC, TIME_DELAY, EBuf);
  // 장치 열기(device, 패킷최대길이, 수신모드, 대기시간, 에러)
  if(NULL == CD)
  {
    perror(EBuf);
    exit(200);
  }
  else
  {  
    printf("### Max Read Packet Length : [%d]Bytes\n", READ_PACKET_Length);
    printf("### Promiscous Mode        : [%s]\n", PROMISC ?  "YES" : "NO");
    printf("### Capture Time Delay     : [%d]Sec\n", TIME_DELAY);
  }

  while(1)
  {
    if(100 <= counter)
    {
      break;
    }
    else
    {
      ++counter;
    }

    RBuf = pcap_next(CD, &CInfo);  // 패킷 정보를 갖고있음(장치, 구조체주소)
    printf("### Captured Packet Length = [%d]\n", CInfo.caplen);

    PrintHexaNAscii(RBuf, CInfo.caplen); // 실제 패킷의 길이
  }
  pcap_close(CD);
  
  return 0;
}

void PrintHexaNAscii(const unsigned char *buffer, int size)
{
  int count1;
  int count2;
  
  const unsigned char *temp=buffer;
  
  printf("Address\t");        
  for(count1=0; count1<16; count1++)
  {// 메뉴 구분
    printf("%02X ", count1);    
  }                  
  for(count1=0; count1<16; count1++)  
  {                  
    printf("%01X", count1);      
  }                  
  printf("\n");            

  for(count1=0; count1<=size; count1+=16)
  {// 메뉴 주소
    printf("0x%04X\t", count1);
    for(count2=0; count2<16; count2++)
    {// 번지 주소
      printf("%02X ", *buffer);
      buffer++;
    }
    
    for(count2=0; count2<16; count2++)
    {// 문자 판별65~90 97~122
      printf("%c", ((*temp>=48)&&(*temp<=57)||
              (*temp>=65)&&(*temp<=90)||
              (*temp>=97)&&(*temp<=122)? *temp : '.'));
      temp++;
    }
    printf("\n");
  }
  printf("\n");
  return;
}

 Ethernet Handle 의 패킷을 보면 LAN카드 번호가 나와 있는 것을 확인 할수 있다. 뒤에 보라색 네모칸안의 45에서 4는 IPv4를 뜻하고 5는 5*4Byte로 20Byte를 갖는다는 것을 알수 있다.
컴파일을 할때 라이브러리 사용을 하기때문에 역시 -lpcap를 붙여주어야 제대로 된다.
(gcc -o packet main.c -lpcap)
char pcap_lookupdev(char *errbuf);
리눅스 머신의 네트웍 디바이스를 가져오는 함수. 
가능한 다비이스중 가장 번호가 낮은 디바이스를 가져옴. 
eth0 <- 으로 표시됨 만약 여러게인경우 숫자만 바뀜 eth1, eth2 ....
i 옵션으로 디바이스를 수동으로 지정할 수 있다.
pcap_t pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
	
위 함수는 실제 기기를 열어주는 기능을 하는 것으로 snaplen는 패킷당 저장할
바이스 수(1500), 실제 datalink계층부터 패킷의 크기를 계산하여 원하는 부분만을
얻어오면 되는 것입니다. 헤더정보만을 보고싶은데 쓸데없이 데이타까지 받을
필요는 없겠죠. 데이터까지 보고싶으면 이를 늘리면 됩니다. 
PROMISCUOUS는 1이며 네트웍 디바이스에 오는 모든 패킷을 받겠다는
의미입니다. 이 모드를 자세하게 설명하면 lan은 모든 패킷이 broadcasting되며
일단 모든 네트웍 디바이스는 동일 네트웍내의 다른 호스트의 패킷도 일단 접하게
됩니다.  그러나, 네트웍 디바이스는 기본적으로 자신의 패킷만을
받게끔 되어있습니다. 그러므로 다른 호스트의 패킷은 버리게 되는 것입니다.
그러나 promiscuous모드로 디바이스 모드를 바꾸게 되면 모든 패킷을 받아들이게
되는 것입니다. 스니퍼링 프로그램은 모두 이 모드를 사용하게 됩니다.
세 번째 인자는 패킷이 버퍼로 전달될 때 바로 전달되는 것이 아니라
위에서 명시한 시간을 넘겼을 때나 버퍼가 다 채워졌을 때 응용프로그램으로
전달되는 것입니다. 

u_char pcap_next(pcap_t *p, struct pcap_pkthdr *h)
 이 함수는 패킷의 정보를 갖고 있습니다. 반환형이 unsigned char형이고
첫 번째 인자는 열어둔 장치를 적어주면되고, 두 번째 인자는 구조체의 주소를
넘겨 주면 됩니다.


저수준 입출력을 사용한 도서 관리 프로그램 v1.0 (2010년 12월 29일 수요일)
사용언어 : C
운영체제 : 리눅스(Ubuntu)
개발도구 : vi 편집기
#include <stdio.h>
#include <fcntl.h>    // oflag 사용을 위함 
#include <sys/stat.h>  // pmode 사용을 위함 
//#include <stdlib.h>
//#include <string.h>
//#include <curses.h>
//#include <unistd.h>
//#include <sys/types.h>

typedef struct tag_booktype
{
  char book[30];
  char author[15];
  char publiser[15];
  char price[15];
  char year[15];
} booktype;

void list(int iInfo);
void insert(void);

int main()
{
  int iFd;
  char iSelect;
  int iCnt=0;
  
  system("clear");
  do {  // 메인 화면 
    if((iFd=open("BOOK.DBF",O_RDWR)) >= 0)
    {  // 파일이 있을 경우만 실행 (보유 현황 표시)
      iCnt=0;
      while(read(iFd, &iSelect, 1) != 0)
      {
        if(iSelect == '\n')
        {
          iCnt++;
        }
      }
    }
  
    close(iFd);
    printf("┏━━━━━━━━━┓\n");
    printf("┃책 보유 현황 : %03d┃\n", iCnt);
    printf("┗━━━━━━━━━┛\n\n");
    printf("┏━ 메뉴선택화면 ━┓\n");
    printf("┃     1.insert     ┃\n");
    printf("┃     2. list      ┃\n");
    printf("┃     3. quit      ┃\n");
    printf("┗━━━━━━━━━┛\n");
    printf(" select : ");
    scanf("%c"&iSelect);
    __fpurge(stdin);
    switch(iSelect)
    {  // 메뉴 선택 설정 
      case '1':
      insert();  // insert함수호출
      break;
    
      case '2':
      list(iCnt);    // list함수호출
      break;

      case '3':  // 종료!!
      break;

      default:  // 선택 오류시 출력!
      printf(" select Error. You select continue.\n");
      break;
    }
  } while('3' != iSelect);  // 메뉴 조건 설정!
  printf(" Books supervision end program.\n");  // 종료 메시지!!
  return 0;
}

void insert(void)
{  // 파일에 정보 추가 설정!
  booktype fIn;
  int iCnt=0;
  int infd;
  char cQuit;

  if((infd=open("BOOK.DBF",O_RDWR|O_APPEND)) < 0)
  {  // 만약 BOOK 파일이 없을 경우 새로 만듬!!
    infd=creat("BOOK.DBF", S_IREAD|S_IWRITE);
    close(infd);
    open("BOOK.DBF", O_RDWR);
  }
  
  do {  // 책 정보 입력!!
    printf("============ [%03d] =============\n", ++iCnt);
    printf("책 이 름 : ");
    scanf("%[^\n]"&fIn.book);  // 공백도 입력 가능!
    __fpurge(stdin);
    fIn.book[strlen(fIn.book)+1]=0;
    fIn.book[strlen(fIn.book)]='|';
    write(infd, fIn.book, strlen(fIn.book));
    
    printf("저    자 : ");
    scanf("%[^\n]"&fIn.author);
    __fpurge(stdin);
    fIn.author[strlen(fIn.author)+1]=0;
    fIn.author[strlen(fIn.author)]='|';
    write(infd, fIn.author, strlen(fIn.author));
    
    printf("출 판 사 : ");
    scanf("%[^\n]"&fIn.publiser);
    __fpurge(stdin);
    fIn.publiser[strlen(fIn.publiser)+1]=0;
    fIn.publiser[strlen(fIn.publiser)]='|';
    write(infd, fIn.publiser, strlen(fIn.publiser));
    
    printf("가    격 : ");
    scanf("%[^\n]"&fIn.price);
    __fpurge(stdin);
    fIn.price[strlen(fIn.price)+1]=0;
    fIn.price[strlen(fIn.price)]='|';
    write(infd, fIn.price, strlen(fIn.price));
    
    printf("출판연도(00/00/00) : ");
    scanf("%[^\n]"&fIn.year);
    __fpurge(stdin);
    fIn.year[strlen(fIn.year)+1]=0;
    fIn.year[strlen(fIn.year)]='\n';
    write(infd, fIn.year, strlen(fIn.year));
    
    printf("아무키나 누르면 계속 끝내려면 'Q' 입력 : ");
    scanf("%c"&cQuit);
    __fpurge(stdin);  // 입력버퍼에 남아있는 찌꺼지 초기화!
  } while(('q' != cQuit)&&('Q' != cQuit));
  close(infd);
  system("clear");
  return;
}
void list(int iInfo)
{  // 파일 안의 정보 출력!
  booktype fList;
  int iCnt=0;
  int iPage=0;
  int iFD;
  int iFind;
  int iFCnt;
  int iEnd;
  int iTemp;
  char cQuit;
  char buffer;
  char cHelp;
  
  system("clear");
  if((iFD=open("BOOK.DBF",O_RDWR)) < 0)
  {  // 파일이 없을 경우 아래 메시지 출력!!
    printf(====================\n");
    printf("   No found File....\n");
    printf(====================\n");
    return;
  }
  
  printf("=========== LIST INFOMATION ============\n");
  do {  // 책 정보 출력!!
    printf("========== [%03d] NUMBER LIST ===========\n", ++iPage);
    
    for(iCnt=0; buffer != '|'; iCnt++)
    {  // 특수문자를 만날때까지 1바이트씩 읽어 버퍼에 저장!
      read(iFD, &buffer, 1);
      fList.book[iCnt]=buffer;
    }
    fList.book[iCnt-1]=0;  // 마지막 특수문자 삭제를 위함!
    for(iCnt=0,buffer=0; buffer != '|'; iCnt++)
    {
      read(iFD, &buffer, 1);
      fList.author[iCnt]=buffer;
    }
    fList.author[iCnt-1]=0;
    for(iCnt=0,buffer=0; buffer != '|'; iCnt++)
    {
      read(iFD, &buffer, 1);
      fList.publiser[iCnt]=buffer;
    }
    fList.publiser[iCnt-1]=0;
    for(iCnt=0,buffer=0; buffer != '|'; iCnt++)
    {
      read(iFD, &buffer, 1);
      fList.price[iCnt]=buffer;
    }
    fList.price[iCnt-1]=0;
    for(iCnt=0,buffer=0; buffer != '\n'; iCnt++)
    {  // 책 한권 정보의 마지막!
      iEnd=read(iFD, &buffer, 1);
      fList.year[iCnt]=buffer;
    }
    fList.year[iCnt-1]=0;
    // 책 정보 출력 
    printf("책 이 름 : ");
    printf("%s", fList.book);
    printf("\n저    자 : ");
    printf("%s", fList.author);
    printf("\n출 판 사 : ");
    printf("%s", fList.publiser);
    printf("\n가    격 : ");
    printf("%s", fList.price);
    printf("\n출판연도 : ");
    printf("%s", fList.year);
    
    if(read(iFD, &buffer, 1== 0)
    {  // 파일의 끝부분이면 출력 종료!
      printf("\n마지막 책의 정보 입니다. 종료하겠습니다.");
      getchar(); // 종료하기전 대기!
      __fpurge(stdin);
      break;  
    }
    lseek(iFD, -1, SEEK_CUR); // 파일의 끝부분을 찾기위한 설정!
    printf("\n계속:Enter 도움말'H' 끝내기'Q' : ");
    scanf("%c"&cQuit);
    __fpurge(stdin);
    iTemp=iPage;
    
    if(('H' == cQuit)||('h' == cQuit))
    {  // 도움말 메뉴 부분! 
      do {
      printf("========================================\n");
      printf("============== Help  Menu ==============\n");
      printf("========================================\n");
      printf("===    현재 책 보유량 : 총 %03d권!    ===\n", iInfo);
      printf("========================================\n");
      printf("===     Q   : Help Menu EXIT         ===\n");
      printf("===     F   : Find list line         ===\n");
      printf("========================================\n");
      printf(">>원하는 항목을 선택하세요 : ");
      cHelp=getchar();
      __fpurge(stdin);
      if((cHelp == 'f')||(cHelp == 'F'))
      {  // 도움말 메뉴에서 'F' 선택시 원하는 책 라인으로 이동!
        printf("========================================\n");
        printf("찾고 싶은 위치를 입력해 주세요(숫자) : ");
        scanf("%d"&iPage);
        __fpurge(stdin);
        if((0 < iPage) && (iInfo >= iPage))
        {  // 1 ~ 총 보유량까지만 입력 가능!
          lseek(iFD, 0, SEEK_SET);  // 파일위치를 제일 처음으로 이동!
          for(iFCnt=0; iFCnt<iPage-1; )
          {  // 한권의 책정보를 찾기 위함!
            read(iFD, &buffer, 1);
            if(buffer == '\n')
            {  // 한권의 책정보를 찾으면 파일카운터 1씩 올림!
              iFCnt++;
            }          
          }
          iPage-=1;
          cHelp='q';
          printf("========================================\n\n");
        }
        else
        {  // 만약 찾는 위치가 1이하거나 보유량을 넘을 경우 실행!
          system("clear");
          printf("============= Error Report =============\n");
          printf("========================================\n");
          printf("= 선택한 범위에는 책의 정보가 없습니다.=\n");
          printf("========================================\n\n");
          iPage=iTemp;  // 입력 오류시 다음 책 페이지 정보!
        }
      }
      } while(('q' != cHelp)&&('Q' != cHelp));
    }
  } while(('q' != cQuit)&&('Q' != cQuit));
  close(iFD);
  printf("========================================\n");
  printf("========= END LIST INFOMATION ==========\n");
  return;
}



'C언어 > 프로젝트' 카테고리의 다른 글

리눅스 pcap 활용한 패킷 아날라이져  (0) 2011.03.09
static의 특징
main.c
#include <stdio.h>

void test(void);

int iNumC;

int main()
{
  static int iNumA=5;

  printf("main Address iNumA : %d\n", iNumA);
  printf("main Value iNumA : %08X\n"&iNumA);
  printf("main Address iNumC : %d\n", iNumC);
  printf("main Value iNumC : %08X\n"&iNumC);
  ++iNumC;
  test();
  //test();
  //test();
  printf("main Address iNumC : %d\n", iNumC);
  printf("main Value iNumC : %08X\n"&iNumC);
  return 0;
}
test.c
int iNumC;

void test(void)
{
  static int iNumA;
  int iNumB;
  
  printf("============ TEST() START =============\n");
  printf("func's TESTA(%d)\n", iNumA);
  printf("test Address iNumA : %08X (static)\n"&iNumA);  // static 변수 
  printf("test Address iNumB : %08X (지역)\n"&iNumB);  // 지역 변수 
  printf("test Address iNumC : %08X (전역)\n"&iNumC);  // 전역 변수 
  printf("=======================================\n");
  printf("test Value iNumA : %d (static)\n", iNumA);  // static 변수 
  printf("test Value iNumB : %d (지역)\n", iNumB);  // 지역 변수 
  iNumC=5;
  printf("test Value iNumC : %d (전역)\n", iNumC);  // 전역 변수 
  printf("=======================================\n");
  iNumA++;
  iNumB++;
  return;
}


위의 소스를 보면 우선 실험을 위해 main함수와 test함수를 분리해 놨다. 우선 A변수는 main과 test함수에서 static을 선언하였고 C변수는 전역변수로 선언해 놓았다. 그리고 B변수는 지역변수이다. 지역변수는 이미 알고있듯이 함수 내에서 선언할경우 지역변수가 되는데 지역변수는 알고있으므로 패스한다. 다음 전역변수부터 보도록 한다. 전역변수 C의 주소를 보면 main함수의 주소와 비슷한것을 볼수있다. 전역변수의 경우는 지역변수와 같이 스택에 저장되는 것이 아니라 BSS, DATA영역을 할당받는데 초기화를 하지 않을경우는 BSS영역에서 타입형만큼의 크기를 0으로 가득채워놓고 정보를 기억하고 있다가 초기화가 이루어지면 DATA영역에 할당되어 그 값을 기억한다. 위에 소스를 보면 main.c와 test.c에 각각 전역변수로 C를 선언되어있다. main.c에서 전역변수를 선언안하고 컴파일할경우 에러메시지와 함께 컴파일이 되지는 않지만 main.c에서도 전역변수를 선언해주면 이상없이 컴파일이 된다. 그리고 출력결과를 확인해보면 main의 전역변수 주소와 test의 전역변수 주소가 같은것을 볼수있다. 그리고 main에서 C변수를 수정하니 test의 변수도 같이 변한것을 볼수있고 test에서 5를 대입해주니 main에서도 5가 대입된것을 볼수있다. 이것을 보면 전역변수C는 모든 함수의 공유를 한다는 것을 유추할수 있는데 이것이 전역변수의 장점이자 단점이 된다. C프로그램에서 유일하게 접근성을 갖고있다. 그리고 static변수를 다시 확인해보자.
위에 출력결과를 보면 static변수A의 주소는 main과 test에서 각각 다른것을 확인할수 있다. 지역변수의 경우 함수를 빠져나가면 그값이 사라지는데 반해 static변수의 경우 함수를 호출하고 빠져나가도 그 값이 전역변수처럼 사라지지않는다. 그리고 전역변수처럼 다른함수의 접근을 허용하지 않아 보안기능을 갖고있다. 위에 소스에서는 main함수에서 A변수의 값을 5넣었다. 출력결과를보면 main은 5인데 test함수의 A변수는 0인것을 보면 쉽게 이해할수 있을 것이다.

ls -al >test.A  <<-- 화면에 보여줄 파일을 test.A로 저장해준다.(reDirection)
#include <stdio.h>

int main()
{

  fprintf(stdout,"STDOUT \n");  // 표준출력 
  fprintf(stderr,"STDERR \n");  // 표준출력 
  return 0;
}
표준 입출력장치 파일 핸들 값.
stdin   0
stdout 1
stderr  2

저수준 file 입출력의 read/write –disk user가 설정한 buffer에서 자료를 읽고쓴다.

Buffer file입출력의 getc/putc  fgets/fputs

-       시스템이 설정한 buffer 와 user가 정한 변수와의 사이에서 자료를 읽고 쓴다

-       Buffer disk간의 자료를 읽고 쓰는 것은 시스템이 필요에 따라서 (buffer empty  full일 때)자동적으로 행한다

입출력 함수 분류표

   

   

    

(메모리내)

문자열

저수준

 

표준파일

(표준 입출력에 대한 I/O)

스트림파일

(file 입출력에 대한 I/O)

바이너리파일

문자

입력

getchar()

getc(stream)

 

 

gfetc(stream)

 

 

출력

putchar()

putc(c,stream)

 

 

fputc(c,stream)

 

 

unget(c,stream)

 

 

입력

(stdin 으로 부터 문자열을str로 시작되는 버퍼에 읽어드린다)

\n 대신에 \0가 부가되어 저장

gets(str)

fgets(buf, max, stream)

 

read(fd, buf,nbyte)

단어

getw(stream)

 

블록

fread(ptr, size, nitems,stream)

 

출력

(str로 보인 버퍼에 기억된 문자열을stdout에 출력한다.)

\0 을 만나면\n으로 바꿔서 출력

puts(str)

fputs(buf, stream)

 

write(fd, buf,nbyte)

단어

putw(w,stream)

 

블록

fwrite(ptr, size, nitems,stream)

 

레코드

입력

scanf(format,[args])

fscanf(stream, format,[args])

sscanf(str, format,[args])

 

출력

printf(format,[args])

fprintf(stream, format,[args])

sprintf(str, format,[args])

 

파일

열기

(자동)

fopen(filename,mode)

 

 

freopen(filename,mode,stream)

 

 

fdopen(fd,mode)

 

 

닫기

(자동)

fclose(stream)

 

 

fflush(stream)

 

 

탐색

(자동)

fseek(stream,offset,mode)

 

open

ftell(stream)

 

close

rewind(stream)

 

lseek(fd,offset, mode)

 

+ Recent posts