본문으로 바로가기

Packet sniffer develop #pcap_open_live

category 카테고리 없음 2018. 4. 15. 15:50

패킷 캡쳐할 디바이스 설정이 모두 완료되었다면, 본격적으로 패킷 캡쳐를 하기 위한 디스크립터를 받아와야 한다. 그 역할을 하는 함수가 바로 pcap_open_live 함수이다.




pcap_open_live 


1
pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf);
cs


위의 함수를 통해 pcap_t 구조체의 포인터로 Packet capture descriptor(PCD)을 반환한다. 인자를 하나씩 확인해보면 device를 통해 어떤 디스크립터를 가져와야할지 판단하며, snaplen을 통해 받아들이는 최대 패킷 길이를 설정해줄 수 있으며, promisc를 통해 promiscuous 모드를 설정한다. 0일 경우 자신과 관련된 패킷만, 1일경우 모두 받아들인다. to_ms는 시간초과 기준을 설정해주기 위한 변수로, 밀리세컨드 단위이다. 성공시 디스크립터를 반환하고, 실패시 NULL을 반환하며, errbuf를 채운다




pcap_fileno


1
int pcap_fileno(pcap_t *p);
cs


pcap_open_live가 반환한 값을 %d 포맷스트링을 이용하여 출력하게 되면 오류가 뜬다. pcap_fileno를 통해 pcap_t 구조체의 디스크립터를 출력할 수 있다.




pcap_close


1
void pcap_close(pcap_t *p);
cs


해당 pcap_t 변수와 관련된 파일을 닫는다. 디스크립터 사용이 끝난 후에 닫아주는 함수이다.






Example


패킷 캡쳐 디스크립터를 받게되면 디바이스 목록은 더이상 필요하지 않으므로 pcap_freealldevs 로 메모리 할당을 해제해주는 것이 좋다.


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include<stdio.h>
#include<pcap.h>
#include<arpa/inet.h>
 
int main(){
    pcap_if_t *alldevsp;
    pcap_if_t *d;
 
    char errbuf[PCAP_ERRBUF_SIZE];
    
    bpf_u_int32 netp;
    bpf_u_int32 maskp;
    int ret,i=1;
    struct in_addr addr;
    char *net;
 
    pcap_t *pcd;
 
    //int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf);
    printf("====== pcap_findalldevs ======\n");
    ret = pcap_findalldevs(&alldevsp,errbuf);
    if(ret == -1){
        printf("pcap_findalldev ERR : %s\n",errbuf);
        return -1;
    }
    
    for(d=alldevsp; d; d=d->next){
        printf("%d. %s", i++, d->name);
        if(d->description){
            printf("(%s)\n",d->description);
        }else{
            printf("(None)\n");
        }
    }
 
    printf("Select device number > ");
    scanf("%d",&i);
    i--;
 
    for(d=alldevsp;i>0;d=d->next, i--);
 
 
    //int pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf);
    printf("====== pcap_lookupnet ======\n");
    ret = pcap_lookupnet(d->name, &netp, &maskp, errbuf);
    if(ret==-1){
        printf("pcap_lookupnet ERR : %s\n",errbuf);
        pcap_freealldevs(alldevsp);
        return -1;
    }
    printf("dev   : %s\n",d->name);
    addr.s_addr = netp;
    net = inet_ntoa(addr);
    if(net ==NULL){
        printf("inet_ntoa ERR");
        pcap_freealldevs(alldevsp);
        return -1;
    }
    printf("netp  : %s\n",net);
    addr.s_addr = maskp;
    net = inet_ntoa(addr);
    if(net==NULL){
        printf("inet_ntoa ERR");
        pcap_freealldevs(alldevsp);
        return -1;
    }
    printf("maskp : %s\n",net);
 
    //pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf);
    printf("====== pcap_open_live ======\n");
    pcd = pcap_open_live(d->name, 10000011000, errbuf);
    if(pcd==NULL){
        printf("pcap_open_live ERR : %s\n",errbuf);
        pcap_freealldevs(alldevsp);
        return -1;
    }
    printf("File Descriptor : %d\n",pcap_fileno(pcd));
 
    pcap_freealldevs(alldevsp);
    pcap_close(pcd);
 
    return 0;
}
 
cs





실행결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@g0pher-virtual-machine:/home/g0pher/sniff_tcpdump# ./sniffer 
====== pcap_findalldevs ======
1. ens33(None)
2. any(Pseudo-device that captures on all interfaces)
3. lo(None)
4. nflog(Linux netfilter log (NFLOG) interface)
5. nfqueue(Linux netfilter queue (NFQUEUE) interface)
6. usbmon1(USB bus number 1)
7. usbmon2(USB bus number 2)
Select device number > 1
====== pcap_lookupnet ======
dev   : ens33
netp  : 192.168.35.0
maskp : 255.255.255.0
====== pcap_open_live ======
File Descriptor : 3
cs