본문
며칠전 패킷분석을 많이 했었다는 글을 올리면서..
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);
}
행여나 혹시나 궁금한게 있으시면// 질문 남겨주세요..
찾아서라도............쿨럭.;ㅋㅋ
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);
}
행여나 혹시나 궁금한게 있으시면// 질문 남겨주세요..
찾아서라도............쿨럭.;ㅋㅋ
'컴퓨터 이야기' 카테고리의 다른 글
[Tip] vi에서 자신이 typedef한 type을 하이라이팅하기~! (2) | 2007.07.23 |
---|---|
[Tip] 스크립트에서 Signal을 제어하자~! (2) | 2007.07.16 |
노트북에 cygwin을 깔아는데..... (2) | 2007.06.20 |
[?] Dell에서 윈도우 대신 우분투를 기본으로 판매할 때 가격은?.. (0) | 2007.06.11 |
[Linux] 우분투 설치하다.-..// (6) | 2007.06.11 |