[1. 원형]
pcap_t* pcap_open_live(const char* device, int snaplen, int promisc, int to_ms, char *ebuf)
void pcap_close(pcap_t *p)
pcap_t* pcap_loop(pcap_t* p, int cnt, pcap_handler callback, u_char* user)
void(* pcap_handler)(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
[2. 설명]
- pcap_open_live()
네트워크 상 패킷을 캡쳐하기 위한 descriptor 를 개방할 때 사용 됨.
device: 패킷을 캡쳐할 네트워크 디바이스 이름
리눅스 2.2 이상 커널에서 "any" 또는 NULL 을 사용 한 경우 모든 인터페이스로부터 패킷을 캡쳐 할 수 있다.
snaplen: 캡쳐하기 위한 최대 바이트 수를 명시한다.
캡쳐된 바이트 수 보다 적은 값이 주어지면, 해당 바이트까지만 캡쳐된 데이터로 제공 됨
보통 65535 를 명시하면 모든 패킷에 대해서 캡쳐가 가능함
promisc: 해당 디바이스를 promiscuous mode 로 개방한다.
다만, device 이름을 "any" 혹은 NULL 로 명시한 경우, 해당 옵션은 무시된다.
to_ms: read timeout 을 ms 단위로 명시한다.
모든 플랫폼에서 지원되지 않을 수 있다.
0 은 보통 패킷이 도착할 때 까지 기다리는 것을 의미한다.
함수 호출에 실패한 경우 NULL 이 반환되며, ebuf 에 에러 메시지가 저장된다. - pcap_close()
pcap_open_live() 로 인해 생성된 pcap_t 자료구조에 대한 자원해제를 진행한다. - pcap_loop()
pcap_dispatch() 와 유사하나 다른점은 명시된 개수만큼의 패킷을 읽을 때 까지 유지함.
read timeout 발생 시에 종료되지 않음.
p: pcap_open_live() 로 인해 개방된 descriptor 의 주소를 전달
cnt: 읽을 패킷 개수 명시
0 이하의 값이면 영원히 읽는다.
pcap_handler: callback 함수를 명시
user: 보통 NULL 을 전달함
에러 발생 시 -1 을 리턴
pcap_breakloop() 로 종료된 경우 -2 를 리턴
cnt 만큼 패킷을 읽었을 경우 0 을 리턴한다. - pcap_handler
pcap_dispatch() 또는 pcap_loop() 이 호출된 경우, 캡쳐된 패킷이 전달 되는 함수의 원형
struct pkt_header 는 프로토콜에 관련된 헤더가 아닌, capture 된 패킷의 메타 정보 (timestamp, length)
pkt_data 는 실제 캡쳐된 패킷의 raw data (파싱이 안된 데이터)
[3. 예제]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "pcap.h" | |
void packet_handler(u_char* param, | |
const struct pcap_pkthdr* header, | |
const u_char* pkt_data) | |
{ | |
printf("caplen: %d\n", header->caplen); | |
printf("len: %d\n\n", header->len); | |
} | |
int main(int argc, char** argv) | |
{ | |
pcap_t* adhandle; | |
char errbuf[PCAP_ERRBUF_SIZE]; | |
pcap_if_t* alldevs; | |
pcap_if_t* d; | |
int i = 0; | |
int no; | |
if (pcap_findalldevs(&alldevs, errbuf) < 0) { | |
printf("pcap_findalldevs error\n"); | |
return 1; | |
} | |
for (d = alldevs; d != NULL; d = d->next) { | |
printf("%d : %s\n", ++i, (d->description) ? (d->description) : (d->name)); | |
} | |
printf("number : "); | |
scanf("%d", &no); | |
for (d = alldevs, i = 0; d != NULL; d = d->next) { | |
if (no == ++i) { | |
break; | |
} | |
} | |
if (d == NULL) { | |
printf("there is no dev\n"); | |
pcap_freealldevs(alldevs); | |
} | |
else { | |
// non-promiscous mode | |
adhandle = pcap_open_live(d->name, 65535, 0, 1000, errbuf); | |
if (adhandle == NULL) { | |
printf("pcap_open_live error %s\n", errbuf); | |
pcap_freealldevs(alldevs); | |
return -1; | |
} | |
printf("Start: packet capture\n"); | |
pcap_freealldevs(alldevs); | |
const int ret = pcap_loop(adhandle, 5, packet_handler, NULL); | |
printf("return of pcap_loop: %d\n", ret); | |
pcap_close(adhandle); | |
} | |
return 0; | |
} |
리눅스의 경우 일반 사용자가 위 코드를 실행 시 아래와 같은 에러가 발생할 수 있다.
pcap_open_live error ens33: You don't have permission to capture on that device (socket: Operation not permitted)
따라서 보통 관리자 권한으로 실행해야 한다.
'C++ > Pcap' 카테고리의 다른 글
pcap_dispatch 와 기타 함수 들 (0) | 2022.03.09 |
---|---|
pcap_lookupnet 함수 (0) | 2022.03.06 |
pcap_findalldevs 함수 (0) | 2022.03.06 |
pcap 개발 환경 설정 (0) | 2022.03.06 |