source: trunk/ETSI-Testsuites/ETSI_auto_IOT/adapter/src/Capture/PCAPCapture.cpp @ 27

Last change on this file since 27 was 22, checked in by rings, 14 years ago
  • Property svn:executable set to *
File size: 5.6 KB
Line 
1/**
2 * @file PCAPCapture.cpp
3 * @author Tomas Urban
4 * @version 0.4
5 * @date 23/07/2009
6 */
7#include "PCAPCapture.h"
8#include <boost/thread/thread.hpp>
9#include <boost/tokenizer.hpp>
10#include "Logger/Logger.h"
11
12PCAPCapture::PCAPCapture() :
13        m_fp(NULL),
14        m_nHandleCount(0),
15        m_bRunning(false),
16        m_dumpFiles(0),
17        m_threadRunning(0)
18{
19}
20
21PCAPCapture::~PCAPCapture()
22{
23        CloseDevice(); 
24}
25
26pcap_t * PCAPCapture::OpenPcapSource(const std::string sSource)
27{
28        char errbuf[PCAP_ERRBUF_SIZE];
29        return pcap_open(sSource.c_str(), SNAP_LEN, PCAP_OPENFLAG_PROMISCUOUS,
30                1000, NULL, errbuf);
31}
32
33void PCAPCapture::CloseDevice()
34{
35        if (m_fp != NULL)
36        {
37                StopCapture();
38                CloseCaptureFile();
39                for (int i = 0; i < m_nHandleCount; i++)
40                        pcap_close(m_fp[i]);
41                delete m_fp;
42                m_fp = NULL;
43                m_threadRunning = NULL;
44                m_nHandleCount = 0;
45        }
46}
47void PCAPCapture::SetPcapHandles(pcap_t ** srcBuf, int nLen)
48{
49        CloseDevice();
50        m_fp = new pcap_t*[nLen];
51        m_nHandleCount = nLen;
52        memcpy(m_fp, srcBuf, nLen * sizeof(pcap_t*));
53        m_threadRunning = new bool[nLen];
54        memset(m_threadRunning, 0, nLen * sizeof(bool));
55}
56
57void PCAPCapture::DispatcherHandler(u_char *temp1,
58                        const struct pcap_pkthdr *header, const u_char *pkt_data)
59{       
60        PCAPCapture::CapturingThread * pThread = reinterpret_cast<PCAPCapture::CapturingThread*>(temp1);
61        PCAPCapture * pObj = pThread->m_pCapture;
62        int nIndex = pThread->m_nHandleIndex;
63        if (pObj->m_dumpFiles)
64        {
65                boost::mutex::scoped_lock lock(pObj->m_mutex);
66                pcap_dump(reinterpret_cast <u_char*>(pObj->m_dumpFiles[nIndex]), header, pkt_data);
67        }
68        CapturedData cd;
69        cd.SetData(header->caplen, reinterpret_cast <const char*> (pkt_data));
70        cd.SetTimestamp(header->ts);
71        if (pObj->m_fp)
72                pObj->ProcessCapturedData(&cd);
73}
74
75PCAPCapture::CapturingThread::CapturingThread(PCAPCapture * pCapture, int nHandleIndex) :
76        m_pCapture(pCapture),
77        m_nHandleIndex(nHandleIndex)
78{
79}
80
81void PCAPCapture::CapturingThread::operator()()
82{
83        std::string s = "Packet capture started";
84        std::string s2 = "";
85        if (m_pCapture->m_nHandleCount > 1)
86        {
87                s2 = " (source #";
88                s2 += boost::lexical_cast<std::string>(m_nHandleIndex + 1);
89                s2 += ")";
90                s += s2;
91        }
92        Logger::Instance().LogDebug(s);
93
94        pcap_loop(m_pCapture->m_fp[m_nHandleIndex], 0, PCAPCapture::DispatcherHandler,
95                reinterpret_cast <u_char*> (this));
96
97        s = "Packet capture ended";
98        s += s2;
99        Logger::Instance().LogDebug(s);
100        {
101                boost::mutex::scoped_lock(m_pCapture->m_mutex);
102                m_pCapture->m_threadRunning[m_nHandleIndex] = false;
103                if (m_pCapture->m_bRunning)
104                        m_pCapture->m_threadClosed.notify_one();
105        }
106}
107
108bool PCAPCapture::StartCapture()
109{
110        if (m_bRunning)
111                return true;
112        m_bRunning = true;
113        if (m_fp)               
114        {
115                for (int i = 0; i < m_nHandleCount; i++)
116                {
117                        m_threadRunning[i] = true;
118                        boost::thread thread(CapturingThread(this, i));
119                }
120        }
121        return true;
122}
123
124bool PCAPCapture::StopCapture()
125{       
126        if (!m_bRunning)
127                return true;
128        m_bRunning = false;
129        if (m_fp)
130        {
131                for (int i = 0; i < m_nHandleCount; i++)
132                {
133                        boost::mutex::scoped_lock cond(m_mutex);
134                        if (m_threadRunning[i])
135                        {
136                                pcap_breakloop(m_fp[i]);
137                                m_threadClosed.wait(cond);
138                        }
139                }
140        }
141        return true;
142}
143
144bool PCAPCapture::SetFilter(const std::string sFilter)
145{
146        if (!m_fp)
147        {
148                Logger::Instance().LogWarning("Cannot apply filter; the capture device is not open");
149                return false;
150        }
151       
152        std::string sFormattedFilter = sFilter;
153
154        // compile the filter           
155        struct bpf_program fcode;
156        std::string s = "Setting PCAP filter (";
157        s += sFormattedFilter;
158        s += ")...";
159        Logger::Instance().LogDebug(s);
160        bool bRes = true;
161        for (int i = 0; i < m_nHandleCount; i++)
162        {               
163                if (m_nHandleCount > 1)
164                {
165                        s = "Applying filter to source #";
166                        s += boost::lexical_cast<std::string>(i + 1);
167                        s += "...";
168                        Logger::Instance().LogDebug(s);
169                }                               
170                if (pcap_compile(m_fp[i], &fcode, sFormattedFilter.c_str(), 1, 0) < 0)
171                {
172                        Logger::Instance().LogError("Error compiling packet filter");
173                        bRes = false;
174                        continue;
175                }
176           
177                //set the filter
178                int nRes = pcap_setfilter(m_fp[i], &fcode);
179                pcap_freecode(&fcode);
180                if (nRes < 0)
181                {
182                        Logger::Instance().LogError("Error setting packet filter");
183                        bRes = false;
184                        continue;
185                }               
186                Logger::Instance().LogInfo("Filter applied successfully");
187        }
188        Logger::Instance().LogDebug("PCAP filter ready");
189        return bRes;
190}
191
192void PCAPCapture::CloseCaptureFile()
193{
194        if (m_dumpFiles)
195        {
196                boost::mutex::scoped_lock lock(m_mutex);
197                for (int i = 0; i < m_nHandleCount; i++)
198                        pcap_dump_close(m_dumpFiles[i]);
199                delete m_dumpFiles;
200                m_dumpFiles = 0;
201        }
202}
203
204bool PCAPCapture::InitCaptureFile(const std::string sFile)
205{
206        if (!m_nHandleCount)
207                return false;
208        CloseCaptureFile();
209        bool bRes = true;
210        if (sFile.length() > 0)
211        {
212                boost::mutex::scoped_lock lock(m_mutex);
213                m_dumpFiles = new pcap_dumper_t * [m_nHandleCount];
214                memset(m_dumpFiles, 0, sizeof(pcap_dumper_t*) * m_nHandleCount);
215
216                std::string sName = sFile;
217                std::string sExt = "";
218                if (m_nHandleCount > 1)
219                {
220                        size_t nSize = sFile.find_last_of('.');
221                        if (nSize < sFile.length())
222                        {
223                                sName = sFile.substr(0, nSize);
224                                sExt = sFile.substr(nSize);
225                        }
226                }
227               
228                for (int i = 0; i < m_nHandleCount; i++)
229                {
230                        std::string sTmp = sFile;
231                        if (m_nHandleCount > 1)
232                        {
233                                sTmp = sName;
234                                sTmp += boost::lexical_cast<std::string>(i + 1);
235                                sTmp += sExt;
236                        }
237                        m_dumpFiles[i] = pcap_dump_open(m_fp[i], sTmp.c_str());
238                        if (!m_dumpFiles[i])
239                        {
240                                std::string s = "Failed to create dump file \"";
241                                s += sTmp;
242                                s += "\"";
243                                Logger::Instance().LogError(s);
244                                return false;
245                        }
246                }
247                Logger::Instance().LogDebug("PCAP dump file successfully initialized");
248        }
249        else
250                Logger::Instance().LogDebug("Dump file disabled");
251        return true;;
252}
253
254
255
Note: See TracBrowser for help on using the repository browser.