libpcaptest.cpp

guy, 02/13/2010 08:51 AM

Download (4.6 KB)

 
1
#include <iostream>
2
#include <stdio.h>
3
#include <string>
4
#include <vector>
5
#include <errno.h>
6
#include <sys/ioctl.h>
7
#include <sys/types.h>
8
#include <sys/time.h>
9
#include <net/bpf.h>
10
#include <pcap.h>
11

    
12
pcap_t* create(const std::string& name, 
13
                           const std::string& pcapFilter, 
14
                           uint32_t snapLen, bool promisc);
15
bool capture(pcap_t * pcapSession);
16
void close(pcap_t* pcapSession);
17

    
18

    
19
int main(int argc, char** argv)
20
{
21
        if (argc != 3)
22
        {
23
                std::cerr << "Usage: libpcaptest <interface> <filter>" 
24
               << std::endl;
25
                return 1;
26
        }
27
        
28
        std::string name(argv[1]), filter(argv[2]);
29
        std::cout << "Capturing from '" << name << " with filter "
30
       << filter << std::endl;
31
         
32
        pcap_t * pcapSession = create(name, filter, 128, true);
33
        capture(pcapSession);
34
        close(pcapSession);
35
        return 0;
36
}
37

    
38
/**
39
This is the callback
40
**/
41
void test_pcap_handler(u_char* user, const struct pcap_pkthdr* header, 
42
                                           const u_char* pkt_data)
43
{
44
        std::cout << "Packet captured" << std::endl;
45
}
46

    
47
/**
48
Temporary used since on Windows they forgot to sign as 'const char*'
49
the filter string provided to pcap_compile...
50
**/
51
void duplicateFilterString(const std::string& pcapFilter, 
52
    std::vector<char>& dupFilter)
53
{
54
        dupFilter.clear();
55
        dupFilter.resize(pcapFilter.size()+1, 0);
56
        
57
        for (uint32_t i=0; i<pcapFilter.size(); ++i)
58
                dupFilter[i] = pcapFilter[i];
59
}
60

    
61
void close(pcap_t* pcapSession)
62
{
63
        if (pcapSession)
64
        {
65
                pcap_close(pcapSession);
66
        }
67
}
68
                
69
                
70
pcap_t* create(const std::string& name, 
71
                           const std::string& pcapFilter, 
72
                           uint32_t snapLen, bool promisc)
73
{
74
        char errbuf[PCAP_ERRBUF_SIZE];
75
        pcap_t* pcapSession;
76
                
77
        if ((pcapSession = pcap_open_live(name.c_str(), 
78
             snapLen, promisc ? 1 : 0, 1000,        errbuf)) == NULL)
79
        {
80
                std::cerr << "Failed pcap_open_live because <"
81
                <<errbuf<<">" << std::endl;
82
                return NULL;
83
        }
84
                        
85
        // compile the filter if it's been supplied or snapLen is provided
86
        if (pcapFilter.empty()==false || snapLen<65535)
87
        {
88
                // get netmask
89
                bpf_u_int32 pcapNetaddr, pcapMask;
90
                pcap_lookupnet(name.c_str(), &pcapNetaddr, &pcapMask, errbuf);
91
                                
92
                struct bpf_program pcapFilterProgram;                
93
                std::vector<char> filterDup;
94
                duplicateFilterString(pcapFilter, filterDup);
95
                                
96
                if (pcap_compile(pcapSession, &pcapFilterProgram, 
97
                    &filterDup[0], 1, pcapMask) == -1) 
98
                {
99
                        std::string error = pcap_geterr(pcapSession);
100
                        pcap_close(pcapSession);
101
                        std::cerr << "Failed pcap_compile because <"
102
                       <<errbuf<<">" << std::endl;
103
                        return NULL;
104
                }        
105
                                
106
                if (pcap_setfilter(pcapSession, &pcapFilterProgram) == -1)
107
                {
108
                        std::string error = pcap_geterr(pcapSession);
109
                        pcap_freecode(&pcapFilterProgram);
110
                        pcap_close(pcapSession);
111
                        std::cerr << "Failed pcap_setfilter because <"
112
                       <<errbuf<<">" << std::endl;
113
                        return NULL;
114
                }
115
                                
116
                pcap_freecode(&pcapFilterProgram);
117
        }
118
                        
119
        // set session in non blocking mode
120
        if (pcap_setnonblock(pcapSession, 1, errbuf)!=0)
121
        {
122
                pcap_close(pcapSession);
123
                std::cerr << "Failed pcap_setnonblock because <"
124
               <<errbuf<<">" << std::endl;
125
                return NULL;
126
        }
127

    
128
        /*
129
                Enable this for immediate delivery of packets through callback.
130
                
131
        uint32_t v = 1;
132
        if (ioctl(pcap_fileno(pcapSession), BIOCIMMEDIATE, &v) < 0) {
133
                pcap_close(pcapSession);
134
                std::cerr << "Failed ioctl BIOCIMMEDIATE" << std::endl;
135
                return NULL;
136
        }
137
        */
138
        
139
        int dlt;
140
        const char *dlt_name;
141
        dlt = pcap_datalink(pcapSession);
142
        dlt_name = pcap_datalink_val_to_name(dlt);
143
        if (dlt_name == NULL) {
144
                (void)fprintf(stderr, 
145
"listening on %s, link-type %u, capture size %u bytes\n",
146
                                          name.c_str(), dlt, snapLen);
147
        } else {
148
                (void)fprintf(stderr, 
149
"listening on %s, link-type %s (%s), capture size %u bytes\n",
150
                                          name.c_str(), dlt_name,
151
                                          pcap_datalink_val_to_description(dlt), snapLen);
152
        }
153
                        
154
        return pcapSession;
155
}
156
                
157
bool capture(pcap_t * pcapSession)
158
{
159
        struct pcap_stat pcapStats;
160
                
161
        while (true)
162
        {
163
                int32_t ret = pcap_dispatch(pcapSession, 100, 
164
                                                                test_pcap_handler, (u_char*)NULL);
165
                std::cout << "Read " << ret << " packets" << std::endl;
166
                if (pcap_stats(pcapSession, &pcapStats) != 0)
167
                {
168
                                std::string error = pcap_geterr(pcapSession);
169
                                std::cerr << "Failed pcap_setnonblock because <"
170
                               <<error<<">" << std::endl;
171
                                return false;
172
                }
173
                std::cout << "ReceivedPackets " << pcapStats.ps_recv << 
174
                                " DroppedPackets " << pcapStats.ps_drop << 
175
                                " I/F DroppedPackets " << pcapStats.ps_ifdrop << std::endl;
176
                                
177
                                
178
                if (ret==-1)
179
                {
180
                        std::string error = pcap_geterr(pcapSession);
181
                        std::cerr << "Failed pcap_dispatch because <"<<error<<">" << std::endl;
182
                        return NULL;
183
                }
184
                                
185
                                
186
                sleep(5);
187
        } 
188
        return true;
189
}