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 "util-checksum.h"
28 #include "util-profiling.h"
29 #include "source-pcap-file.h"
30 
31 extern int max_pending_packets;
33 
34 static void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt);
35 
37 {
38  if (pfv != NULL) {
39  if (pfv->pcap_handle != NULL) {
40  pcap_close(pfv->pcap_handle);
41  pfv->pcap_handle = NULL;
42  }
43  if (pfv->filename != NULL) {
44  if (pfv->shared != NULL && pfv->shared->should_delete) {
45  SCLogDebug("Deleting pcap file %s", pfv->filename);
46  if (unlink(pfv->filename) != 0) {
48  "Failed to delete %s", pfv->filename);
49  }
50  }
51  SCFree(pfv->filename);
52  pfv->filename = NULL;
53  }
54  pfv->shared = NULL;
55  SCFree(pfv);
56  }
57 }
58 
59 void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt)
60 {
61  SCEnter();
62 
63  PcapFileFileVars *ptv = (PcapFileFileVars *)user;
65 
66  if (unlikely(p == NULL)) {
67  SCReturn;
68  }
70 
72  p->ts.tv_sec = h->ts.tv_sec;
73  p->ts.tv_usec = h->ts.tv_usec;
74  SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
75  p->datalink = ptv->datalink;
76  p->pcap_cnt = ++pcap_g.cnt;
77 
78  p->pcap_v.tenant_id = ptv->shared->tenant_id;
79  ptv->shared->pkts++;
80  ptv->shared->bytes += h->caplen;
81 
82  if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
83  TmqhOutputPacketpool(ptv->shared->tv, p);
85  SCReturn;
86  }
87 
88  /* We only check for checksum disable */
93  SC_ATOMIC_GET(pcap_g.invalid_checksums))) {
96  }
97  }
98 
100 
101  if (TmThreadsSlotProcessPkt(ptv->shared->tv, ptv->shared->slot, p) != TM_ECODE_OK) {
102  pcap_breakloop(ptv->pcap_handle);
104  }
105 
106  SCReturn;
107 }
108 
109 char pcap_filename[PATH_MAX] = "unknown";
110 
111 const char *PcapFileGetFilename(void)
112 {
113  return pcap_filename;
114 }
115 
116 /**
117  * \brief Main PCAP file reading Loop function
118  */
120 {
121  SCEnter();
122 
123  /* initialize all the thread's initial timestamp */
124  if (likely(ptv->first_pkt_hdr != NULL)) {
126  PcapFileCallbackLoop((char *)ptv, ptv->first_pkt_hdr,
127  (u_char *)ptv->first_pkt_data);
128  ptv->first_pkt_hdr = NULL;
129  ptv->first_pkt_data = NULL;
130  }
131 
132  int packet_q_len = 64;
133  TmEcode loop_result = TM_ECODE_OK;
135 
136  while (loop_result == TM_ECODE_OK) {
139  }
140 
141  /* make sure we have at least one packet in the packet pool, to prevent
142  * us from alloc'ing packets at line rate */
143  PacketPoolWait();
144 
145  /* Right now we just support reading packets one at a time. */
146  int r = pcap_dispatch(ptv->pcap_handle, packet_q_len,
147  (pcap_handler)PcapFileCallbackLoop, (u_char *)ptv);
148  if (unlikely(r == -1)) {
149  SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s for %s",
150  r, pcap_geterr(ptv->pcap_handle), ptv->filename);
151  if (ptv->shared->cb_result == TM_ECODE_FAILED) {
153  }
154  loop_result = TM_ECODE_DONE;
155  } else if (unlikely(r == 0)) {
156  SCLogInfo("pcap file %s end of file reached (pcap err code %" PRId32 ")",
157  ptv->filename, r);
158  ptv->shared->files++;
159  loop_result = TM_ECODE_DONE;
160  } else if (ptv->shared->cb_result == TM_ECODE_FAILED) {
162  "Pcap callback PcapFileCallbackLoop failed for %s", ptv->filename);
163  loop_result = TM_ECODE_FAILED;
164  }
165  StatsSyncCountersIfSignalled(ptv->shared->tv);
166  }
167 
168  SCReturnInt(loop_result);
169 }
170 
171 /** \internal
172  * \brief get the timestamp of the first packet and rewind
173  * \param pfv pcap file variables for storing the timestamp
174  * \retval bool true on success, false on error
175  */
176 static bool PeekFirstPacketTimestamp(PcapFileFileVars *pfv)
177 {
178  int r = pcap_next_ex(pfv->pcap_handle, &pfv->first_pkt_hdr, &pfv->first_pkt_data);
179  if (r <= 0 || pfv->first_pkt_hdr == NULL) {
181  "failed to get first packet timestamp. pcap_next_ex(): %d", r);
182  return false;
183  }
184  /* timestamp in pfv->first_pkt_hdr may not be 'struct timeval' so
185  * do a manual copy of the members. */
186  pfv->first_pkt_ts.tv_sec = pfv->first_pkt_hdr->ts.tv_sec;
187  pfv->first_pkt_ts.tv_usec = pfv->first_pkt_hdr->ts.tv_usec;
188  return true;
189 }
190 
192 {
193  char errbuf[PCAP_ERRBUF_SIZE] = "";
194 
195  if(unlikely(pfv->filename == NULL)) {
196  SCLogError(SC_ERR_INVALID_ARGUMENT, "Filename was null");
198  }
199 
200  pfv->pcap_handle = pcap_open_offline(pfv->filename, errbuf);
201  if (pfv->pcap_handle == NULL) {
202  SCLogError(SC_ERR_FOPEN, "%s", errbuf);
204  }
205 
206  if (pfv->shared != NULL && pfv->shared->bpf_string != NULL) {
207  SCLogInfo("using bpf-filter \"%s\"", pfv->shared->bpf_string);
208 
209  if (pcap_compile(pfv->pcap_handle, &pfv->filter, pfv->shared->bpf_string, 1, 0) < 0) {
210  SCLogError(SC_ERR_BPF, "bpf compilation error %s for %s",
211  pcap_geterr(pfv->pcap_handle), pfv->filename);
213  }
214 
215  if (pcap_setfilter(pfv->pcap_handle, &pfv->filter) < 0) {
216  SCLogError(SC_ERR_BPF,"could not set bpf filter %s for %s",
217  pcap_geterr(pfv->pcap_handle), pfv->filename);
218  pcap_freecode(&pfv->filter);
220  }
221  pcap_freecode(&pfv->filter);
222  }
223 
224  pfv->datalink = pcap_datalink(pfv->pcap_handle);
225  SCLogDebug("datalink %" PRId32 "", pfv->datalink);
226 
227  if (!PeekFirstPacketTimestamp(pfv))
229 
230  DecoderFunc UnusedFnPtr;
231  TmEcode validated = ValidateLinkType(pfv->datalink, &UnusedFnPtr);
232  SCReturnInt(validated);
233 }
234 
235 TmEcode ValidateLinkType(int datalink, DecoderFunc *DecoderFn)
236 {
237  switch (datalink) {
238  case LINKTYPE_LINUX_SLL:
239  *DecoderFn = DecodeSll;
240  break;
241  case LINKTYPE_ETHERNET:
242  *DecoderFn = DecodeEthernet;
243  break;
244  case LINKTYPE_PPP:
245  *DecoderFn = DecodePPP;
246  break;
247  case LINKTYPE_IPV4:
248  case LINKTYPE_RAW:
249  case LINKTYPE_RAW2:
251  *DecoderFn = DecodeRaw;
252  break;
253  case LINKTYPE_NULL:
254  *DecoderFn = DecodeNull;
255  break;
256  case LINKTYPE_CISCO_HDLC:
257  *DecoderFn = DecodeCHDLC;
258  break;
259 
260  default:
262  "datalink type %"PRId32" not (yet) supported in module PcapFile.",
263  datalink);
265  }
266 
268 }
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:119
PcapFileFileVars_::filename
char * filename
Definition: source-pcap-file-helper.h:70
max_pending_packets
int max_pending_packets
Definition: suricata.c:212
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:43
PacketCopyData
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:262
source-pcap-file.h
ValidateLinkType
TmEcode ValidateLinkType(int datalink, DecoderFunc *DecoderFn)
Definition: source-pcap-file-helper.c:235
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:298
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:570
util-checksum.h
TM_ECODE_DONE
@ TM_ECODE_DONE
Definition: tm-threads-common.h:82
Packet_::flags
uint32_t flags
Definition: decode.h:449
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:974
LINKTYPE_LINUX_SLL
#define LINKTYPE_LINUX_SLL
Definition: decode.h:1089
SURICATA_STOP
#define SURICATA_STOP
Definition: suricata.h:90
TmThreadsInitThreadsTimestamp
void TmThreadsInitThreadsTimestamp(const struct timeval *ts)
Definition: tm-threads.c:2208
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:41
StatsSyncCountersIfSignalled
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:137
CHECKSUM_VALIDATION_DISABLE
@ CHECKSUM_VALIDATION_DISABLE
Definition: decode.h:43
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:375
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
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:70
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:80
LINKTYPE_NULL
#define LINKTYPE_NULL
Definition: decode.h:1087
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
Packet_::datalink
int datalink
Definition: decode.h:583
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1150
DecodeNull
int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-null.c:48
CHECKSUM_VALIDATION_AUTO
@ CHECKSUM_VALIDATION_AUTO
Definition: decode.h:45
PcapFileGlobalVars_::cnt
uint64_t cnt
Definition: source-pcap-file-helper.h:31
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:51
LINKTYPE_IPV4
#define LINKTYPE_IPV4
Definition: decode.h:1095
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:489
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
InitPcapFile
TmEcode InitPcapFile(PcapFileFileVars *pfv)
Definition: source-pcap-file-helper.c:191
LINKTYPE_GRE_OVER_IP
#define LINKTYPE_GRE_OVER_IP
Definition: decode.h:1096
LINKTYPE_PPP
#define LINKTYPE_PPP
Definition: decode.h:1090
SC_ERR_INVALID_ARGUMENT
@ SC_ERR_INVALID_ARGUMENT
Definition: util-error.h:43
util-profiling.h
PacketPoolWait
void PacketPoolWait(void)
Definition: tmqh-packetpool.c:84
SCReturn
#define SCReturn
Definition: util-debug.h:302
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:158
source-pcap-file-helper.h
Packet_
Definition: decode.h:414
PcapPacketVars_::tenant_id
uint32_t tenant_id
Definition: source-pcap.h:37
PKT_IGNORE_CHECKSUM
#define PKT_IGNORE_CHECKSUM
Definition: decode.h:1118
PcapFileFileVars_
Definition: source-pcap-file-helper.h:69
TmEcode
TmEcode
Definition: tm-threads-common.h:79
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:217
LINKTYPE_RAW
#define LINKTYPE_RAW
Definition: decode.h:1091
PcapFileSharedVars_::bpf_string
char * bpf_string
Definition: source-pcap-file-helper.h:42
Packet_::ts
struct timeval ts
Definition: decode.h:457
pcap_filename
char pcap_filename[PATH_MAX]
Definition: source-pcap-file-helper.c:109
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:257
DecodeSll
int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-sll.c:39
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:150
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:244
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:1094
LINKTYPE_CISCO_HDLC
#define LINKTYPE_CISCO_HDLC
Definition: decode.h:1097
PcapFileGetFilename
const char * PcapFileGetFilename(void)
Definition: source-pcap-file-helper.c:111
DecodeRaw
int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-raw.c:46
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:34
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:36
PcapFileSharedVars_::tv
ThreadVars * tv
Definition: source-pcap-file-helper.h:50
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
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:180
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:41
PcapFileSharedVars_::pkts
uint64_t pkts
Definition: source-pcap-file-helper.h:54
LINKTYPE_ETHERNET
#define LINKTYPE_ETHERNET
Definition: decode.h:1088
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:198