1 /* Copyright (C) 2007-2019 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Live pcap packet acquisition support
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "decode.h"
29 #include "packet-queue.h"
30 #include "threads.h"
31 #include "threadvars.h"
32 #include "tm-queuehandlers.h"
33 #include "tm-threads.h"
34 #include "source-pcap.h"
35 #include "conf.h"
36 #include "util-debug.h"
37 #include "util-error.h"
38 #include "util-privs.h"
39 #include "util-device.h"
40 #include "util-optimize.h"
41 #include "util-checksum.h"
42 #include "util-ioctl.h"
43 #include "tmqh-packetpool.h"
44 
45 #define PCAP_STATE_DOWN 0
46 #define PCAP_STATE_UP 1
47 
48 #define PCAP_RECONNECT_TIMEOUT 500000
49 
50 /**
51  * \brief 64bit pcap stats counters.
52  *
53  * libpcap only supports 32bit counters. They will eventually wrap around.
54  *
55  * Keep track of libpcap counters as 64bit counters to keep on counting even
56  * if libpcap's 32bit counters wrap around.
57  * Requires pcap_stats() to be called before 32bit stats wrap around twice,
58  * which we do.
59  */
60 typedef struct PcapStats64_ {
61     uint64_t ps_recv;
62     uint64_t ps_drop;
63     uint64_t ps_ifdrop;
64 } PcapStats64;
65 
66 /**
67  * \brief Structure to hold thread specific variables.
68  */
69 typedef struct PcapThreadVars_
70 {
71     /* thread specific handle */
72     pcap_t *pcap_handle;
73     /* handle state */
74     unsigned char pcap_state;
75     /* thread specific bpf */
76     struct bpf_program filter;
77     /* ptr to string from config */
78     const char *bpf_filter;
79 
80     time_t last_stats_dump;
81 
82     /* data link type for the thread */
83     int datalink;
84 
85     /* counters */
86     uint64_t pkts;
87     uint64_t bytes;
88 
89     uint16_t capture_kernel_packets;
90     uint16_t capture_kernel_drops;
91     uint16_t capture_kernel_ifdrops;
92 
93     ThreadVars *tv;
94     TmSlot *slot;
95 
96     /** callback result -- set if one of the thread module failed. */
97     int cb_result;
98 
99     /* pcap buffer size */
100     int pcap_buffer_size;
101     int pcap_snaplen;
102 
103     ChecksumValidationMode checksum_mode;
104 
105     LiveDevice *livedev;
106 
107     PcapStats64 last_stats64;
108 } PcapThreadVars;
109 
110 static TmEcode ReceivePcapThreadInit(ThreadVars *, const void *, void **);
111 static void ReceivePcapThreadExitStats(ThreadVars *, void *);
112 static TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot);
113 static TmEcode ReceivePcapBreakLoop(ThreadVars *tv, void *data);
114 
115 static TmEcode DecodePcapThreadInit(ThreadVars *, const void *, void **);
116 static TmEcode DecodePcapThreadDeinit(ThreadVars *tv, void *data);
117 static TmEcode DecodePcap(ThreadVars *, Packet *, void *);
118 
119 #ifdef UNITTESTS
120 static void SourcePcapRegisterTests(void);
121 #endif
122 
123 /** protect pcap_compile and pcap_setfilter, as they are not thread safe:
124  *  http://seclists.org/tcpdump/2009/q1/62 */
125 static SCMutex pcap_bpf_compile_lock = SCMUTEX_INITIALIZER;
126 
127 /**
128  * \brief Registration Function for ReceivePcap.
129  */
TmModuleReceivePcapRegister(void)130 void TmModuleReceivePcapRegister (void)
131 {
132     tmm_modules[TMM_RECEIVEPCAP].name = "ReceivePcap";
133     tmm_modules[TMM_RECEIVEPCAP].ThreadInit = ReceivePcapThreadInit;
134     tmm_modules[TMM_RECEIVEPCAP].PktAcqLoop = ReceivePcapLoop;
135     tmm_modules[TMM_RECEIVEPCAP].PktAcqBreakLoop = ReceivePcapBreakLoop;
136     tmm_modules[TMM_RECEIVEPCAP].ThreadExitPrintStats = ReceivePcapThreadExitStats;
137     tmm_modules[TMM_RECEIVEPCAP].cap_flags = SC_CAP_NET_RAW;
138     tmm_modules[TMM_RECEIVEPCAP].flags = TM_FLAG_RECEIVE_TM;
139 #ifdef UNITTESTS
140     tmm_modules[TMM_RECEIVEPCAP].RegisterTests = SourcePcapRegisterTests;
141 #endif
142 }
143 
144 /**
145  * \brief Registration Function for DecodePcap.
146  */
TmModuleDecodePcapRegister(void)147 void TmModuleDecodePcapRegister (void)
148 {
149     tmm_modules[TMM_DECODEPCAP].name = "DecodePcap";
150     tmm_modules[TMM_DECODEPCAP].ThreadInit = DecodePcapThreadInit;
151     tmm_modules[TMM_DECODEPCAP].Func = DecodePcap;
152     tmm_modules[TMM_DECODEPCAP].ThreadDeinit = DecodePcapThreadDeinit;
153     tmm_modules[TMM_DECODEPCAP].flags = TM_FLAG_DECODE_TM;
154 }
155 
156 /**
157  * \brief Update 64 bit |last| value from |current32| value taking one
158  * wrap-around into account.
159  */
UpdatePcapStatsValue64(uint64_t * last,uint32_t current32)160 static inline void UpdatePcapStatsValue64(uint64_t *last, uint32_t current32)
161 {
162     /* uint64_t -> uint32_t is defined behaviour. It slices lower 32bits. */
163     uint32_t last32 = *last;
164 
165     /* Branchless code as wrap-around is defined for unsigned */
166     *last += (uint32_t)(current32 - last32);
167 
168     /* Same calculation as:
169     if (likely(current32 >= last32)) {
170         *last += current32 - last32;
171     } else {
172         *last += (1ull << 32) + current32 - last32;
173     }
174     */
175 }
176 
177 /**
178  * \brief Update 64 bit |last| stat values with values from |current|
179  * 32 bit pcap_stat.
180  */
UpdatePcapStats64(PcapStats64 * last,const struct pcap_stat * current)181 static inline void UpdatePcapStats64(
182         PcapStats64 *last, const struct pcap_stat *current)
183 {
184     UpdatePcapStatsValue64(&last->ps_recv, current->ps_recv);
185     UpdatePcapStatsValue64(&last->ps_drop, current->ps_drop);
186     UpdatePcapStatsValue64(&last->ps_ifdrop, current->ps_ifdrop);
187 }
188 
PcapDumpCounters(PcapThreadVars * ptv)189 static inline void PcapDumpCounters(PcapThreadVars *ptv)
190 {
191     struct pcap_stat pcap_s;
192     if (likely((pcap_stats(ptv->pcap_handle, &pcap_s) >= 0))) {
193         UpdatePcapStats64(&ptv->last_stats64, &pcap_s);
194 
195         StatsSetUI64(ptv->tv, ptv->capture_kernel_packets,
196                 ptv->last_stats64.ps_recv);
197         StatsSetUI64(
198                 ptv->tv, ptv->capture_kernel_drops, ptv->last_stats64.ps_drop);
199         (void)SC_ATOMIC_SET(ptv->livedev->drop, ptv->last_stats64.ps_drop);
200         StatsSetUI64(ptv->tv, ptv->capture_kernel_ifdrops,
201                 ptv->last_stats64.ps_ifdrop);
202     }
203 }
204 
PcapTryReopen(PcapThreadVars * ptv)205 static int PcapTryReopen(PcapThreadVars *ptv)
206 {
207     ptv->pcap_state = PCAP_STATE_DOWN;
208 
209     int pcap_activate_r = pcap_activate(ptv->pcap_handle);
210     if (pcap_activate_r != 0) {
211         return pcap_activate_r;
212     }
213 
214     /* set bpf filter if we have one */
215     if (ptv->bpf_filter != NULL) {
216         if (pcap_compile(ptv->pcap_handle, &ptv->filter,
217                     (char *)ptv->bpf_filter, 1, 0) < 0)
218         {
219             SCLogError(SC_ERR_BPF, "bpf compilation error %s",
220                     pcap_geterr(ptv->pcap_handle));
221             return -1;
222         }
223 
224         if (pcap_setfilter(ptv->pcap_handle, &ptv->filter) < 0) {
225             SCLogError(SC_ERR_BPF, "could not set bpf filter %s",
226                     pcap_geterr(ptv->pcap_handle));
227             return -1;
228         }
229     }
230 
231     SCLogInfo("Recovering interface listening");
232     ptv->pcap_state = PCAP_STATE_UP;
233     return 0;
234 }
235 
PcapCallbackLoop(char * user,struct pcap_pkthdr * h,u_char * pkt)236 static void PcapCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt)
237 {
238     SCEnter();
239 
240     PcapThreadVars *ptv = (PcapThreadVars *)user;
241     Packet *p = PacketGetFromQueueOrAlloc();
242     struct timeval current_time;
243 
244     if (unlikely(p == NULL)) {
245         SCReturn;
246     }
247 
248     PKT_SET_SRC(p, PKT_SRC_WIRE);
249     p->ts.tv_sec = h->ts.tv_sec;
250     p->ts.tv_usec = h->ts.tv_usec;
251     SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
252     p->datalink = ptv->datalink;
253 
254     ptv->pkts++;
255     ptv->bytes += h->caplen;
256     (void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
257     p->livedev = ptv->livedev;
258 
259     if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
260         TmqhOutputPacketpool(ptv->tv, p);
261         SCReturn;
262     }
263 
264     switch (ptv->checksum_mode) {
265         case CHECKSUM_VALIDATION_AUTO:
266             if (ChecksumAutoModeCheck(ptv->pkts,
267                         SC_ATOMIC_GET(ptv->livedev->pkts),
268                         SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
269                 ptv->checksum_mode = CHECKSUM_VALIDATION_DISABLE;
270                 p->flags |= PKT_IGNORE_CHECKSUM;
271             }
272             break;
273         case CHECKSUM_VALIDATION_DISABLE:
274             p->flags |= PKT_IGNORE_CHECKSUM;
275             break;
276         default:
277             break;
278     }
279 
280     if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
281         pcap_breakloop(ptv->pcap_handle);
282         ptv->cb_result = TM_ECODE_FAILED;
283     }
284 
285     /* Trigger one dump of stats every second */
286     TimeGet(&current_time);
287     if (current_time.tv_sec != ptv->last_stats_dump) {
288         PcapDumpCounters(ptv);
289         ptv->last_stats_dump = current_time.tv_sec;
290     }
291 
292     SCReturn;
293 }
294 
295 #ifndef PCAP_ERROR_BREAK
296 #define PCAP_ERROR_BREAK -2
297 #endif
298 
299 /**
300  *  \brief Main PCAP reading Loop function
301  */
ReceivePcapLoop(ThreadVars * tv,void * data,void * slot)302 static TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot)
303 {
304     SCEnter();
305 
306     int packet_q_len = 64;
307     PcapThreadVars *ptv = (PcapThreadVars *)data;
308     TmSlot *s = (TmSlot *)slot;
309 
310     ptv->slot = s->slot_next;
311     ptv->cb_result = TM_ECODE_OK;
312 
313     while (1) {
314         if (suricata_ctl_flags & SURICATA_STOP) {
315             SCReturnInt(TM_ECODE_OK);
316         }
317 
318         /* make sure we have at least one packet in the packet pool, to prevent
319          * us from alloc'ing packets at line rate */
320         PacketPoolWait();
321 
322         int r = pcap_dispatch(ptv->pcap_handle, packet_q_len,
323                           (pcap_handler)PcapCallbackLoop, (u_char *)ptv);
324         if (unlikely(r == 0 || r == PCAP_ERROR_BREAK)) {
325             if (r == PCAP_ERROR_BREAK && ptv->cb_result == TM_ECODE_FAILED) {
326                 SCReturnInt(TM_ECODE_FAILED);
327             }
328             TmThreadsCaptureHandleTimeout(tv, NULL);
329         } else if (unlikely(r < 0)) {
330             int dbreak = 0;
331             SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s",
332                        r, pcap_geterr(ptv->pcap_handle));
333             do {
334                 usleep(PCAP_RECONNECT_TIMEOUT);
335                 if (suricata_ctl_flags != 0) {
336                     dbreak = 1;
337                     break;
338                 }
339                 r = PcapTryReopen(ptv);
340             } while (r < 0);
341             if (dbreak) {
342                 break;
343             }
344         } else if (ptv->cb_result == TM_ECODE_FAILED) {
345             SCLogError(SC_ERR_PCAP_DISPATCH, "Pcap callback PcapCallbackLoop failed");
346             SCReturnInt(TM_ECODE_FAILED);
347         }
348 
349         StatsSyncCountersIfSignalled(tv);
350     }
351 
352     PcapDumpCounters(ptv);
353     StatsSyncCountersIfSignalled(tv);
354     SCReturnInt(TM_ECODE_OK);
355 }
356 
357 /**
358  * \brief PCAP Break Loop function.
359  */
ReceivePcapBreakLoop(ThreadVars * tv,void * data)360 static TmEcode ReceivePcapBreakLoop(ThreadVars *tv, void *data)
361 {
362     SCEnter();
363     PcapThreadVars *ptv = (PcapThreadVars *)data;
364     if (ptv->pcap_handle == NULL) {
365         SCReturnInt(TM_ECODE_FAILED);
366     }
367     pcap_breakloop(ptv->pcap_handle);
368     SCReturnInt(TM_ECODE_OK);
369 }
370 
371 /**
372  * \brief Init function for ReceivePcap.
373  *
374  * This is a setup function for recieving packets
375  * via libpcap. There are two versions of this function
376  * depending on the major version of libpcap used.
377  * For versions prior to 1.x we use open_pcap_live,
378  * for versions 1.x and greater we use pcap_create + pcap_activate.
379  *
380  * \param tv pointer to ThreadVars
381  * \param initdata pointer to the interface passed from the user
382  * \param data pointer gets populated with PcapThreadVars
383  *
384  * \todo Create a general pcap setup function.
385  */
ReceivePcapThreadInit(ThreadVars * tv,const void * initdata,void ** data)386 static TmEcode ReceivePcapThreadInit(ThreadVars *tv, const void *initdata, void **data)
387 {
388     SCEnter();
389     PcapIfaceConfig *pcapconfig = (PcapIfaceConfig *)initdata;
390 
391     if (initdata == NULL) {
392         SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL");
393         SCReturnInt(TM_ECODE_FAILED);
394     }
395 
396     PcapThreadVars *ptv = SCCalloc(1, sizeof(PcapThreadVars));
397     if (unlikely(ptv == NULL)) {
398         pcapconfig->DerefFunc(pcapconfig);
399         SCReturnInt(TM_ECODE_FAILED);
400     }
401 
402     ptv->tv = tv;
403 
404     ptv->livedev = LiveGetDevice(pcapconfig->iface);
405     if (ptv->livedev == NULL) {
406         SCLogError(SC_ERR_INVALID_VALUE, "unable to find Live device");
407         SCFree(ptv);
408         SCReturnInt(TM_ECODE_FAILED);
409     }
410     SCLogInfo("using interface %s", (char *)pcapconfig->iface);
411 
412     if (LiveGetOffload() == 0) {
413         (void)GetIfaceOffloading((char *)pcapconfig->iface, 1, 1);
414     } else {
415         DisableIfaceOffloading(ptv->livedev, 1, 1);
416     }
417 
418     ptv->checksum_mode = pcapconfig->checksum_mode;
419     if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
420         SCLogInfo("running in 'auto' checksum mode. Detection of interface "
421                 "state will require " xstr(CHECKSUM_SAMPLE_COUNT) " packets");
422     }
423 
424     char errbuf[PCAP_ERRBUF_SIZE];
425     ptv->pcap_handle = pcap_create((char *)pcapconfig->iface, errbuf);
426     if (ptv->pcap_handle == NULL) {
427         if (strlen(errbuf)) {
428             SCLogError(SC_ERR_PCAP_CREATE, "could not create a new "
429                     "pcap handler for %s, error %s",
430                     (char *)pcapconfig->iface, errbuf);
431         } else {
432             SCLogError(SC_ERR_PCAP_CREATE, "could not create a new "
433                     "pcap handler for %s",
434                     (char *)pcapconfig->iface);
435         }
436         SCFree(ptv);
437         pcapconfig->DerefFunc(pcapconfig);
438         SCReturnInt(TM_ECODE_FAILED);
439     }
440 
441     if (pcapconfig->snaplen == 0) {
442         /* We set snaplen if we can get the MTU */
443         ptv->pcap_snaplen = GetIfaceMaxPacketSize(pcapconfig->iface);
444     } else {
445         ptv->pcap_snaplen = pcapconfig->snaplen;
446     }
447     if (ptv->pcap_snaplen > 0) {
448         /* set Snaplen. Must be called before pcap_activate */
449         int pcap_set_snaplen_r = pcap_set_snaplen(ptv->pcap_handle, ptv->pcap_snaplen);
450         if (pcap_set_snaplen_r != 0) {
451             SCLogError(SC_ERR_PCAP_SET_SNAPLEN, "could not set snaplen, "
452                     "error: %s", pcap_geterr(ptv->pcap_handle));
453             SCFree(ptv);
454             pcapconfig->DerefFunc(pcapconfig);
455             SCReturnInt(TM_ECODE_FAILED);
456         }
457         SCLogInfo("Set snaplen to %d for '%s'", ptv->pcap_snaplen,
458                   pcapconfig->iface);
459     }
460 
461     /* set Promisc, and Timeout. Must be called before pcap_activate */
462     int pcap_set_promisc_r = pcap_set_promisc(ptv->pcap_handle, pcapconfig->promisc);
463     if (pcap_set_promisc_r != 0) {
464         SCLogError(SC_ERR_PCAP_SET_PROMISC, "could not set promisc mode, "
465                 "error %s", pcap_geterr(ptv->pcap_handle));
466         SCFree(ptv);
467         pcapconfig->DerefFunc(pcapconfig);
468         SCReturnInt(TM_ECODE_FAILED);
469     }
470 
471     int pcap_set_timeout_r = pcap_set_timeout(ptv->pcap_handle, LIBPCAP_COPYWAIT);
472     if (pcap_set_timeout_r != 0) {
473         SCLogError(SC_ERR_PCAP_SET_TIMEOUT, "could not set timeout, "
474                 "error %s", pcap_geterr(ptv->pcap_handle));
475         SCFree(ptv);
476         pcapconfig->DerefFunc(pcapconfig);
477         SCReturnInt(TM_ECODE_FAILED);
478     }
479 #ifdef HAVE_PCAP_SET_BUFF
480     ptv->pcap_buffer_size = pcapconfig->buffer_size;
481     if (ptv->pcap_buffer_size > 0) {
482         SCLogInfo("going to use pcap buffer size of %" PRId32,
483                 ptv->pcap_buffer_size);
484 
485         int pcap_set_buffer_size_r = pcap_set_buffer_size(ptv->pcap_handle,
486                 ptv->pcap_buffer_size);
487         if (pcap_set_buffer_size_r != 0) {
488             SCLogError(SC_ERR_PCAP_SET_BUFF_SIZE, "could not set "
489                     "pcap buffer size, error %s", pcap_geterr(ptv->pcap_handle));
490             SCFree(ptv);
491             pcapconfig->DerefFunc(pcapconfig);
492             SCReturnInt(TM_ECODE_FAILED);
493         }
494     }
495 #endif /* HAVE_PCAP_SET_BUFF */
496 
497     /* activate the handle */
498     int pcap_activate_r = pcap_activate(ptv->pcap_handle);
499     if (pcap_activate_r != 0) {
500         SCLogError(SC_ERR_PCAP_ACTIVATE_HANDLE, "could not activate the "
501                 "pcap handler, error %s", pcap_geterr(ptv->pcap_handle));
502         SCFree(ptv);
503         pcapconfig->DerefFunc(pcapconfig);
504         SCReturnInt(TM_ECODE_FAILED);
505     }
506     ptv->pcap_state = PCAP_STATE_UP;
507 
508     /* set bpf filter if we have one */
509     if (pcapconfig->bpf_filter) {
510         SCMutexLock(&pcap_bpf_compile_lock);
511 
512         ptv->bpf_filter = pcapconfig->bpf_filter;
513 
514         if (pcap_compile(ptv->pcap_handle, &ptv->filter,
515                     (char *)ptv->bpf_filter, 1, 0) < 0)
516         {
517             SCLogError(SC_ERR_BPF, "bpf compilation error %s",
518                     pcap_geterr(ptv->pcap_handle));
519 
520             SCMutexUnlock(&pcap_bpf_compile_lock);
521             SCFree(ptv);
522             pcapconfig->DerefFunc(pcapconfig);
523             return TM_ECODE_FAILED;
524         }
525 
526         if (pcap_setfilter(ptv->pcap_handle, &ptv->filter) < 0) {
527             SCLogError(SC_ERR_BPF, "could not set bpf filter %s",
528                     pcap_geterr(ptv->pcap_handle));
529 
530             SCMutexUnlock(&pcap_bpf_compile_lock);
531             SCFree(ptv);
532             pcapconfig->DerefFunc(pcapconfig);
533             return TM_ECODE_FAILED;
534         }
535 
536         SCMutexUnlock(&pcap_bpf_compile_lock);
537     }
538 
539     /* no offloading supported at all */
540     (void)GetIfaceOffloading(pcapconfig->iface, 1, 1);
541 
542     ptv->datalink = pcap_datalink(ptv->pcap_handle);
543 
544     pcapconfig->DerefFunc(pcapconfig);
545 
546     ptv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets",
547             ptv->tv);
548     ptv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops",
549             ptv->tv);
550     ptv->capture_kernel_ifdrops = StatsRegisterCounter("capture.kernel_ifdrops",
551             ptv->tv);
552 
553     *data = (void *)ptv;
554     SCReturnInt(TM_ECODE_OK);
555 }
556 
557 /**
558  * \brief This function prints stats to the screen at exit.
559  * \param tv pointer to ThreadVars
560  * \param data pointer that gets cast into PcapThreadVars for ptv
561  */
ReceivePcapThreadExitStats(ThreadVars * tv,void * data)562 static void ReceivePcapThreadExitStats(ThreadVars *tv, void *data)
563 {
564     SCEnter();
565     PcapThreadVars *ptv = (PcapThreadVars *)data;
566     struct pcap_stat pcap_s;
567 
568     if (pcap_stats(ptv->pcap_handle, &pcap_s) < 0) {
569         SCLogError(SC_ERR_STAT,"(%s) Failed to get pcap_stats: %s",
570                 tv->name, pcap_geterr(ptv->pcap_handle));
571         SCLogInfo("(%s) Packets %" PRIu64 ", bytes %" PRIu64 "", tv->name,
572                 ptv->pkts, ptv->bytes);
573     } else {
574         SCLogInfo("(%s) Packets %" PRIu64 ", bytes %" PRIu64 "", tv->name,
575                 ptv->pkts, ptv->bytes);
576 
577         /* these numbers are not entirely accurate as ps_recv contains packets
578          * that are still waiting to be processed at exit. ps_drop only contains
579          * packets dropped by the driver and not any packets dropped by the interface.
580          * Additionally see http://tracker.icir.org/bro/ticket/18
581          *
582          * Note: ps_recv includes dropped packets and should be considered total.
583          * Unless we start to look at ps_ifdrop which isn't supported everywhere.
584          */
585         UpdatePcapStats64(&ptv->last_stats64, &pcap_s);
586         float drop_percent =
587                 likely(ptv->last_stats64.ps_recv > 0)
588                         ? (((float)ptv->last_stats64.ps_drop) /
589                                   (float)ptv->last_stats64.ps_recv) *
590                                   100
591                         : 0;
592         SCLogInfo("(%s) Pcap Total:%" PRIu64 " Recv:%" PRIu64 " Drop:%" PRIu64
593                   " (%02.1f%%).",
594                 tv->name, ptv->last_stats64.ps_recv,
595                 ptv->last_stats64.ps_recv - ptv->last_stats64.ps_drop,
596                 ptv->last_stats64.ps_drop, drop_percent);
597     }
598 }
599 
600 /**
601  * \brief This function passes off to link type decoders.
602  *
603  * DecodePcap decodes packets from libpcap and passes
604  * them off to the proper link type decoder.
605  *
606  * \param t pointer to ThreadVars
607  * \param p pointer to the current packet
608  * \param data pointer that gets cast into PcapThreadVars for ptv
609  */
DecodePcap(ThreadVars * tv,Packet * p,void * data)610 static TmEcode DecodePcap(ThreadVars *tv, Packet *p, void *data)
611 {
612     SCEnter();
613     DecodeThreadVars *dtv = (DecodeThreadVars *)data;
614 
615     BUG_ON(PKT_IS_PSEUDOPKT(p));
616 
617     /* update counters */
618     DecodeUpdatePacketCounters(tv, dtv, p);
619 
620     DecodeLinkLayer(tv, dtv, p->datalink, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
621 
622     PacketDecodeFinalize(tv, dtv, p);
623 
624     SCReturnInt(TM_ECODE_OK);
625 }
626 
DecodePcapThreadInit(ThreadVars * tv,const void * initdata,void ** data)627 static TmEcode DecodePcapThreadInit(ThreadVars *tv, const void *initdata, void **data)
628 {
629     SCEnter();
630 
631     DecodeThreadVars *dtv = DecodeThreadVarsAlloc(tv);
632     if (dtv == NULL)
633         SCReturnInt(TM_ECODE_FAILED);
634 
635     DecodeRegisterPerfCounters(dtv, tv);
636 
637     *data = (void *)dtv;
638 
639     SCReturnInt(TM_ECODE_OK);
640 }
641 
DecodePcapThreadDeinit(ThreadVars * tv,void * data)642 static TmEcode DecodePcapThreadDeinit(ThreadVars *tv, void *data)
643 {
644     if (data != NULL)
645         DecodeThreadVarsFree(tv, data);
646     SCReturnInt(TM_ECODE_OK);
647 }
648 
PcapTranslateIPToDevice(char * pcap_dev,size_t len)649 void PcapTranslateIPToDevice(char *pcap_dev, size_t len)
650 {
651     char errbuf[PCAP_ERRBUF_SIZE];
652     pcap_if_t *alldevsp = NULL;
653 
654     struct addrinfo ai_hints;
655     struct addrinfo *ai_list = NULL;
656 
657     memset(&ai_hints, 0, sizeof(ai_hints));
658     ai_hints.ai_family = AF_UNSPEC;
659     ai_hints.ai_flags = AI_NUMERICHOST;
660 
661     /* try to translate IP */
662     if (getaddrinfo(pcap_dev, NULL, &ai_hints, &ai_list) != 0) {
663         return;
664     }
665 
666     if (pcap_findalldevs(&alldevsp, errbuf)) {
667         freeaddrinfo(ai_list);
668         return;
669     }
670 
671     for (pcap_if_t *devsp = alldevsp; devsp ; devsp = devsp->next) {
672         for (pcap_addr_t *ip = devsp->addresses; ip ; ip = ip->next) {
673 
674             if (ai_list->ai_family != ip->addr->sa_family) {
675                 continue;
676             }
677 
678             if (ip->addr->sa_family == AF_INET) {
679                 if (memcmp(&((struct sockaddr_in*)ai_list->ai_addr)->sin_addr,
680                             &((struct sockaddr_in*)ip->addr)->sin_addr,
681                             sizeof(struct in_addr)))
682                 {
683                     continue;
684                 }
685             } else if (ip->addr->sa_family == AF_INET6) {
686                 if (memcmp(&((struct sockaddr_in6*)ai_list->ai_addr)->sin6_addr,
687                             &((struct sockaddr_in6*)ip->addr)->sin6_addr,
688                             sizeof(struct in6_addr)))
689                 {
690                     continue;
691                 }
692             } else {
693                 continue;
694             }
695 
696             freeaddrinfo(ai_list);
697 
698             memset(pcap_dev, 0, len);
699             strlcpy(pcap_dev, devsp->name, len);
700 
701             pcap_freealldevs(alldevsp);
702             return;
703         }
704     }
705 
706     freeaddrinfo(ai_list);
707 
708     pcap_freealldevs(alldevsp);
709 }
710 
711 /*
712  *  unittests
713  */
714 
715 #ifdef UNITTESTS
716 #include "tests/source-pcap.c"
717 /**
718  *  \brief  Register the Unit tests for pcap source
719  */
SourcePcapRegisterTests(void)720 static void SourcePcapRegisterTests(void)
721 {
722     SourcePcapRegisterStatsTests();
723 }
724 #endif /* UNITTESTS */
725