며칠전 패킷분석을 많이 했었다는 글을 올리면서..
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 |
| [WinpCap] winpcap 예제..basic_dump.c 분석~!// (23) | 2007/06/24 |
| 노트북에 cygwin을 깔아는데..... (2) | 2007/06/20 |
| [?] Dell에서 윈도우 대신 우분투를 기본으로 판매할 때 가격은?.. (0) | 2007/06/11 |
| [Linux] 우분투 설치하다.-..// (6) | 2007/06/11 |
Trackback : http://heestory.kr/trackback/220
-
삭제
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를 다운 받으면 그 안에 샘플들이 많이 있어서..
댓글을 달아 주세요
성실하게 잘 달아 놓으셨네요, 잘 보고 갑니다~
프로그래밍 초보가..
처음 winpcap을 공부한다는 마음으로 달았습니다-ㅋ
5년전을 기억하며...ㅋㅋ
방문 감사합니당~~ㅋ 자주 놀러오세욧.ㅎ
멋지세요~
pcap 참 쓰기 간략하게 잘 만들어진거 같아요 ㅎ
이거 아님 NDIS 삽질을 얼마나 하려나 ㅡ,..ㅡ
잘보고 갑니다~
감사합니다^-^...
pcap 참 쓰기 편하죠...ㅎ
윈도우에서 NDIS 한번 해볼꺼라고 원서보다가 잠들었던 기억이.....쿨럭;;ㅎ
방문 감사드리고~ 다음에 또 놀러오세요.ㅋㅋ
참 고맙네요 pcap가 어느정도 보이네요 그전에는 전혀보일것같지 않더니
다른것은 더 분석하지 못햇나요. 인차 분석해서 또 올렷으면 고맙겠네요. 화이팅 ^^
방문 감사합니다^-^ㅋ
도움이 되셨다니..기쁘네요.하핫..ㅋㅋ
어떤걸 더 분석할까 고민하다가..
마땅한게 없어서..;;
혹시 궁금한거 있으면 요청하시면 제가 아는 선에서 분석해드리겠습니다^-^..
오~성실하게 주석 달아놓으셨네요^-^
담아갈께요!!!
ㅋㅋ네-^// ㅎ
안녕하세요.
좋은자료 감사히 읽고 공부하는데 쓰겠습니다.
혹시 제가 하다가 모르는 부분에 대해서 질문 메일 보내고 싶은데
혹시 메일주소 알수 있을까요?
아..네-
dinoguy 지메일닷컴
입니다-ㅋ 열시미하세용-ㅎㅋㅋ
정말감사합니다. 이번에 라우터에 패킷을 분석해서 DB를 구축하려하는데
정말 찾던 자료입니다 .
좋은자료 참고해서 좋은자료 만들어 보겠습니다.
방문 감사합니다..ㅋ
좋은 자료 만드셔서 공유해주세요-ㅋㅋ
네 알겠습니다 ^^
와 찾던자료인데!! 퍼가도되나요?
네-..출처만 남겨주세요-ㅋㅋ
윈도우 환경에서의 패킷캡춰 누수율이 어느정도 될까요 ? 리눅스는 커널컴파일 없이는 누수율이 상당해서 패킷량 많은 곳에서 사용하기는 좀 애매모호 하더라구요.
글쎄요...??하하;;
리눅스에서는..drop되는 패킷수가 나와서..
인식을 했었는데...윈도우에서는 별 생각없이 썼더니;;;
전혀 모르겠네요-ㅎㅎ
예전에 대학원에서...같은 연구실에 선배가..queue를 여러개 사용해서 누수율을 최소화 시키는 걸 개발했었는데...ㅋㅋ
관련 자료들이 없어요..하핫;;ㅋㅋ
멋지시네요 ㅎㅎ
이제 네트워킹 프로그래밍을 공부 시작한 초본데요;;;
시작부터 막혀서 쫌 여쭤볼려고요 ㅎㅎㅎ
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을 잘못 연결한건가요?? ㅡㅡ;;;;;
아;; 라이브러리가 문제였던거 같네요 ㅎㅎㅎ 위에 소스 실행해보니까... 길이만 나오네요?? ㅎㅎㅎ 좋은자료 감사 합니다~ 열공할께요 ㅎ
방문 감사합니다....
스스로 해결하셨네요-ㅋㅋㅋ 추카드려요-ㅎ
잘보고 퍼갑니다 __)
ㅋㅋ네^^
좋은 내용 잘 보고 갑니다.
네이버 블로그로 퍼갑니다~^^
출처는 당연히 표시할게요~감사.