본문으로 바로가기

Packet sniffer develop #pcap_loop

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

패킷 캡쳐 디스크립터까지 받아내었다면, 실제로 패킷을 받아보는 코딩을 해보자




pcap_loop


1
int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
cs


위 함수를 통해서 패킷을 받아들일 수 있다. 인자를 살펴보면 p를 통해 PCD(Packet Capture Descriptor)를 넘겨주는것을 알 수 있다. cnt 변수를 통해서 캡쳐할 패킷 수를 지정해주고, 패킷을 받을 때 호출할 callback 함수를 지정해준다. user는 패킷 데이터 포인터라고 한다(아직 어떤 변수인지 정확히 모르겠다)



pcap_handler


1
typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
cs


위를 통해 callback 함수를 호출할 때 3개의 파라미터를 넘겨주는 것을 알 수 있다. user 변수는 pcap_loop함수를 호출할 때 넘겨주었던 user 변수를 넘겨주는듯 하다. if문으로 확인해보니 NULL이었다. 같은 자료형인 u_char bytes상수는 실제 패킷의 데이터를 뜻하는것 같다. h변수는 pcap_pkthdr이라는 구조체로 이루어진 상수이다. 이 구조체는 아래와 같은 변수들로 이루어져있다.


1
2
3
4
5
struct pcap_pkthdr {
    struct timeval ts;
    bpf_u_int32 caplen;
    bpf_u_int32 len;
};
cs


타임스탬프 변수인 ts와 현재 위치까지의 길이인 caplen, 패킷의 길이를 담는 len 변수로 이루어져있다.







Example


아래코드에서는 pcap_loop 함수의 cnt 인자를 5로 주었으므로 callback함수가 5번 호출되어야 한다.




소스코드

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
85
86
87
88
89
90
91
92
93
94
95
96
97
#include<stdio.h>
#include<pcap.h>
#include<arpa/inet.h>
 
void callback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
 
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;//Packet Capture Descriptor
 
    //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);
 
    //int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
    printf("====== pcap_loop ======\n");
    pcap_loop(pcd, 5, callback, NULL);
    pcap_close(pcd);
    return 0;
}
 
void callback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes){
    int i=0;
    printf("\ncallback function successfully called!!\n");
    printf("h->caplen : %d\n", h->caplen);
    printf("h->len    : %d\n", h->len);
    for(i=0; i<h->len; i++){
        printf("%x",*(bytes+i));
    }
}
cs





실행화면

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
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
====== pcap_loop ======
 
callback function successfully called!!
h->caplen : 122
h->len    : 122
05056c0010c29aad3b80451006c58a14004061a8c0a82381c0a8231016103d2e955cc68a5b650180fbc83100000307daa3b4-
callback function successfully called!!
h->caplen : 60
h->len    : 60
0c29aad3b05056c001804500287a2a400806b8d2c0a8231c0a82381103016c68a5b6d2e95a050100fd37d00000000
callback function successfully called!!
h->caplen : 90
h->len    : 90
05056c0010c29aad3b80451004c58a24004061a27c0a82381c0a8231016103d2e95a0c68a5b650180fbc8110000010bf944d-
callback function successfully called!!
h->caplen : 122
h->len    : 122
05056c0010c29aad3b80451006c58a34004061a6c0a82381c0a8231016103d2e95c4c68a5b650180fbc8310000030452566b-
callback function successfully called!!
h->caplen : 60
h->len    : 60
0c29aad3b05056c001804500287a2b400806b8d1c0a8231c0a82381103016c68a5b6d2e96850100fd31500000000
cs