suricata
source-pcap-file-helper.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 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 Danny Browning <danny.browning@protectwise.com>
22  *
23  * File based pcap packet acquisition support
24  */
25 
27 #include "suricata.h"
28 #include "util-datalink.h"
29 #include "util-checksum.h"
30 #include "util-profiling.h"
31 #include "source-pcap-file.h"
32 #include "util-exception-policy.h"
33 
34 extern int max_pending_packets;
36 
37 static void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt);
38 
40 {
41  if (pfv != NULL) {
42  if (pfv->pcap_handle != NULL) {
43  pcap_close(pfv->pcap_handle);
44  pfv->pcap_handle = NULL;
45  }
46  if (pfv->filename != NULL) {
47  if (pfv->shared != NULL && pfv->shared->should_delete) {
48  SCLogDebug("Deleting pcap file %s", pfv->filename);
49  if (unlink(pfv->filename) != 0) {
51  "Failed to delete %s", pfv->filename);
52  }
53  }
54  SCFree(pfv->filename);
55  pfv->filename = NULL;
56  }
57  pfv->shared = NULL;
58  SCFree(pfv);
59  }
60 }
61 
62 void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt)
63 {
64  SCEnter();
65 #ifdef DEBUG
66  if (unlikely((pcap_g.cnt + 1ULL) == g_eps_pcap_packet_loss)) {
67  SCLogNotice("skipping packet %" PRIu64, g_eps_pcap_packet_loss);
68  pcap_g.cnt++;
69  SCReturn;
70  }
71 #endif
72  PcapFileFileVars *ptv = (PcapFileFileVars *)user;
74 
75  if (unlikely(p == NULL)) {
76  SCReturn;
77  }
79 
81  p->ts.tv_sec = h->ts.tv_sec;
82  p->ts.tv_usec = h->ts.tv_usec % 1000000;
83  SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
84  p->datalink = ptv->datalink;
85  p->pcap_cnt = ++pcap_g.cnt;
86 
87  p->pcap_v.tenant_id = ptv->shared->tenant_id;
88  ptv->shared->pkts++;
89  ptv->shared->bytes += h->caplen;
90 
91  if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
92  TmqhOutputPacketpool(ptv->shared->tv, p);
94  SCReturn;
95  }
96 
97  /* We only check for checksum disable */
102  SC_ATOMIC_GET(pcap_g.invalid_checksums))) {
105  }
106  }
107 
109 
110  if (TmThreadsSlotProcessPkt(ptv->shared->tv, ptv->shared->slot, p) != TM_ECODE_OK) {
111  pcap_breakloop(ptv->pcap_handle);
113  }
114 
115  SCReturn;
116 }
117 
118 char pcap_filename[PATH_MAX] = "unknown";
119 
120 const char *PcapFileGetFilename(void)
121 {
122  return pcap_filename;
123 }
124 
125 /**
126  * \brief Main PCAP file reading Loop function
127  */
129 {
130  SCEnter();
131 
132  /* initialize all the thread's initial timestamp */
133  if (likely(ptv->first_pkt_hdr != NULL)) {
135  PcapFileCallbackLoop((char *)ptv, ptv->first_pkt_hdr,
136  (u_char *)ptv->first_pkt_data);
137  ptv->first_pkt_hdr = NULL;
138  ptv->first_pkt_data = NULL;
139  }
140 
141  int packet_q_len = 64;
142  TmEcode loop_result = TM_ECODE_OK;
144 
145  while (loop_result == TM_ECODE_OK) {
148  }
149 
150  /* make sure we have at least one packet in the packet pool, to prevent
151  * us from alloc'ing packets at line rate */
152  PacketPoolWait();
153 
154  /* Right now we just support reading packets one at a time. */
155  int r = pcap_dispatch(ptv->pcap_handle, packet_q_len,
156  (pcap_handler)PcapFileCallbackLoop, (u_char *)ptv);
157  if (unlikely(r == -1)) {
158  SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s for %s",
159  r, pcap_geterr(ptv->pcap_handle), ptv->filename);
160  if (ptv->shared->cb_result == TM_ECODE_FAILED) {
162  }
163  loop_result = TM_ECODE_DONE;
164  } else if (unlikely(r == 0)) {
165  SCLogInfo("pcap file %s end of file reached (pcap err code %" PRId32 ")",
166  ptv->filename, r);
167  ptv->shared->files++;
168  loop_result = TM_ECODE_DONE;
169  } else if (ptv->shared->cb_result == TM_ECODE_FAILED) {
171  "Pcap callback PcapFileCallbackLoop failed for %s", ptv->filename);
172  loop_result = TM_ECODE_FAILED;
173  }
174  StatsSyncCountersIfSignalled(ptv->shared->tv);
175  }
176 
177  SCReturnInt(loop_result);
178 }
179 
180 /** \internal
181  * \brief get the timestamp of the first packet and rewind
182  * \param pfv pcap file variables for storing the timestamp
183  * \retval bool true on success, false on error
184  */
185 static bool PeekFirstPacketTimestamp(PcapFileFileVars *pfv)
186 {
187  int r = pcap_next_ex(pfv->pcap_handle, &pfv->first_pkt_hdr, &pfv->first_pkt_data);
188  if (r <= 0 || pfv->first_pkt_hdr == NULL) {
190  "failed to get first packet timestamp. pcap_next_ex(): %d", r);
191  return false;
192  }
193  /* timestamp in pfv->first_pkt_hdr may not be 'struct timeval' so
194  * do a manual copy of the members. */
195  pfv->first_pkt_ts.tv_sec = pfv->first_pkt_hdr->ts.tv_sec;
196  pfv->first_pkt_ts.tv_usec = pfv->first_pkt_hdr->ts.tv_usec;
197  return true;
198 }
199 
201 {
202  char errbuf[PCAP_ERRBUF_SIZE] = "";
203 
204  if(unlikely(pfv->filename == NULL)) {
205  SCLogError(SC_ERR_INVALID_ARGUMENT, "Filename was null");
207  }
208 
209  pfv->pcap_handle = pcap_open_offline(pfv->filename, errbuf);
210  if (pfv->pcap_handle == NULL) {
211  SCLogError(SC_ERR_FOPEN, "%s", errbuf);
213  }
214 
215  if (pfv->shared != NULL && pfv->shared->bpf_string != NULL) {
216  SCLogInfo("using bpf-filter \"%s\"", pfv->shared->bpf_string);
217 
218  if (pcap_compile(pfv->pcap_handle, &pfv->filter, pfv->shared->bpf_string, 1, 0) < 0) {
219  SCLogError(SC_ERR_BPF, "bpf compilation error %s for %s",
220  pcap_geterr(pfv->pcap_handle), pfv->filename);
222  }
223 
224  if (pcap_setfilter(pfv->pcap_handle, &pfv->filter) < 0) {
225  SCLogError(SC_ERR_BPF,"could not set bpf filter %s for %s",
226  pcap_geterr(pfv->pcap_handle), pfv->filename);
227  pcap_freecode(&pfv->filter);
229  }
230  pcap_freecode(&pfv->filter);
231  }
232 
233  pfv->datalink = pcap_datalink(pfv->pcap_handle);
234  SCLogDebug("datalink %" PRId32 "", pfv->datalink);
236 
237  if (!PeekFirstPacketTimestamp(pfv))
239 
240  DecoderFunc UnusedFnPtr;
241  TmEcode validated = ValidateLinkType(pfv->datalink, &UnusedFnPtr);
242  SCReturnInt(validated);
243 }
244 
245 TmEcode ValidateLinkType(int datalink, DecoderFunc *DecoderFn)
246 {
247  switch (datalink) {
248  case LINKTYPE_LINUX_SLL:
249  *DecoderFn = DecodeSll;
250  break;
251  case LINKTYPE_ETHERNET:
252  *DecoderFn = DecodeEthernet;
253  break;
254  case LINKTYPE_PPP:
255  *DecoderFn = DecodePPP;
256  break;
257  case LINKTYPE_IPV4:
258  case LINKTYPE_RAW:
259  case LINKTYPE_RAW2:
261  *DecoderFn = DecodeRaw;
262  break;
263  case LINKTYPE_NULL:
264  *DecoderFn = DecodeNull;
265  break;
266  case LINKTYPE_CISCO_HDLC:
267  *DecoderFn = DecodeCHDLC;
268  break;
269 
270  default:
272  "datalink type %"PRId32" not (yet) supported in module PcapFile.",
273  datalink);
275  }
276 
278 }
PcapFileSharedVars_::slot
TmSlot * slot
Definition: source-pcap-file-helper.h:51
PcapFileDispatch
TmEcode PcapFileDispatch(PcapFileFileVars *ptv)
Main PCAP file reading Loop function.
Definition: source-pcap-file-helper.c:128
PcapFileFileVars_::filename
char * filename
Definition: source-pcap-file-helper.h:70
max_pending_packets
int max_pending_packets
Definition: suricata.c:175
PcapFileGlobalVars_
Definition: source-pcap-file-helper.h:30
PcapFileFileVars_::first_pkt_data
const u_char * first_pkt_data
Definition: source-pcap-file-helper.h:80
PcapFileFileVars_::datalink
int datalink
Definition: source-pcap-file-helper.h:73
DecodePPP
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ppp.c:44
PacketCopyData
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:292
source-pcap-file.h
ValidateLinkType
TmEcode ValidateLinkType(int datalink, DecoderFunc *DecoderFn)
Definition: source-pcap-file-helper.c:245
PcapFileFileVars_::shared
PcapFileSharedVars * shared
Definition: source-pcap-file-helper.h:76
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:588
util-checksum.h
TM_ECODE_DONE
@ TM_ECODE_DONE
Definition: tm-threads-common.h:84
Packet_::flags
uint32_t flags
Definition: decode.h:460
PcapFileSharedVars_::should_delete
bool should_delete
Definition: source-pcap-file-helper.h:48
SC_ERR_PCAP_FILE_DELETE_FAILED
@ SC_ERR_PCAP_FILE_DELETE_FAILED
Definition: util-error.h:226
DecoderFunc
int(* DecoderFunc)(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode.h:874
LINKTYPE_LINUX_SLL
#define LINKTYPE_LINUX_SLL
Definition: decode.h:966
SURICATA_STOP
#define SURICATA_STOP
Definition: suricata.h:89
TmThreadsInitThreadsTimestamp
void TmThreadsInitThreadsTimestamp(const struct timeval *ts)
Definition: tm-threads.c:2205
PcapFileSharedVars_::cb_result
int cb_result
Definition: source-pcap-file-helper.h:62
DecodeCHDLC
int DecodeCHDLC(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-chdlc.c:42
StatsSyncCountersIfSignalled
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:140
CHECKSUM_VALIDATION_DISABLE
@ CHECKSUM_VALIDATION_DISABLE
Definition: decode.h:46
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:357
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:83
SC_ERR_PCAP_OPEN_OFFLINE
@ SC_ERR_PCAP_OPEN_OFFLINE
Definition: util-error.h:56
ChecksumAutoModeCheck
int ChecksumAutoModeCheck(uint64_t thread_count, uint64_t iface_count, uint64_t iface_fail)
Check if the number of invalid checksums indicate checksum offloading in place.
Definition: util-checksum.c:69
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:82
LINKTYPE_NULL
#define LINKTYPE_NULL
Definition: decode.h:964
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
Packet_::datalink
int datalink
Definition: decode.h:601
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1055
DecodeNull
int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-null.c:52
CHECKSUM_VALIDATION_AUTO
@ CHECKSUM_VALIDATION_AUTO
Definition: decode.h:48
PcapFileGlobalVars_::cnt
uint64_t cnt
Definition: source-pcap-file-helper.h:31
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:54
LINKTYPE_IPV4
#define LINKTYPE_IPV4
Definition: decode.h:972
util-exception-policy.h
TMM_RECEIVEPCAPFILE
@ TMM_RECEIVEPCAPFILE
Definition: tm-threads-common.h:39
PcapFileGlobalVars_::checksum_mode
ChecksumValidationMode checksum_mode
Definition: source-pcap-file-helper.h:33
Packet_::pcap_v
PcapPacketVars pcap_v
Definition: decode.h:505
SCEnter
#define SCEnter(...)
Definition: util-debug.h:298
InitPcapFile
TmEcode InitPcapFile(PcapFileFileVars *pfv)
Definition: source-pcap-file-helper.c:200
LINKTYPE_GRE_OVER_IP
#define LINKTYPE_GRE_OVER_IP
Definition: decode.h:973
LINKTYPE_PPP
#define LINKTYPE_PPP
Definition: decode.h:967
SC_ERR_INVALID_ARGUMENT
@ SC_ERR_INVALID_ARGUMENT
Definition: util-error.h:43
util-profiling.h
PacketPoolWait
void PacketPoolWait(void)
Definition: tmqh-packetpool.c:69
SCReturn
#define SCReturn
Definition: util-debug.h:300
SC_ERR_FOPEN
@ SC_ERR_FOPEN
Definition: util-error.h:74
PACKET_PROFILING_TMM_END
#define PACKET_PROFILING_TMM_END(p, id)
Definition: util-profiling.h:159
source-pcap-file-helper.h
Packet_
Definition: decode.h:425
PcapPacketVars_::tenant_id
uint32_t tenant_id
Definition: source-pcap.h:37
PKT_IGNORE_CHECKSUM
#define PKT_IGNORE_CHECKSUM
Definition: decode.h:1012
PcapFileFileVars_
Definition: source-pcap-file-helper.h:69
TmEcode
TmEcode
Definition: tm-threads-common.h:81
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:215
LINKTYPE_RAW
#define LINKTYPE_RAW
Definition: decode.h:968
PcapFileSharedVars_::bpf_string
char * bpf_string
Definition: source-pcap-file-helper.h:42
Packet_::ts
struct timeval ts
Definition: decode.h:468
pcap_filename
char pcap_filename[PATH_MAX]
Definition: source-pcap-file-helper.c:118
SC_ERR_PCAP_DISPATCH
@ SC_ERR_PCAP_DISPATCH
Definition: util-error.h:50
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:255
DecodeSll
int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-sll.c:41
PcapFileSharedVars_::tenant_id
uint32_t tenant_id
Definition: source-pcap-file-helper.h:44
SC_ERR_BPF
@ SC_ERR_BPF
Definition: util-error.h:157
SC_ERR_UNIMPLEMENTED
@ SC_ERR_UNIMPLEMENTED
Definition: util-error.h:118
PcapFileFileVars_::first_pkt_ts
struct timeval first_pkt_ts
Definition: source-pcap-file-helper.h:82
PACKET_PROFILING_TMM_START
#define PACKET_PROFILING_TMM_START(p, id)
Definition: util-profiling.h:151
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:242
SCFree
#define SCFree(p)
Definition: util-mem.h:61
PcapFileFileVars_::pcap_handle
pcap_t * pcap_handle
Definition: source-pcap-file-helper.h:71
LINKTYPE_RAW2
#define LINKTYPE_RAW2
Definition: decode.h:971
LINKTYPE_CISCO_HDLC
#define LINKTYPE_CISCO_HDLC
Definition: decode.h:974
PcapFileGetFilename
const char * PcapFileGetFilename(void)
Definition: source-pcap-file-helper.c:120
suricata.h
DecodeRaw
int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-raw.c:42
PcapFileFileVars_::first_pkt_hdr
struct pcap_pkthdr * first_pkt_hdr
Definition: source-pcap-file-helper.h:81
pcap_g
PcapFileGlobalVars pcap_g
Definition: source-pcap-file.c:36
PcapFileFileVars_::filter
struct bpf_program filter
Definition: source-pcap-file-helper.h:74
likely
#define likely(expr)
Definition: util-optimize.h:32
PcapFileSharedVars_::bytes
uint64_t bytes
Definition: source-pcap-file-helper.h:55
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:376
CleanupPcapFileFileVars
void CleanupPcapFileFileVars(PcapFileFileVars *pfv)
Definition: source-pcap-file-helper.c:39
PcapFileSharedVars_::tv
ThreadVars * tv
Definition: source-pcap-file-helper.h:50
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:230
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:302
PacketGetFromQueueOrAlloc
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition: decode.c:208
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:42
PcapFileSharedVars_::pkts
uint64_t pkts
Definition: source-pcap-file-helper.h:54
LINKTYPE_ETHERNET
#define LINKTYPE_ETHERNET
Definition: decode.h:965
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:161